<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[40583] trunk/src: TinyMCE: update to 4.6.0.</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/40583">40583</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/40583","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>azaozz</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2017-05-08 05:31:08 +0000 (Mon, 08 May 2017)</dd>
</dl>
<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>TinyMCE: update to 4.6.0. Has many new features and bug fixes, changelog: https://www.tinymce.com/docs/changelog/#version460-may42017.
Fixes <a href="https://core.trac.wordpress.org/ticket/40690">#40690</a>.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpadminincludesupdatecorephp">trunk/src/wp-admin/includes/update-core.php</a></li>
<li><a href="#trunksrcwpincludesclasswpeditorphp">trunk/src/wp-includes/class-wp-editor.php</a></li>
<li><a href="#trunksrcwpincludesgeneraltemplatephp">trunk/src/wp-includes/general-template.php</a></li>
<li><a href="#trunksrcwpincludesjstinymcelicensetxt">trunk/src/wp-includes/js/tinymce/license.txt</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginscharmappluginjs">trunk/src/wp-includes/js/tinymce/plugins/charmap/plugin.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginscharmappluginminjs">trunk/src/wp-includes/js/tinymce/plugins/charmap/plugin.min.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginscolorpickerpluginjs">trunk/src/wp-includes/js/tinymce/plugins/colorpicker/plugin.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginscolorpickerpluginminjs">trunk/src/wp-includes/js/tinymce/plugins/colorpicker/plugin.min.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginscompat3xpluginjs">trunk/src/wp-includes/js/tinymce/plugins/compat3x/plugin.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginscompat3xpluginminjs">trunk/src/wp-includes/js/tinymce/plugins/compat3x/plugin.min.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginsdirectionalitypluginjs">trunk/src/wp-includes/js/tinymce/plugins/directionality/plugin.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginsdirectionalitypluginminjs">trunk/src/wp-includes/js/tinymce/plugins/directionality/plugin.min.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginsfullscreenpluginjs">trunk/src/wp-includes/js/tinymce/plugins/fullscreen/plugin.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginsfullscreenpluginminjs">trunk/src/wp-includes/js/tinymce/plugins/fullscreen/plugin.min.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginshrpluginjs">trunk/src/wp-includes/js/tinymce/plugins/hr/plugin.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginshrpluginminjs">trunk/src/wp-includes/js/tinymce/plugins/hr/plugin.min.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginsimagepluginjs">trunk/src/wp-includes/js/tinymce/plugins/image/plugin.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginsimagepluginminjs">trunk/src/wp-includes/js/tinymce/plugins/image/plugin.min.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginslistspluginjs">trunk/src/wp-includes/js/tinymce/plugins/lists/plugin.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginslistspluginminjs">trunk/src/wp-includes/js/tinymce/plugins/lists/plugin.min.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginsmediapluginjs">trunk/src/wp-includes/js/tinymce/plugins/media/plugin.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginsmediapluginminjs">trunk/src/wp-includes/js/tinymce/plugins/media/plugin.min.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginspastepluginjs">trunk/src/wp-includes/js/tinymce/plugins/paste/plugin.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginspastepluginminjs">trunk/src/wp-includes/js/tinymce/plugins/paste/plugin.min.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginstabfocuspluginjs">trunk/src/wp-includes/js/tinymce/plugins/tabfocus/plugin.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginstabfocuspluginminjs">trunk/src/wp-includes/js/tinymce/plugins/tabfocus/plugin.min.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginstextcolorpluginjs">trunk/src/wp-includes/js/tinymce/plugins/textcolor/plugin.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginstextcolorpluginminjs">trunk/src/wp-includes/js/tinymce/plugins/textcolor/plugin.min.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginswordpresspluginjs">trunk/src/wp-includes/js/tinymce/plugins/wordpress/plugin.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcepluginswpviewpluginjs">trunk/src/wp-includes/js/tinymce/plugins/wpview/plugin.js</a></li>
<li><a href="#trunksrcwpincludesjstinymceskinslightgraycontentinlinemincss">trunk/src/wp-includes/js/tinymce/skins/lightgray/content.inline.min.css</a></li>
<li><a href="#trunksrcwpincludesjstinymceskinslightgraycontentmincss">trunk/src/wp-includes/js/tinymce/skins/lightgray/content.min.css</a></li>
<li><a href="#trunksrcwpincludesjstinymceskinslightgrayskinmincss">trunk/src/wp-includes/js/tinymce/skins/lightgray/skin.min.css</a></li>
<li><a href="#trunksrcwpincludesjstinymcethemesinlitethemejs">trunk/src/wp-includes/js/tinymce/themes/inlite/theme.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcethemesinlitethememinjs">trunk/src/wp-includes/js/tinymce/themes/inlite/theme.min.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcethemesmodernthemejs">trunk/src/wp-includes/js/tinymce/themes/modern/theme.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcethemesmodernthememinjs">trunk/src/wp-includes/js/tinymce/themes/modern/theme.min.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcetiny_mce_popupjs">trunk/src/wp-includes/js/tinymce/tiny_mce_popup.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcetinymcejs">trunk/src/wp-includes/js/tinymce/tinymce.js</a></li>
<li><a href="#trunksrcwpincludesjstinymcetinymceminjs">trunk/src/wp-includes/js/tinymce/tinymce.min.js</a></li>
<li><a href="#trunksrcwpincludesjstinymceutilseditable_selectsjs">trunk/src/wp-includes/js/tinymce/utils/editable_selects.js</a></li>
<li><a href="#trunksrcwpincludesjstinymceutilsform_utilsjs">trunk/src/wp-includes/js/tinymce/utils/form_utils.js</a></li>
<li><a href="#trunksrcwpincludesjstinymceutilsmctabsjs">trunk/src/wp-includes/js/tinymce/utils/mctabs.js</a></li>
<li><a href="#trunksrcwpincludesjstinymceutilsvalidatejs">trunk/src/wp-includes/js/tinymce/utils/validate.js</a></li>
<li><a href="#trunksrcwpincludesversionphp">trunk/src/wp-includes/version.php</a></li>
</ul>
<h3>Removed Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesjstinymcepluginsmediamoxieplayerswf">trunk/src/wp-includes/js/tinymce/plugins/media/moxieplayer.swf</a></li>
<li><a href="#trunksrcwpincludesjstinymceskinslightgrayfontsreadmemd">trunk/src/wp-includes/js/tinymce/skins/lightgray/fonts/readme.md</a></li>
<li><a href="#trunksrcwpincludesjstinymceskinslightgrayfontstinymcesmalljson">trunk/src/wp-includes/js/tinymce/skins/lightgray/fonts/tinymce-small.json</a></li>
<li><a href="#trunksrcwpincludesjstinymceskinslightgrayfontstinymcejson">trunk/src/wp-includes/js/tinymce/skins/lightgray/fonts/tinymce.json</a></li>
<li><a href="#trunksrcwpincludesjstinymceskinslightgrayskinie7mincss">trunk/src/wp-includes/js/tinymce/skins/lightgray/skin.ie7.min.css</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpadminincludesupdatecorephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/update-core.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/update-core.php 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-admin/includes/update-core.php 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -705,6 +705,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'wp-includes/theme-compat/comments-popup.php',
</span><span class="cx" style="display: block; padding: 0 10px"> // 4.6
</span><span class="cx" style="display: block; padding: 0 10px"> 'wp-admin/includes/class-wp-automatic-upgrader.php', // Wrong file name, see #37628.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+// 4.8
+'wp-includes/js/tinymce/plugins/media/moxieplayer.swf',
+'wp-includes/js/tinymce/skins/lightgray/fonts/readme.md',
+'wp-includes/js/tinymce/skins/lightgray/fonts/tinymce-small.json',
+'wp-includes/js/tinymce/skins/lightgray/fonts/tinymce.json',
+'wp-includes/js/tinymce/skins/lightgray/skin.ie7.min.css',
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span></span></pre></div>
<a id="trunksrcwpincludesclasswpeditorphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/class-wp-editor.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp-editor.php 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/class-wp-editor.php 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -947,6 +947,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'cache_suffix' => 'wp-mce-' . $tinymce_version,
</span><span class="cx" style="display: block; padding: 0 10px"> 'resize' => 'vertical',
</span><span class="cx" style="display: block; padding: 0 10px"> 'menubar' => false,
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'branding' => false,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Limit the preview styles in the menu/toolbar
</span><span class="cx" style="display: block; padding: 0 10px"> 'preview_styles' => 'font-family font-size font-weight font-style text-decoration text-transform',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1039,6 +1040,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'Name' => _x( 'Name', 'Name of link anchor (TinyMCE)' ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'Anchor' => _x( 'Anchor', 'Link anchor (TinyMCE)' ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'Anchors' => _x( 'Anchors', 'Link anchors (TinyMCE)' ),
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.' =>
+ __( 'Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.' ),
+ 'Id' => _x( 'Id', 'Id for link anchor (TinyMCE)' ),
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Fullpage plugin
</span><span class="cx" style="display: block; padding: 0 10px"> 'Document properties' => __( 'Document properties' ),
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1050,6 +1054,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'Author' => __( 'Author' ),
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Media, image plugins
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'Image' => __( 'Image' ),
</ins><span class="cx" style="display: block; padding: 0 10px"> 'Insert/edit image' => array( __( 'Insert/edit image' ), 'accessM' ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'General' => __( 'General' ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'Advanced' => __( 'Advanced' ),
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1061,8 +1066,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'Style' => __( 'Style' ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'Dimensions' => __( 'Dimensions' ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'Insert image' => __( 'Insert image' ),
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'Date/time' => __( 'Date/time' ),
</ins><span class="cx" style="display: block; padding: 0 10px"> 'Insert date/time' => __( 'Insert date/time' ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'Insert/edit video' => __( 'Insert/edit video' ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'Table of Contents' => __( 'Table of Contents' ),
+ 'Insert/Edit code sample' => __( 'Insert/edit code sample' ),
+ 'Language' => __( 'Language' ),
+ 'Media' => __( 'Media' ),
+ 'Insert/edit media' => __( 'Insert/edit media' ),
</ins><span class="cx" style="display: block; padding: 0 10px"> 'Poster' => __( 'Poster' ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'Alternative source' => __( 'Alternative source' ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'Paste your embed code below:' => __( 'Paste your embed code below:' ),
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1087,10 +1097,26 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'Insert/edit link' => array( __( 'Insert/edit link' ), 'metaK' ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'Remove link' => array( __( 'Remove link' ), 'accessS' ),
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Link plugin
+ 'Link' => __( 'Link' ),
+ 'Insert link' => __( 'Insert link' ),
+ 'Insert/edit link' => __( 'Insert/edit link' ),
+ 'Target' => __( 'Target' ),
+ 'New window' => __( 'New window' ),
+ 'Text to display' => __( 'Text to display' ),
+ 'Url' => __( 'URL' ),
+ 'The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?' =>
+ __( 'The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?' ),
+ 'The URL you entered seems to be an external link. Do you want to add the required http:// prefix?' =>
+ __( 'The URL you entered seems to be an external link. Do you want to add the required http:// prefix?' ),
+
</ins><span class="cx" style="display: block; padding: 0 10px"> 'Color' => __( 'Color' ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'Custom color' => __( 'Custom color' ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'Custom...' => _x( 'Custom...', 'label for custom color' ), // no ellipsis
</span><span class="cx" style="display: block; padding: 0 10px"> 'No color' => __( 'No color' ),
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'R' => _x( 'R', 'Short for red in RGB' ),
+ 'G' => _x( 'G', 'Short for green in RGB' ),
+ 'B' => _x( 'B', 'Short for blue in RGB' ),
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Spelling, search/replace plugins
</span><span class="cx" style="display: block; padding: 0 10px"> 'Could not find the specified string.' => __( 'Could not find the specified string.' ),
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1235,16 +1261,27 @@
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Link plugin (not included):
- * Insert link
- * Target
- * New window
- * Text to display
- * The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?
- * The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?
- * Url
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /*
+ Imagetools plugin (not included):
+ 'Edit image' => __( 'Edit image' ),
+ 'Image options' => __( 'Image options' ),
+ 'Back' => __( 'Back' ),
+ 'Invert' => __( 'Invert' ),
+ 'Flip horizontally' => __( 'Flip horizontally' ),
+ 'Flip vertically' => __( 'Flip vertically' ),
+ 'Crop' => __( 'Crop' ),
+ 'Orientation' => __( 'Orientation' ),
+ 'Resize' => __( 'Resize' ),
+ 'Rotate clockwise' => __( 'Rotate clockwise' ),
+ 'Rotate counterclockwise' => __( 'Rotate counterclockwise' ),
+ 'Sharpen' => __( 'Sharpen' ),
+ 'Brightness' => __( 'Brightness' ),
+ 'Color levels' => __( 'Color levels' ),
+ 'Contrast' => __( 'Contrast' ),
+ 'Gamma' => __( 'Gamma' ),
+ 'Zoom in' => __( 'Zoom in' ),
+ 'Zoom out' => __( 'Zoom out' ),
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> return self::$translation;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1456,6 +1493,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> var init, id, $wrap;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( typeof tinymce !== 'undefined' ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( tinymce.Env.ie && tinymce.Env.ie < 11 ) {
+ tinymce.$( '.wp-editor-wrap ' ).removeClass( 'tmce-active' ).addClass( 'html-active' );
+ return;
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> for ( id in tinyMCEPreInit.mceInit ) {
</span><span class="cx" style="display: block; padding: 0 10px"> init = tinyMCEPreInit.mceInit[id];
</span><span class="cx" style="display: block; padding: 0 10px"> $wrap = tinymce.$( '#wp-' + id + '-wrap' );
</span></span></pre></div>
<a id="trunksrcwpincludesgeneraltemplatephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/general-template.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/general-template.php 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/general-template.php 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2988,7 +2988,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> if ( get_user_option( 'rich_editing' ) == 'true' || ! is_user_logged_in() ) { // default to 'true' for logged out users
</span><span class="cx" style="display: block; padding: 0 10px"> if ( $is_safari ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_rich_edit = ! wp_is_mobile() || ( preg_match( '!AppleWebKit/(\d+)!', $_SERVER['HTTP_USER_AGENT'], $match ) && intval( $match[1] ) >= 534 );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- } elseif ( $is_gecko || $is_chrome || $is_IE || $is_edge || ( $is_opera && !wp_is_mobile() ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ } elseif ( $is_IE ) {
+ $wp_rich_edit = ( strpos( $_SERVER['HTTP_USER_AGENT'], 'MSIE ' ) === false );
+ } elseif ( $is_gecko || $is_chrome || $is_edge || ( $is_opera && !wp_is_mobile() ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $wp_rich_edit = true;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcelicensetxt"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/license.txt</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/license.txt 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/license.txt 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,5 +1,5 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> Copyright (C) 1991, 1999 Free Software Foundation, Inc.
</span><span class="cx" style="display: block; padding: 0 10px"> 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -10,7 +10,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> as the successor of the GNU Library Public License, version 2, hence
</span><span class="cx" style="display: block; padding: 0 10px"> the version number 2.1.]
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Preamble
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Preamble
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> The licenses for most software are designed to take away your
</span><span class="cx" style="display: block; padding: 0 10px"> freedom to share and change it. By contrast, the GNU General Public
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -112,7 +112,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> former contains code derived from the library, whereas the latter must
</span><span class="cx" style="display: block; padding: 0 10px"> be combined with the library in order to run.
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- GNU LESSER GENERAL PUBLIC LICENSE
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ GNU LESSER GENERAL PUBLIC LICENSE
</ins><span class="cx" style="display: block; padding: 0 10px"> TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> 0. This License Agreement applies to any software library or other
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -432,7 +432,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> of all derivatives of our free software and of promoting the sharing
</span><span class="cx" style="display: block; padding: 0 10px"> and reuse of software generally.
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- NO WARRANTY
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ NO WARRANTY
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
</span><span class="cx" style="display: block; padding: 0 10px"> WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -455,7 +455,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
</span><span class="cx" style="display: block; padding: 0 10px"> DAMAGES.
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- END OF TERMS AND CONDITIONS
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ END OF TERMS AND CONDITIONS
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> How to Apply These Terms to Your New Libraries
</span><span class="cx" style="display: block; padding: 0 10px">
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginscharmappluginjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/charmap/plugin.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/charmap/plugin.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/charmap/plugin.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,466 +1,614 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+(function () {
+
+var defs = {}; // id -> {dependencies, definition, instance (possibly undefined)}
+
+// Used when there is no 'main' module.
+// The name is probably (hopefully) unique so minification removes for releases.
+var register_3795 = function (id) {
+ var module = dem(id);
+ var fragments = id.split('.');
+ var target = Function('return this;')();
+ for (var i = 0; i < fragments.length - 1; ++i) {
+ if (target[fragments[i]] === undefined)
+ target[fragments[i]] = {};
+ target = target[fragments[i]];
+ }
+ target[fragments[fragments.length - 1]] = module;
+};
+
+var instantiate = function (id) {
+ var actual = defs[id];
+ var dependencies = actual.deps;
+ var definition = actual.defn;
+ var len = dependencies.length;
+ var instances = new Array(len);
+ for (var i = 0; i < len; ++i)
+ instances[i] = dem(dependencies[i]);
+ var defResult = definition.apply(null, instances);
+ if (defResult === undefined)
+ throw 'module [' + id + '] returned undefined';
+ actual.instance = defResult;
+};
+
+var def = function (id, dependencies, definition) {
+ if (typeof id !== 'string')
+ throw 'module id must be a string';
+ else if (dependencies === undefined)
+ throw 'no dependencies for ' + id;
+ else if (definition === undefined)
+ throw 'no definition function for ' + id;
+ defs[id] = {
+ deps: dependencies,
+ defn: definition,
+ instance: undefined
+ };
+};
+
+var dem = function (id) {
+ var actual = defs[id];
+ if (actual === undefined)
+ throw 'module [' + id + '] was undefined';
+ else if (actual.instance === undefined)
+ instantiate(id);
+ return actual.instance;
+};
+
+var req = function (ids, callback) {
+ var len = ids.length;
+ var instances = new Array(len);
+ for (var i = 0; i < len; ++i)
+ instances.push(dem(ids[i]));
+ callback.apply(null, callback);
+};
+
+var ephox = {};
+
+ephox.bolt = {
+ module: {
+ api: {
+ define: def,
+ require: req,
+ demand: dem
+ }
+ }
+};
+
+var define = def;
+var require = req;
+var demand = dem;
+// this helps with minificiation when using a lot of global references
+var defineGlobal = function (id, ref) {
+ define(id, [], function () { return ref; });
+};
+/*jsc
+["tinymce.plugins.charmap.Plugin","tinymce.core.PluginManager","tinymce.core.util.Tools","global!tinymce.util.Tools.resolve"]
+jsc*/
+defineGlobal("global!tinymce.util.Tools.resolve", tinymce.util.Tools.resolve);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * plugin.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ResolveGlobal.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/*global tinymce:true */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.PluginManager',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.PluginManager');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-tinymce.PluginManager.add('charmap', function(editor) {
- var isArray = tinymce.util.Tools.isArray;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getDefaultCharMap() {
- return [
- ['160', 'no-break space'],
- ['173', 'soft hyphen'],
- ['34', 'quotation mark'],
- // finance
- ['162', 'cent sign'],
- ['8364', 'euro sign'],
- ['163', 'pound sign'],
- ['165', 'yen sign'],
- // signs
- ['169', 'copyright sign'],
- ['174', 'registered sign'],
- ['8482', 'trade mark sign'],
- ['8240', 'per mille sign'],
- ['181', 'micro sign'],
- ['183', 'middle dot'],
- ['8226', 'bullet'],
- ['8230', 'three dot leader'],
- ['8242', 'minutes / feet'],
- ['8243', 'seconds / inches'],
- ['167', 'section sign'],
- ['182', 'paragraph sign'],
- ['223', 'sharp s / ess-zed'],
- // quotations
- ['8249', 'single left-pointing angle quotation mark'],
- ['8250', 'single right-pointing angle quotation mark'],
- ['171', 'left pointing guillemet'],
- ['187', 'right pointing guillemet'],
- ['8216', 'left single quotation mark'],
- ['8217', 'right single quotation mark'],
- ['8220', 'left double quotation mark'],
- ['8221', 'right double quotation mark'],
- ['8218', 'single low-9 quotation mark'],
- ['8222', 'double low-9 quotation mark'],
- ['60', 'less-than sign'],
- ['62', 'greater-than sign'],
- ['8804', 'less-than or equal to'],
- ['8805', 'greater-than or equal to'],
- ['8211', 'en dash'],
- ['8212', 'em dash'],
- ['175', 'macron'],
- ['8254', 'overline'],
- ['164', 'currency sign'],
- ['166', 'broken bar'],
- ['168', 'diaeresis'],
- ['161', 'inverted exclamation mark'],
- ['191', 'turned question mark'],
- ['710', 'circumflex accent'],
- ['732', 'small tilde'],
- ['176', 'degree sign'],
- ['8722', 'minus sign'],
- ['177', 'plus-minus sign'],
- ['247', 'division sign'],
- ['8260', 'fraction slash'],
- ['215', 'multiplication sign'],
- ['185', 'superscript one'],
- ['178', 'superscript two'],
- ['179', 'superscript three'],
- ['188', 'fraction one quarter'],
- ['189', 'fraction one half'],
- ['190', 'fraction three quarters'],
- // math / logical
- ['402', 'function / florin'],
- ['8747', 'integral'],
- ['8721', 'n-ary sumation'],
- ['8734', 'infinity'],
- ['8730', 'square root'],
- ['8764', 'similar to'],
- ['8773', 'approximately equal to'],
- ['8776', 'almost equal to'],
- ['8800', 'not equal to'],
- ['8801', 'identical to'],
- ['8712', 'element of'],
- ['8713', 'not an element of'],
- ['8715', 'contains as member'],
- ['8719', 'n-ary product'],
- ['8743', 'logical and'],
- ['8744', 'logical or'],
- ['172', 'not sign'],
- ['8745', 'intersection'],
- ['8746', 'union'],
- ['8706', 'partial differential'],
- ['8704', 'for all'],
- ['8707', 'there exists'],
- ['8709', 'diameter'],
- ['8711', 'backward difference'],
- ['8727', 'asterisk operator'],
- ['8733', 'proportional to'],
- ['8736', 'angle'],
- // undefined
- ['180', 'acute accent'],
- ['184', 'cedilla'],
- ['170', 'feminine ordinal indicator'],
- ['186', 'masculine ordinal indicator'],
- ['8224', 'dagger'],
- ['8225', 'double dagger'],
- // alphabetical special chars
- ['192', 'A - grave'],
- ['193', 'A - acute'],
- ['194', 'A - circumflex'],
- ['195', 'A - tilde'],
- ['196', 'A - diaeresis'],
- ['197', 'A - ring above'],
- ['256', 'A - macron'],
- ['198', 'ligature AE'],
- ['199', 'C - cedilla'],
- ['200', 'E - grave'],
- ['201', 'E - acute'],
- ['202', 'E - circumflex'],
- ['203', 'E - diaeresis'],
- ['274', 'E - macron'],
- ['204', 'I - grave'],
- ['205', 'I - acute'],
- ['206', 'I - circumflex'],
- ['207', 'I - diaeresis'],
- ['298', 'I - macron'],
- ['208', 'ETH'],
- ['209', 'N - tilde'],
- ['210', 'O - grave'],
- ['211', 'O - acute'],
- ['212', 'O - circumflex'],
- ['213', 'O - tilde'],
- ['214', 'O - diaeresis'],
- ['216', 'O - slash'],
- ['332', 'O - macron'],
- ['338', 'ligature OE'],
- ['352', 'S - caron'],
- ['217', 'U - grave'],
- ['218', 'U - acute'],
- ['219', 'U - circumflex'],
- ['220', 'U - diaeresis'],
- ['362', 'U - macron'],
- ['221', 'Y - acute'],
- ['376', 'Y - diaeresis'],
- ['562', 'Y - macron'],
- ['222', 'THORN'],
- ['224', 'a - grave'],
- ['225', 'a - acute'],
- ['226', 'a - circumflex'],
- ['227', 'a - tilde'],
- ['228', 'a - diaeresis'],
- ['229', 'a - ring above'],
- ['257', 'a - macron'],
- ['230', 'ligature ae'],
- ['231', 'c - cedilla'],
- ['232', 'e - grave'],
- ['233', 'e - acute'],
- ['234', 'e - circumflex'],
- ['235', 'e - diaeresis'],
- ['275', 'e - macron'],
- ['236', 'i - grave'],
- ['237', 'i - acute'],
- ['238', 'i - circumflex'],
- ['239', 'i - diaeresis'],
- ['299', 'i - macron'],
- ['240', 'eth'],
- ['241', 'n - tilde'],
- ['242', 'o - grave'],
- ['243', 'o - acute'],
- ['244', 'o - circumflex'],
- ['245', 'o - tilde'],
- ['246', 'o - diaeresis'],
- ['248', 'o slash'],
- ['333', 'o macron'],
- ['339', 'ligature oe'],
- ['353', 's - caron'],
- ['249', 'u - grave'],
- ['250', 'u - acute'],
- ['251', 'u - circumflex'],
- ['252', 'u - diaeresis'],
- ['363', 'u - macron'],
- ['253', 'y - acute'],
- ['254', 'thorn'],
- ['255', 'y - diaeresis'],
- ['563', 'y - macron'],
- ['913', 'Alpha'],
- ['914', 'Beta'],
- ['915', 'Gamma'],
- ['916', 'Delta'],
- ['917', 'Epsilon'],
- ['918', 'Zeta'],
- ['919', 'Eta'],
- ['920', 'Theta'],
- ['921', 'Iota'],
- ['922', 'Kappa'],
- ['923', 'Lambda'],
- ['924', 'Mu'],
- ['925', 'Nu'],
- ['926', 'Xi'],
- ['927', 'Omicron'],
- ['928', 'Pi'],
- ['929', 'Rho'],
- ['931', 'Sigma'],
- ['932', 'Tau'],
- ['933', 'Upsilon'],
- ['934', 'Phi'],
- ['935', 'Chi'],
- ['936', 'Psi'],
- ['937', 'Omega'],
- ['945', 'alpha'],
- ['946', 'beta'],
- ['947', 'gamma'],
- ['948', 'delta'],
- ['949', 'epsilon'],
- ['950', 'zeta'],
- ['951', 'eta'],
- ['952', 'theta'],
- ['953', 'iota'],
- ['954', 'kappa'],
- ['955', 'lambda'],
- ['956', 'mu'],
- ['957', 'nu'],
- ['958', 'xi'],
- ['959', 'omicron'],
- ['960', 'pi'],
- ['961', 'rho'],
- ['962', 'final sigma'],
- ['963', 'sigma'],
- ['964', 'tau'],
- ['965', 'upsilon'],
- ['966', 'phi'],
- ['967', 'chi'],
- ['968', 'psi'],
- ['969', 'omega'],
- // symbols
- ['8501', 'alef symbol'],
- ['982', 'pi symbol'],
- ['8476', 'real part symbol'],
- ['978', 'upsilon - hook symbol'],
- ['8472', 'Weierstrass p'],
- ['8465', 'imaginary part'],
- // arrows
- ['8592', 'leftwards arrow'],
- ['8593', 'upwards arrow'],
- ['8594', 'rightwards arrow'],
- ['8595', 'downwards arrow'],
- ['8596', 'left right arrow'],
- ['8629', 'carriage return'],
- ['8656', 'leftwards double arrow'],
- ['8657', 'upwards double arrow'],
- ['8658', 'rightwards double arrow'],
- ['8659', 'downwards double arrow'],
- ['8660', 'left right double arrow'],
- ['8756', 'therefore'],
- ['8834', 'subset of'],
- ['8835', 'superset of'],
- ['8836', 'not a subset of'],
- ['8838', 'subset of or equal to'],
- ['8839', 'superset of or equal to'],
- ['8853', 'circled plus'],
- ['8855', 'circled times'],
- ['8869', 'perpendicular'],
- ['8901', 'dot operator'],
- ['8968', 'left ceiling'],
- ['8969', 'right ceiling'],
- ['8970', 'left floor'],
- ['8971', 'right floor'],
- ['9001', 'left-pointing angle bracket'],
- ['9002', 'right-pointing angle bracket'],
- ['9674', 'lozenge'],
- ['9824', 'black spade suit'],
- ['9827', 'black club suit'],
- ['9829', 'black heart suit'],
- ['9830', 'black diamond suit'],
- ['8194', 'en space'],
- ['8195', 'em space'],
- ['8201', 'thin space'],
- ['8204', 'zero width non-joiner'],
- ['8205', 'zero width joiner'],
- ['8206', 'left-to-right mark'],
- ['8207', 'right-to-left mark']
- ];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.Tools',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.util.Tools');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function charmapFilter(charmap) {
- return tinymce.util.Tools.grep(charmap, function(item) {
- return isArray(item) && item.length == 2;
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Plugin.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getCharsFromSetting(settingValue) {
- if (isArray(settingValue)) {
- return [].concat(charmapFilter(settingValue));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * This class contains all core logic for the charmap plugin.
+ *
+ * @class tinymce.charmap.Plugin
+ * @private
+ */
+define(
+ 'tinymce.plugins.charmap.Plugin',
+ [
+ 'tinymce.core.PluginManager',
+ 'tinymce.core.util.Tools'
+ ],
+ function (PluginManager, Tools) {
+ PluginManager.add('charmap', function (editor) {
+ var isArray = Tools.isArray;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof settingValue == "function") {
- return settingValue();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getDefaultCharMap() {
+ return [
+ ['160', 'no-break space'],
+ ['173', 'soft hyphen'],
+ ['34', 'quotation mark'],
+ // finance
+ ['162', 'cent sign'],
+ ['8364', 'euro sign'],
+ ['163', 'pound sign'],
+ ['165', 'yen sign'],
+ // signs
+ ['169', 'copyright sign'],
+ ['174', 'registered sign'],
+ ['8482', 'trade mark sign'],
+ ['8240', 'per mille sign'],
+ ['181', 'micro sign'],
+ ['183', 'middle dot'],
+ ['8226', 'bullet'],
+ ['8230', 'three dot leader'],
+ ['8242', 'minutes / feet'],
+ ['8243', 'seconds / inches'],
+ ['167', 'section sign'],
+ ['182', 'paragraph sign'],
+ ['223', 'sharp s / ess-zed'],
+ // quotations
+ ['8249', 'single left-pointing angle quotation mark'],
+ ['8250', 'single right-pointing angle quotation mark'],
+ ['171', 'left pointing guillemet'],
+ ['187', 'right pointing guillemet'],
+ ['8216', 'left single quotation mark'],
+ ['8217', 'right single quotation mark'],
+ ['8220', 'left double quotation mark'],
+ ['8221', 'right double quotation mark'],
+ ['8218', 'single low-9 quotation mark'],
+ ['8222', 'double low-9 quotation mark'],
+ ['60', 'less-than sign'],
+ ['62', 'greater-than sign'],
+ ['8804', 'less-than or equal to'],
+ ['8805', 'greater-than or equal to'],
+ ['8211', 'en dash'],
+ ['8212', 'em dash'],
+ ['175', 'macron'],
+ ['8254', 'overline'],
+ ['164', 'currency sign'],
+ ['166', 'broken bar'],
+ ['168', 'diaeresis'],
+ ['161', 'inverted exclamation mark'],
+ ['191', 'turned question mark'],
+ ['710', 'circumflex accent'],
+ ['732', 'small tilde'],
+ ['176', 'degree sign'],
+ ['8722', 'minus sign'],
+ ['177', 'plus-minus sign'],
+ ['247', 'division sign'],
+ ['8260', 'fraction slash'],
+ ['215', 'multiplication sign'],
+ ['185', 'superscript one'],
+ ['178', 'superscript two'],
+ ['179', 'superscript three'],
+ ['188', 'fraction one quarter'],
+ ['189', 'fraction one half'],
+ ['190', 'fraction three quarters'],
+ // math / logical
+ ['402', 'function / florin'],
+ ['8747', 'integral'],
+ ['8721', 'n-ary sumation'],
+ ['8734', 'infinity'],
+ ['8730', 'square root'],
+ ['8764', 'similar to'],
+ ['8773', 'approximately equal to'],
+ ['8776', 'almost equal to'],
+ ['8800', 'not equal to'],
+ ['8801', 'identical to'],
+ ['8712', 'element of'],
+ ['8713', 'not an element of'],
+ ['8715', 'contains as member'],
+ ['8719', 'n-ary product'],
+ ['8743', 'logical and'],
+ ['8744', 'logical or'],
+ ['172', 'not sign'],
+ ['8745', 'intersection'],
+ ['8746', 'union'],
+ ['8706', 'partial differential'],
+ ['8704', 'for all'],
+ ['8707', 'there exists'],
+ ['8709', 'diameter'],
+ ['8711', 'backward difference'],
+ ['8727', 'asterisk operator'],
+ ['8733', 'proportional to'],
+ ['8736', 'angle'],
+ // undefined
+ ['180', 'acute accent'],
+ ['184', 'cedilla'],
+ ['170', 'feminine ordinal indicator'],
+ ['186', 'masculine ordinal indicator'],
+ ['8224', 'dagger'],
+ ['8225', 'double dagger'],
+ // alphabetical special chars
+ ['192', 'A - grave'],
+ ['193', 'A - acute'],
+ ['194', 'A - circumflex'],
+ ['195', 'A - tilde'],
+ ['196', 'A - diaeresis'],
+ ['197', 'A - ring above'],
+ ['256', 'A - macron'],
+ ['198', 'ligature AE'],
+ ['199', 'C - cedilla'],
+ ['200', 'E - grave'],
+ ['201', 'E - acute'],
+ ['202', 'E - circumflex'],
+ ['203', 'E - diaeresis'],
+ ['274', 'E - macron'],
+ ['204', 'I - grave'],
+ ['205', 'I - acute'],
+ ['206', 'I - circumflex'],
+ ['207', 'I - diaeresis'],
+ ['298', 'I - macron'],
+ ['208', 'ETH'],
+ ['209', 'N - tilde'],
+ ['210', 'O - grave'],
+ ['211', 'O - acute'],
+ ['212', 'O - circumflex'],
+ ['213', 'O - tilde'],
+ ['214', 'O - diaeresis'],
+ ['216', 'O - slash'],
+ ['332', 'O - macron'],
+ ['338', 'ligature OE'],
+ ['352', 'S - caron'],
+ ['217', 'U - grave'],
+ ['218', 'U - acute'],
+ ['219', 'U - circumflex'],
+ ['220', 'U - diaeresis'],
+ ['362', 'U - macron'],
+ ['221', 'Y - acute'],
+ ['376', 'Y - diaeresis'],
+ ['562', 'Y - macron'],
+ ['222', 'THORN'],
+ ['224', 'a - grave'],
+ ['225', 'a - acute'],
+ ['226', 'a - circumflex'],
+ ['227', 'a - tilde'],
+ ['228', 'a - diaeresis'],
+ ['229', 'a - ring above'],
+ ['257', 'a - macron'],
+ ['230', 'ligature ae'],
+ ['231', 'c - cedilla'],
+ ['232', 'e - grave'],
+ ['233', 'e - acute'],
+ ['234', 'e - circumflex'],
+ ['235', 'e - diaeresis'],
+ ['275', 'e - macron'],
+ ['236', 'i - grave'],
+ ['237', 'i - acute'],
+ ['238', 'i - circumflex'],
+ ['239', 'i - diaeresis'],
+ ['299', 'i - macron'],
+ ['240', 'eth'],
+ ['241', 'n - tilde'],
+ ['242', 'o - grave'],
+ ['243', 'o - acute'],
+ ['244', 'o - circumflex'],
+ ['245', 'o - tilde'],
+ ['246', 'o - diaeresis'],
+ ['248', 'o slash'],
+ ['333', 'o macron'],
+ ['339', 'ligature oe'],
+ ['353', 's - caron'],
+ ['249', 'u - grave'],
+ ['250', 'u - acute'],
+ ['251', 'u - circumflex'],
+ ['252', 'u - diaeresis'],
+ ['363', 'u - macron'],
+ ['253', 'y - acute'],
+ ['254', 'thorn'],
+ ['255', 'y - diaeresis'],
+ ['563', 'y - macron'],
+ ['913', 'Alpha'],
+ ['914', 'Beta'],
+ ['915', 'Gamma'],
+ ['916', 'Delta'],
+ ['917', 'Epsilon'],
+ ['918', 'Zeta'],
+ ['919', 'Eta'],
+ ['920', 'Theta'],
+ ['921', 'Iota'],
+ ['922', 'Kappa'],
+ ['923', 'Lambda'],
+ ['924', 'Mu'],
+ ['925', 'Nu'],
+ ['926', 'Xi'],
+ ['927', 'Omicron'],
+ ['928', 'Pi'],
+ ['929', 'Rho'],
+ ['931', 'Sigma'],
+ ['932', 'Tau'],
+ ['933', 'Upsilon'],
+ ['934', 'Phi'],
+ ['935', 'Chi'],
+ ['936', 'Psi'],
+ ['937', 'Omega'],
+ ['945', 'alpha'],
+ ['946', 'beta'],
+ ['947', 'gamma'],
+ ['948', 'delta'],
+ ['949', 'epsilon'],
+ ['950', 'zeta'],
+ ['951', 'eta'],
+ ['952', 'theta'],
+ ['953', 'iota'],
+ ['954', 'kappa'],
+ ['955', 'lambda'],
+ ['956', 'mu'],
+ ['957', 'nu'],
+ ['958', 'xi'],
+ ['959', 'omicron'],
+ ['960', 'pi'],
+ ['961', 'rho'],
+ ['962', 'final sigma'],
+ ['963', 'sigma'],
+ ['964', 'tau'],
+ ['965', 'upsilon'],
+ ['966', 'phi'],
+ ['967', 'chi'],
+ ['968', 'psi'],
+ ['969', 'omega'],
+ // symbols
+ ['8501', 'alef symbol'],
+ ['982', 'pi symbol'],
+ ['8476', 'real part symbol'],
+ ['978', 'upsilon - hook symbol'],
+ ['8472', 'Weierstrass p'],
+ ['8465', 'imaginary part'],
+ // arrows
+ ['8592', 'leftwards arrow'],
+ ['8593', 'upwards arrow'],
+ ['8594', 'rightwards arrow'],
+ ['8595', 'downwards arrow'],
+ ['8596', 'left right arrow'],
+ ['8629', 'carriage return'],
+ ['8656', 'leftwards double arrow'],
+ ['8657', 'upwards double arrow'],
+ ['8658', 'rightwards double arrow'],
+ ['8659', 'downwards double arrow'],
+ ['8660', 'left right double arrow'],
+ ['8756', 'therefore'],
+ ['8834', 'subset of'],
+ ['8835', 'superset of'],
+ ['8836', 'not a subset of'],
+ ['8838', 'subset of or equal to'],
+ ['8839', 'superset of or equal to'],
+ ['8853', 'circled plus'],
+ ['8855', 'circled times'],
+ ['8869', 'perpendicular'],
+ ['8901', 'dot operator'],
+ ['8968', 'left ceiling'],
+ ['8969', 'right ceiling'],
+ ['8970', 'left floor'],
+ ['8971', 'right floor'],
+ ['9001', 'left-pointing angle bracket'],
+ ['9002', 'right-pointing angle bracket'],
+ ['9674', 'lozenge'],
+ ['9824', 'black spade suit'],
+ ['9827', 'black club suit'],
+ ['9829', 'black heart suit'],
+ ['9830', 'black diamond suit'],
+ ['8194', 'en space'],
+ ['8195', 'em space'],
+ ['8201', 'thin space'],
+ ['8204', 'zero width non-joiner'],
+ ['8205', 'zero width joiner'],
+ ['8206', 'left-to-right mark'],
+ ['8207', 'right-to-left mark']
+ ];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return [];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function charmapFilter(charmap) {
+ return Tools.grep(charmap, function (item) {
+ return isArray(item) && item.length == 2;
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function extendCharMap(charmap) {
- var settings = editor.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getCharsFromSetting(settingValue) {
+ if (isArray(settingValue)) {
+ return [].concat(charmapFilter(settingValue));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.charmap) {
- charmap = getCharsFromSetting(settings.charmap);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof settingValue == "function") {
+ return settingValue();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.charmap_append) {
- return [].concat(charmap).concat(getCharsFromSetting(settings.charmap_append));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return [];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return charmap;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function extendCharMap(charmap) {
+ var settings = editor.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getCharMap() {
- return extendCharMap(getDefaultCharMap());
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.charmap) {
+ charmap = getCharsFromSetting(settings.charmap);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function insertChar(chr) {
- editor.fire('insertCustomChar', {chr: chr}).chr;
- editor.execCommand('mceInsertContent', false, chr);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.charmap_append) {
+ return [].concat(charmap).concat(getCharsFromSetting(settings.charmap_append));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function showDialog() {
- var gridHtml, x, y, win;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return charmap;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getParentTd(elm) {
- while (elm) {
- if (elm.nodeName == 'TD') {
- return elm;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getCharMap() {
+ return extendCharMap(getDefaultCharMap());
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elm = elm.parentNode;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function insertChar(chr) {
+ editor.fire('insertCustomChar', { chr: chr }).chr;
+ editor.execCommand('mceInsertContent', false, chr);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- gridHtml = '<table role="presentation" cellspacing="0" class="mce-charmap"><tbody>';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function showDialog() {
+ var gridHtml, x, y, win;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var charmap = getCharMap();
- var width = Math.min(charmap.length, 25);
- var height = Math.ceil(charmap.length / width);
- for (y = 0; y < height; y++) {
- gridHtml += '<tr>';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getParentTd(elm) {
+ while (elm) {
+ if (elm.nodeName == 'TD') {
+ return elm;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (x = 0; x < width; x++) {
- var index = y * width + x;
- if (index < charmap.length) {
- var chr = charmap[index];
- var chrText = chr ? String.fromCharCode(parseInt(chr[0], 10)) : ' ';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elm = elm.parentNode;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- gridHtml += (
- '<td title="' + chr[1] + '"><div tabindex="-1" title="' + chr[1] + '" role="button" data-chr="' + chrText + '">' +
- chrText +
- '</div></td>'
- );
- } else {
- gridHtml += '<td />';
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ gridHtml = '<table role="presentation" cellspacing="0" class="mce-charmap"><tbody>';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- gridHtml += '</tr>';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var charmap = getCharMap();
+ var width = Math.min(charmap.length, 25);
+ var height = Math.ceil(charmap.length / width);
+ for (y = 0; y < height; y++) {
+ gridHtml += '<tr>';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- gridHtml += '</tbody></table>';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (x = 0; x < width; x++) {
+ var index = y * width + x;
+ if (index < charmap.length) {
+ var chr = charmap[index];
+ var chrText = chr ? String.fromCharCode(parseInt(chr[0], 10)) : ' ';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var charMapPanel = {
- type: 'container',
- html: gridHtml,
- onclick: function(e) {
- var target = e.target;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ gridHtml += (
+ '<td title="' + chr[1] + '">' +
+ '<div tabindex="-1" title="' + chr[1] + '" role="button" data-chr="' + chrText + '">' +
+ chrText +
+ '</div>' +
+ '</td>'
+ );
+ } else {
+ gridHtml += '<td />';
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (/^(TD|DIV)$/.test(target.nodeName)) {
- if (getParentTd(target).firstChild) {
- insertChar(target.getAttribute('data-chr'));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ gridHtml += '</tr>';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!e.ctrlKey) {
- win.close();
- }
- }
- }
- },
- onmouseover: function(e) {
- var td = getParentTd(e.target);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ gridHtml += '</tbody></table>';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (td && td.firstChild) {
- win.find('#preview').text(td.firstChild.firstChild.data);
- win.find('#previewTitle').text(td.title);
- } else {
- win.find('#preview').text(' ');
- win.find('#previewTitle').text(' ');
- }
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var charMapPanel = {
+ type: 'container',
+ html: gridHtml,
+ onclick: function (e) {
+ var target = e.target;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- win = editor.windowManager.open({
- title: "Special character",
- spacing: 10,
- padding: 10,
- items: [
- charMapPanel,
- {
- type: 'container',
- layout: 'flex',
- direction: 'column',
- align: 'center',
- spacing: 5,
- minWidth: 160,
- minHeight: 160,
- items: [
- {
- type: 'label',
- name: 'preview',
- text: ' ',
- style: 'font-size: 40px; text-align: center',
- border: 1,
- minWidth: 140,
- minHeight: 80
- },
- {
- type: 'label',
- name: 'previewTitle',
- text: ' ',
- style: 'text-align: center',
- border: 1,
- minWidth: 140,
- minHeight: 80
- }
- ]
- }
- ],
- buttons: [
- {text: "Close", onclick: function() {
- win.close();
- }}
- ]
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (/^(TD|DIV)$/.test(target.nodeName)) {
+ var charDiv = getParentTd(target).firstChild;
+ if (charDiv && charDiv.hasAttribute('data-chr')) {
+ insertChar(charDiv.getAttribute('data-chr'));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addCommand('mceShowCharmap', showDialog);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!e.ctrlKey) {
+ win.close();
+ }
+ }
+ }
+ },
+ onmouseover: function (e) {
+ var td = getParentTd(e.target);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addButton('charmap', {
- icon: 'charmap',
- tooltip: 'Special character',
- cmd: 'mceShowCharmap'
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (td && td.firstChild) {
+ win.find('#preview').text(td.firstChild.firstChild.data);
+ win.find('#previewTitle').text(td.title);
+ } else {
+ win.find('#preview').text(' ');
+ win.find('#previewTitle').text(' ');
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addMenuItem('charmap', {
- icon: 'charmap',
- text: 'Special character',
- cmd: 'mceShowCharmap',
- context: 'insert'
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ win = editor.windowManager.open({
+ title: "Special character",
+ spacing: 10,
+ padding: 10,
+ items: [
+ charMapPanel,
+ {
+ type: 'container',
+ layout: 'flex',
+ direction: 'column',
+ align: 'center',
+ spacing: 5,
+ minWidth: 160,
+ minHeight: 160,
+ items: [
+ {
+ type: 'label',
+ name: 'preview',
+ text: ' ',
+ style: 'font-size: 40px; text-align: center',
+ border: 1,
+ minWidth: 140,
+ minHeight: 80
+ },
+ {
+ type: 'label',
+ name: 'previewTitle',
+ text: ' ',
+ style: 'text-align: center',
+ border: 1,
+ minWidth: 140,
+ minHeight: 80
+ }
+ ]
+ }
+ ],
+ buttons: [
+ {
+ text: "Close", onclick: function () {
+ win.close();
+ }
+ }
+ ]
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- getCharMap: getCharMap,
- insertChar: insertChar
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addCommand('mceShowCharmap', showDialog);
+
+ editor.addButton('charmap', {
+ icon: 'charmap',
+ tooltip: 'Special character',
+ cmd: 'mceShowCharmap'
+ });
+
+ editor.addMenuItem('charmap', {
+ icon: 'charmap',
+ text: 'Special character',
+ cmd: 'mceShowCharmap',
+ context: 'insert'
+ });
+
+ return {
+ getCharMap: getCharMap,
+ insertChar: insertChar
+ };
+ });
+
+ return function () { };
+ }
+);
+dem('tinymce.plugins.charmap.Plugin')();
+})();
</ins></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginscharmappluginminjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/charmap/plugin.min.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/charmap/plugin.min.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/charmap/plugin.min.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1 +1 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-tinymce.PluginManager.add("charmap",function(e){function t(){return[["160","no-break space"],["173","soft hyphen"],["34","quotation mark"],["162","cent sign"],["8364","euro sign"],["163","pound sign"],["165","yen sign"],["169","copyright sign"],["174","registered sign"],["8482","trade mark sign"],["8240","per mille sign"],["181","micro sign"],["183","middle dot"],["8226","bullet"],["8230","three dot leader"],["8242","minutes / feet"],["8243","seconds / inches"],["167","section sign"],["182","paragraph sign&quo
t;],["223","sharp s / ess-zed"],["8249","single left-pointing angle quotation mark"],["8250","single right-pointing angle quotation mark"],["171","left pointing guillemet"],["187","right pointing guillemet"],["8216","left single quotation mark"],["8217","right single quotation mark"],["8220","left double quotation mark"],["8221","right double quotation mark"],["8218","single low-9 quotation mark"],["8222","double low-9 quotation mark"],["60","less-than sign"],["62","greater-than sign"],["8804","less-than or equal to"],["8805","greater-than or equal to"],["8211","en dash"],["8212","em dash"],["175","macron"],["8254",&quo
t;overline"],["164","currency sign"],["166","broken bar"],["168","diaeresis"],["161","inverted exclamation mark"],["191","turned question mark"],["710","circumflex accent"],["732","small tilde"],["176","degree sign"],["8722","minus sign"],["177","plus-minus sign"],["247","division sign"],["8260","fraction slash"],["215","multiplication sign"],["185","superscript one"],["178","superscript two"],["179","superscript three"],["188","fraction one quarter"],["189","fraction one half"],["190","fraction three quarters"],["402","function / florin"],["8747","integral"],["
;8721","n-ary sumation"],["8734","infinity"],["8730","square root"],["8764","similar to"],["8773","approximately equal to"],["8776","almost equal to"],["8800","not equal to"],["8801","identical to"],["8712","element of"],["8713","not an element of"],["8715","contains as member"],["8719","n-ary product"],["8743","logical and"],["8744","logical or"],["172","not sign"],["8745","intersection"],["8746","union"],["8706","partial differential"],["8704","for all"],["8707","there exists"],["8709","diameter"],["8711","backward difference"],["8727","as
terisk operator"],["8733","proportional to"],["8736","angle"],["180","acute accent"],["184","cedilla"],["170","feminine ordinal indicator"],["186","masculine ordinal indicator"],["8224","dagger"],["8225","double dagger"],["192","A - grave"],["193","A - acute"],["194","A - circumflex"],["195","A - tilde"],["196","A - diaeresis"],["197","A - ring above"],["256","A - macron"],["198","ligature AE"],["199","C - cedilla"],["200","E - grave"],["201","E - acute"],["202","E - circumflex"],["203","E - diaeresis"],["274","E - macron"],["204","
;I - grave"],["205","I - acute"],["206","I - circumflex"],["207","I - diaeresis"],["298","I - macron"],["208","ETH"],["209","N - tilde"],["210","O - grave"],["211","O - acute"],["212","O - circumflex"],["213","O - tilde"],["214","O - diaeresis"],["216","O - slash"],["332","O - macron"],["338","ligature OE"],["352","S - caron"],["217","U - grave"],["218","U - acute"],["219","U - circumflex"],["220","U - diaeresis"],["362","U - macron"],["221","Y - acute"],["376","Y - diaeresis"],["562","Y - macron"],["222","THORN
"],["224","a - grave"],["225","a - acute"],["226","a - circumflex"],["227","a - tilde"],["228","a - diaeresis"],["229","a - ring above"],["257","a - macron"],["230","ligature ae"],["231","c - cedilla"],["232","e - grave"],["233","e - acute"],["234","e - circumflex"],["235","e - diaeresis"],["275","e - macron"],["236","i - grave"],["237","i - acute"],["238","i - circumflex"],["239","i - diaeresis"],["299","i - macron"],["240","eth"],["241","n - tilde"],["242","o - grave"],["243","o - acute"],["244","o - circumfle
x"],["245","o - tilde"],["246","o - diaeresis"],["248","o slash"],["333","o macron"],["339","ligature oe"],["353","s - caron"],["249","u - grave"],["250","u - acute"],["251","u - circumflex"],["252","u - diaeresis"],["363","u - macron"],["253","y - acute"],["254","thorn"],["255","y - diaeresis"],["563","y - macron"],["913","Alpha"],["914","Beta"],["915","Gamma"],["916","Delta"],["917","Epsilon"],["918","Zeta"],["919","Eta"],["920","Theta"],["921","Iota"],["922","Kappa"],["923",
"Lambda"],["924","Mu"],["925","Nu"],["926","Xi"],["927","Omicron"],["928","Pi"],["929","Rho"],["931","Sigma"],["932","Tau"],["933","Upsilon"],["934","Phi"],["935","Chi"],["936","Psi"],["937","Omega"],["945","alpha"],["946","beta"],["947","gamma"],["948","delta"],["949","epsilon"],["950","zeta"],["951","eta"],["952","theta"],["953","iota"],["954","kappa"],["955","lambda"],["956","mu"],["957","nu"],["958","xi"],["959","omicron&quo
t;],["960","pi"],["961","rho"],["962","final sigma"],["963","sigma"],["964","tau"],["965","upsilon"],["966","phi"],["967","chi"],["968","psi"],["969","omega"],["8501","alef symbol"],["982","pi symbol"],["8476","real part symbol"],["978","upsilon - hook symbol"],["8472","Weierstrass p"],["8465","imaginary part"],["8592","leftwards arrow"],["8593","upwards arrow"],["8594","rightwards arrow"],["8595","downwards arrow"],["8596","left right arrow"],["8629","carriage return"],["8656","leftwards double arrow"],["8657","upwa
rds double arrow"],["8658","rightwards double arrow"],["8659","downwards double arrow"],["8660","left right double arrow"],["8756","therefore"],["8834","subset of"],["8835","superset of"],["8836","not a subset of"],["8838","subset of or equal to"],["8839","superset of or equal to"],["8853","circled plus"],["8855","circled times"],["8869","perpendicular"],["8901","dot operator"],["8968","left ceiling"],["8969","right ceiling"],["8970","left floor"],["8971","right floor"],["9001","left-pointing angle bracket"],["9002","right-pointing angle bracket"],["9674","lozenge"],["9824",&
quot;black spade suit"],["9827","black club suit"],["9829","black heart suit"],["9830","black diamond suit"],["8194","en space"],["8195","em space"],["8201","thin space"],["8204","zero width non-joiner"],["8205","zero width joiner"],["8206","left-to-right mark"],["8207","right-to-left mark"]]}function n(e){return tinymce.util.Tools.grep(e,function(e){return l(e)&&2==e.length})}function r(e){return l(e)?[].concat(n(e)):"function"==typeof e?e():[]}function i(t){var n=e.settings;return n.charmap&&(t=r(n.charmap)),n.charmap_append?[].concat(t).concat(r(n.charmap_append)):t}function o(){return i(t())}function a(t){e.fire("insertCustomChar",{chr:t}).chr,e.execCommand("mceInsertContent",!1,t)}function s(){function t(e){for(;e;){if("TD&quo
t;==e.nodeName)return e;e=e.parentNode}}var n,r,i,s;n='<table role="presentation" cellspacing="0" class="mce-charmap"><tbody>';var l=o(),u=Math.min(l.length,25),c=Math.ceil(l.length/u);for(i=0;i<c;i++){for(n+="<tr>",r=0;r<u;r++){var d=i*u+r;if(d<l.length){var f=l[d],p=f?String.fromCharCode(parseInt(f[0],10)):" ";n+='<td title="'+f[1]+'"><div tabindex="-1" title="'+f[1]+'" role="button" data-chr="'+p+'">'+p+"</div></td>"}else n+="<td />"}n+="</tr>"}n+="</tbody></table>";var h={type:"container",html:n,onclick:function(e){var n=e.target;/^(TD|DIV)$/.test(n.nodeName)&&t(n).firstChild&&(a(n.getAttribute("data-chr")),e.ctrlKey||s.close())},onmouseover:function(e){var n=t(e.target);n&&n.firstChild?(s.find("#preview")
.text(n.firstChild.firstChild.data),s.find("#previewTitle").text(n.title)):(s.find("#preview").text(" "),s.find("#previewTitle").text(" "))}};s=e.windowManager.open({title:"Special character",spacing:10,padding:10,items:[h,{type:"container",layout:"flex",direction:"column",align:"center",spacing:5,minWidth:160,minHeight:160,items:[{type:"label",name:"preview",text:" ",style:"font-size: 40px; text-align: center",border:1,minWidth:140,minHeight:80},{type:"label",name:"previewTitle",text:" ",style:"text-align: center",border:1,minWidth:140,minHeight:80}]}],buttons:[{text:"Close",onclick:function(){s.close()}}]})}var l=tinymce.util.Tools.isArray;return e.addCommand("mceShowCharmap",s),e.addButton("charmap",{icon:"charmap",tooltip:"Special character",cmd:"m
ceShowCharmap"}),e.addMenuItem("charmap",{icon:"charmap",text:"Special character",cmd:"mceShowCharmap",context:"insert"}),{getCharMap:o,insertChar:a}});
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+!function(){var a={},b=function(b){for(var c=a[b],e=c.deps,f=c.defn,g=e.length,h=new Array(g),i=0;i<g;++i)h[i]=d(e[i]);var j=f.apply(null,h);if(void 0===j)throw"module ["+b+"] returned undefined";c.instance=j},c=function(b,c,d){if("string"!=typeof b)throw"module id must be a string";if(void 0===c)throw"no dependencies for "+b;if(void 0===d)throw"no definition function for "+b;a[b]={deps:c,defn:d,instance:void 0}},d=function(c){var d=a[c];if(void 0===d)throw"module ["+c+"] was undefined";return void 0===d.instance&&b(c),d.instance},e=function(a,b){for(var c=a.length,e=new Array(c),f=0;f<c;++f)e.push(d(a[f]));b.apply(null,b)},f={};f.bolt={module:{api:{define:c,require:e,demand:d}}};var g=c,h=function(a,b){g(a,[],function(){return b})};h("3",tinymce.util.Tools.resolve),g("1",[&q
uot;3"],function(a){return a("tinymce.PluginManager")}),g("2",["3"],function(a){return a("tinymce.util.Tools")}),g("0",["1","2"],function(a,b){return a.add("charmap",function(a){function c(){return[["160","no-break space"],["173","soft hyphen"],["34","quotation mark"],["162","cent sign"],["8364","euro sign"],["163","pound sign"],["165","yen sign"],["169","copyright sign"],["174","registered sign"],["8482","trade mark sign"],["8240","per mille sign"],["181","micro sign"],["183","middle dot"],["8226","bullet"],["8230","three dot leader"],["8242","minutes / feet"],["8243","
seconds / inches"],["167","section sign"],["182","paragraph sign"],["223","sharp s / ess-zed"],["8249","single left-pointing angle quotation mark"],["8250","single right-pointing angle quotation mark"],["171","left pointing guillemet"],["187","right pointing guillemet"],["8216","left single quotation mark"],["8217","right single quotation mark"],["8220","left double quotation mark"],["8221","right double quotation mark"],["8218","single low-9 quotation mark"],["8222","double low-9 quotation mark"],["60","less-than sign"],["62","greater-than sign"],["8804","less-than or equal to"],["8805","greater-than or equal to"],["8211","en da
sh"],["8212","em dash"],["175","macron"],["8254","overline"],["164","currency sign"],["166","broken bar"],["168","diaeresis"],["161","inverted exclamation mark"],["191","turned question mark"],["710","circumflex accent"],["732","small tilde"],["176","degree sign"],["8722","minus sign"],["177","plus-minus sign"],["247","division sign"],["8260","fraction slash"],["215","multiplication sign"],["185","superscript one"],["178","superscript two"],["179","superscript three"],["188","fraction one quarter"],["189","fraction one half"],["190","fraction three qu
arters"],["402","function / florin"],["8747","integral"],["8721","n-ary sumation"],["8734","infinity"],["8730","square root"],["8764","similar to"],["8773","approximately equal to"],["8776","almost equal to"],["8800","not equal to"],["8801","identical to"],["8712","element of"],["8713","not an element of"],["8715","contains as member"],["8719","n-ary product"],["8743","logical and"],["8744","logical or"],["172","not sign"],["8745","intersection"],["8746","union"],["8706","partial differential"],["8704","for all"],["8707","there exists"],["87
09","diameter"],["8711","backward difference"],["8727","asterisk operator"],["8733","proportional to"],["8736","angle"],["180","acute accent"],["184","cedilla"],["170","feminine ordinal indicator"],["186","masculine ordinal indicator"],["8224","dagger"],["8225","double dagger"],["192","A - grave"],["193","A - acute"],["194","A - circumflex"],["195","A - tilde"],["196","A - diaeresis"],["197","A - ring above"],["256","A - macron"],["198","ligature AE"],["199","C - cedilla"],["200","E - grave"],["201","E - acute"],["202","E - circumflex"]
,["203","E - diaeresis"],["274","E - macron"],["204","I - grave"],["205","I - acute"],["206","I - circumflex"],["207","I - diaeresis"],["298","I - macron"],["208","ETH"],["209","N - tilde"],["210","O - grave"],["211","O - acute"],["212","O - circumflex"],["213","O - tilde"],["214","O - diaeresis"],["216","O - slash"],["332","O - macron"],["338","ligature OE"],["352","S - caron"],["217","U - grave"],["218","U - acute"],["219","U - circumflex"],["220","U - diaeresis"],["362","U - macron"],["221","Y - acute"],[&quo
t;376","Y - diaeresis"],["562","Y - macron"],["222","THORN"],["224","a - grave"],["225","a - acute"],["226","a - circumflex"],["227","a - tilde"],["228","a - diaeresis"],["229","a - ring above"],["257","a - macron"],["230","ligature ae"],["231","c - cedilla"],["232","e - grave"],["233","e - acute"],["234","e - circumflex"],["235","e - diaeresis"],["275","e - macron"],["236","i - grave"],["237","i - acute"],["238","i - circumflex"],["239","i - diaeresis"],["299","i - macron"],["240","eth"],["241","n - tilde"],["2
42","o - grave"],["243","o - acute"],["244","o - circumflex"],["245","o - tilde"],["246","o - diaeresis"],["248","o slash"],["333","o macron"],["339","ligature oe"],["353","s - caron"],["249","u - grave"],["250","u - acute"],["251","u - circumflex"],["252","u - diaeresis"],["363","u - macron"],["253","y - acute"],["254","thorn"],["255","y - diaeresis"],["563","y - macron"],["913","Alpha"],["914","Beta"],["915","Gamma"],["916","Delta"],["917","Epsilon"],["918","Zeta"],["919","Eta"],["920"
,"Theta"],["921","Iota"],["922","Kappa"],["923","Lambda"],["924","Mu"],["925","Nu"],["926","Xi"],["927","Omicron"],["928","Pi"],["929","Rho"],["931","Sigma"],["932","Tau"],["933","Upsilon"],["934","Phi"],["935","Chi"],["936","Psi"],["937","Omega"],["945","alpha"],["946","beta"],["947","gamma"],["948","delta"],["949","epsilon"],["950","zeta"],["951","eta"],["952","theta"],["953","iota"],["954","kappa"],["955","lambda"],["956","mu
"],["957","nu"],["958","xi"],["959","omicron"],["960","pi"],["961","rho"],["962","final sigma"],["963","sigma"],["964","tau"],["965","upsilon"],["966","phi"],["967","chi"],["968","psi"],["969","omega"],["8501","alef symbol"],["982","pi symbol"],["8476","real part symbol"],["978","upsilon - hook symbol"],["8472","Weierstrass p"],["8465","imaginary part"],["8592","leftwards arrow"],["8593","upwards arrow"],["8594","rightwards arrow"],["8595","downwards arrow"],["8596","left right arrow"],["8629",&qu
ot;carriage return"],["8656","leftwards double arrow"],["8657","upwards double arrow"],["8658","rightwards double arrow"],["8659","downwards double arrow"],["8660","left right double arrow"],["8756","therefore"],["8834","subset of"],["8835","superset of"],["8836","not a subset of"],["8838","subset of or equal to"],["8839","superset of or equal to"],["8853","circled plus"],["8855","circled times"],["8869","perpendicular"],["8901","dot operator"],["8968","left ceiling"],["8969","right ceiling"],["8970","left floor"],["8971","right floor"],["9001","left-pointing angle bracket"],["900
2","right-pointing angle bracket"],["9674","lozenge"],["9824","black spade suit"],["9827","black club suit"],["9829","black heart suit"],["9830","black diamond suit"],["8194","en space"],["8195","em space"],["8201","thin space"],["8204","zero width non-joiner"],["8205","zero width joiner"],["8206","left-to-right mark"],["8207","right-to-left mark"]]}function d(a){return b.grep(a,function(a){return j(a)&&2==a.length})}function e(a){return j(a)?[].concat(d(a)):"function"==typeof a?a():[]}function f(b){var c=a.settings;return c.charmap&&(b=e(c.charmap)),c.charmap_append?[].concat(b).concat(e(c.charmap_append)):b}function g(){return f(c())}function h(b){a.fire("insertCustomChar",{chr:b}).chr,a.execCom
mand("mceInsertContent",!1,b)}function i(){function b(a){for(;a;){if("TD"==a.nodeName)return a;a=a.parentNode}}var c,d,e,f;c='<table role="presentation" cellspacing="0" class="mce-charmap"><tbody>';var i=g(),j=Math.min(i.length,25),k=Math.ceil(i.length/j);for(e=0;e<k;e++){for(c+="<tr>",d=0;d<j;d++){var l=e*j+d;if(l<i.length){var m=i[l],n=m?String.fromCharCode(parseInt(m[0],10)):" ";c+='<td title="'+m[1]+'"><div tabindex="-1" title="'+m[1]+'" role="button" data-chr="'+n+'">'+n+"</div></td>"}else c+="<td />"}c+="</tr>"}c+="</tbody></table>";var o={type:"container",html:c,onclick:function(a){var c=a.target;if(/^(TD|DIV)$/.test(c.nodeName)){var d=b(c).firstChild;d&&d.hasAttribute("data-chr")&&(h(d.getAttribute(&
quot;data-chr")),a.ctrlKey||f.close())}},onmouseover:function(a){var c=b(a.target);c&&c.firstChild?(f.find("#preview").text(c.firstChild.firstChild.data),f.find("#previewTitle").text(c.title)):(f.find("#preview").text(" "),f.find("#previewTitle").text(" "))}};f=a.windowManager.open({title:"Special character",spacing:10,padding:10,items:[o,{type:"container",layout:"flex",direction:"column",align:"center",spacing:5,minWidth:160,minHeight:160,items:[{type:"label",name:"preview",text:" ",style:"font-size: 40px; text-align: center",border:1,minWidth:140,minHeight:80},{type:"label",name:"previewTitle",text:" ",style:"text-align: center",border:1,minWidth:140,minHeight:80}]}],buttons:[{text:"Close",onclick:function(){f.close()}}]})}var j=b.isArray;return a.addCommand("mceShow
Charmap",i),a.addButton("charmap",{icon:"charmap",tooltip:"Special character",cmd:"mceShowCharmap"}),a.addMenuItem("charmap",{icon:"charmap",text:"Special character",cmd:"mceShowCharmap",context:"insert"}),{getCharMap:g,insertChar:h}}),function(){}}),d("0")()}();
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginscolorpickerpluginjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/colorpicker/plugin.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/colorpicker/plugin.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/colorpicker/plugin.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,112 +1,255 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+(function () {
+
+var defs = {}; // id -> {dependencies, definition, instance (possibly undefined)}
+
+// Used when there is no 'main' module.
+// The name is probably (hopefully) unique so minification removes for releases.
+var register_3795 = function (id) {
+ var module = dem(id);
+ var fragments = id.split('.');
+ var target = Function('return this;')();
+ for (var i = 0; i < fragments.length - 1; ++i) {
+ if (target[fragments[i]] === undefined)
+ target[fragments[i]] = {};
+ target = target[fragments[i]];
+ }
+ target[fragments[fragments.length - 1]] = module;
+};
+
+var instantiate = function (id) {
+ var actual = defs[id];
+ var dependencies = actual.deps;
+ var definition = actual.defn;
+ var len = dependencies.length;
+ var instances = new Array(len);
+ for (var i = 0; i < len; ++i)
+ instances[i] = dem(dependencies[i]);
+ var defResult = definition.apply(null, instances);
+ if (defResult === undefined)
+ throw 'module [' + id + '] returned undefined';
+ actual.instance = defResult;
+};
+
+var def = function (id, dependencies, definition) {
+ if (typeof id !== 'string')
+ throw 'module id must be a string';
+ else if (dependencies === undefined)
+ throw 'no dependencies for ' + id;
+ else if (definition === undefined)
+ throw 'no definition function for ' + id;
+ defs[id] = {
+ deps: dependencies,
+ defn: definition,
+ instance: undefined
+ };
+};
+
+var dem = function (id) {
+ var actual = defs[id];
+ if (actual === undefined)
+ throw 'module [' + id + '] was undefined';
+ else if (actual.instance === undefined)
+ instantiate(id);
+ return actual.instance;
+};
+
+var req = function (ids, callback) {
+ var len = ids.length;
+ var instances = new Array(len);
+ for (var i = 0; i < len; ++i)
+ instances.push(dem(ids[i]));
+ callback.apply(null, callback);
+};
+
+var ephox = {};
+
+ephox.bolt = {
+ module: {
+ api: {
+ define: def,
+ require: req,
+ demand: dem
+ }
+ }
+};
+
+var define = def;
+var require = req;
+var demand = dem;
+// this helps with minificiation when using a lot of global references
+var defineGlobal = function (id, ref) {
+ define(id, [], function () { return ref; });
+};
+/*jsc
+["tinymce.plugins.colorpicker.Plugin","tinymce.core.PluginManager","tinymce.core.util.Color","global!tinymce.util.Tools.resolve"]
+jsc*/
+defineGlobal("global!tinymce.util.Tools.resolve", tinymce.util.Tools.resolve);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * plugin.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ResolveGlobal.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/*global tinymce:true */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.PluginManager',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.PluginManager');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-tinymce.PluginManager.add('colorpicker', function(editor) {
- function colorPickerCallback(callback, value) {
- function setColor(value) {
- var color = new tinymce.util.Color(value), rgb = color.toRgb();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- win.fromJSON({
- r: rgb.r,
- g: rgb.g,
- b: rgb.b,
- hex: color.toHex().substr(1)
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.Color',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.util.Color');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- showPreview(color.toHex());
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Plugin.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function showPreview(hexColor) {
- win.find('#preview')[0].getEl().style.background = hexColor;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * This class contains all core logic for the colorpicker plugin.
+ *
+ * @class tinymce.colorpicker.Plugin
+ * @private
+ */
+define(
+ 'tinymce.plugins.colorpicker.Plugin',
+ [
+ 'tinymce.core.PluginManager',
+ 'tinymce.core.util.Color'
+ ],
+ function (PluginManager, Color) {
+ PluginManager.add('colorpicker', function (editor) {
+ function colorPickerCallback(callback, value) {
+ function setColor(value) {
+ var color = new Color(value), rgb = color.toRgb();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var win = editor.windowManager.open({
- title: 'Color',
- items: {
- type: 'container',
- layout: 'flex',
- direction: 'row',
- align: 'stretch',
- padding: 5,
- spacing: 10,
- items: [
- {
- type: 'colorpicker',
- value: value,
- onchange: function() {
- var rgb = this.rgb();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ win.fromJSON({
+ r: rgb.r,
+ g: rgb.g,
+ b: rgb.b,
+ hex: color.toHex().substr(1)
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (win) {
- win.find('#r').value(rgb.r);
- win.find('#g').value(rgb.g);
- win.find('#b').value(rgb.b);
- win.find('#hex').value(this.value().substr(1));
- showPreview(this.value());
- }
- }
- },
- {
- type: 'form',
- padding: 0,
- labelGap: 5,
- defaults: {
- type: 'textbox',
- size: 7,
- value: '0',
- flex: 1,
- spellcheck: false,
- onchange: function() {
- var colorPickerCtrl = win.find('colorpicker')[0];
- var name, value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ showPreview(color.toHex());
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- name = this.name();
- value = this.value();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function showPreview(hexColor) {
+ win.find('#preview')[0].getEl().style.background = hexColor;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name == "hex") {
- value = '#' + value;
- setColor(value);
- colorPickerCtrl.value(value);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var win = editor.windowManager.open({
+ title: 'Color',
+ items: {
+ type: 'container',
+ layout: 'flex',
+ direction: 'row',
+ align: 'stretch',
+ padding: 5,
+ spacing: 10,
+ items: [
+ {
+ type: 'colorpicker',
+ value: value,
+ onchange: function () {
+ var rgb = this.rgb();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- value = {
- r: win.find('#r').value(),
- g: win.find('#g').value(),
- b: win.find('#b').value()
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (win) {
+ win.find('#r').value(rgb.r);
+ win.find('#g').value(rgb.g);
+ win.find('#b').value(rgb.b);
+ win.find('#hex').value(this.value().substr(1));
+ showPreview(this.value());
+ }
+ }
+ },
+ {
+ type: 'form',
+ padding: 0,
+ labelGap: 5,
+ defaults: {
+ type: 'textbox',
+ size: 7,
+ value: '0',
+ flex: 1,
+ spellcheck: false,
+ onchange: function () {
+ var colorPickerCtrl = win.find('colorpicker')[0];
+ var name, value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- colorPickerCtrl.value(value);
- setColor(value);
- }
- },
- items: [
- {name: 'r', label: 'R', autofocus: 1},
- {name: 'g', label: 'G'},
- {name: 'b', label: 'B'},
- {name: 'hex', label: '#', value: '000000'},
- {name: 'preview', type: 'container', border: 1}
- ]
- }
- ]
- },
- onSubmit: function() {
- callback('#' + this.toJSON().hex);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ name = this.name();
+ value = this.value();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- setColor(value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name == "hex") {
+ value = '#' + value;
+ setColor(value);
+ colorPickerCtrl.value(value);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!editor.settings.color_picker_callback) {
- editor.settings.color_picker_callback = colorPickerCallback;
- }
-});
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ value = {
+ r: win.find('#r').value(),
+ g: win.find('#g').value(),
+ b: win.find('#b').value()
+ };
+
+ colorPickerCtrl.value(value);
+ setColor(value);
+ }
+ },
+ items: [
+ { name: 'r', label: 'R', autofocus: 1 },
+ { name: 'g', label: 'G' },
+ { name: 'b', label: 'B' },
+ { name: 'hex', label: '#', value: '000000' },
+ { name: 'preview', type: 'container', border: 1 }
+ ]
+ }
+ ]
+ },
+ onSubmit: function () {
+ callback('#' + this.toJSON().hex);
+ }
+ });
+
+ setColor(value);
+ }
+
+ if (!editor.settings.color_picker_callback) {
+ editor.settings.color_picker_callback = colorPickerCallback;
+ }
+ });
+
+ return function () { };
+ }
+);
+dem('tinymce.plugins.colorpicker.Plugin')();
+})();
</ins></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginscolorpickerpluginminjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/colorpicker/plugin.min.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/colorpicker/plugin.min.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/colorpicker/plugin.min.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1 +1 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-tinymce.PluginManager.add("colorpicker",function(e){function t(t,n){function r(e){var t=new tinymce.util.Color(e),n=t.toRgb();o.fromJSON({r:n.r,g:n.g,b:n.b,hex:t.toHex().substr(1)}),i(t.toHex())}function i(e){o.find("#preview")[0].getEl().style.background=e}var o=e.windowManager.open({title:"Color",items:{type:"container",layout:"flex",direction:"row",align:"stretch",padding:5,spacing:10,items:[{type:"colorpicker",value:n,onchange:function(){var e=this.rgb();o&&(o.find("#r").value(e.r),o.find("#g").value(e.g),o.find("#b").value(e.b),o.find("#hex").value(this.value().substr(1)),i(this.value()))}},{type:"form",padding:0,labelGap:5,defaults:{type:"textbox",size:7,value:"0",flex:1,spellcheck:!1,onchange:function(){var e,t,n=o.find("
;colorpicker")[0];return e=this.name(),t=this.value(),"hex"==e?(t="#"+t,r(t),void n.value(t)):(t={r:o.find("#r").value(),g:o.find("#g").value(),b:o.find("#b").value()},n.value(t),void r(t))}},items:[{name:"r",label:"R",autofocus:1},{name:"g",label:"G"},{name:"b",label:"B"},{name:"hex",label:"#",value:"000000"},{name:"preview",type:"container",border:1}]}]},onSubmit:function(){t("#"+this.toJSON().hex)}});r(n)}e.settings.color_picker_callback||(e.settings.color_picker_callback=t)});
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+!function(){var a={},b=function(b){for(var c=a[b],e=c.deps,f=c.defn,g=e.length,h=new Array(g),i=0;i<g;++i)h[i]=d(e[i]);var j=f.apply(null,h);if(void 0===j)throw"module ["+b+"] returned undefined";c.instance=j},c=function(b,c,d){if("string"!=typeof b)throw"module id must be a string";if(void 0===c)throw"no dependencies for "+b;if(void 0===d)throw"no definition function for "+b;a[b]={deps:c,defn:d,instance:void 0}},d=function(c){var d=a[c];if(void 0===d)throw"module ["+c+"] was undefined";return void 0===d.instance&&b(c),d.instance},e=function(a,b){for(var c=a.length,e=new Array(c),f=0;f<c;++f)e.push(d(a[f]));b.apply(null,b)},f={};f.bolt={module:{api:{define:c,require:e,demand:d}}};var g=c,h=function(a,b){g(a,[],function(){return b})};h("3",tinymce.util.Tools.resolve),g("1",[&q
uot;3"],function(a){return a("tinymce.PluginManager")}),g("2",["3"],function(a){return a("tinymce.util.Color")}),g("0",["1","2"],function(a,b){return a.add("colorpicker",function(a){function c(c,d){function e(a){var c=new b(a),d=c.toRgb();g.fromJSON({r:d.r,g:d.g,b:d.b,hex:c.toHex().substr(1)}),f(c.toHex())}function f(a){g.find("#preview")[0].getEl().style.background=a}var g=a.windowManager.open({title:"Color",items:{type:"container",layout:"flex",direction:"row",align:"stretch",padding:5,spacing:10,items:[{type:"colorpicker",value:d,onchange:function(){var a=this.rgb();g&&(g.find("#r").value(a.r),g.find("#g").value(a.g),g.find("#b").value(a.b),g.find("#hex").value(this.value().substr(1)),f(this.value()))}},{type:"form",padding:0,labelGap:5,defaults:{type:"textbox"
,size:7,value:"0",flex:1,spellcheck:!1,onchange:function(){var a,b,c=g.find("colorpicker")[0];return a=this.name(),b=this.value(),"hex"==a?(b="#"+b,e(b),void c.value(b)):(b={r:g.find("#r").value(),g:g.find("#g").value(),b:g.find("#b").value()},c.value(b),void e(b))}},items:[{name:"r",label:"R",autofocus:1},{name:"g",label:"G"},{name:"b",label:"B"},{name:"hex",label:"#",value:"000000"},{name:"preview",type:"container",border:1}]}]},onSubmit:function(){c("#"+this.toJSON().hex)}});e(d)}a.settings.color_picker_callback||(a.settings.color_picker_callback=c)}),function(){}}),d("0")()}();
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginscompat3xpluginjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/compat3x/plugin.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/compat3x/plugin.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/compat3x/plugin.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2,7 +2,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * plugin.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -19,288 +19,301 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * - No editor.onEvent
</span><span class="cx" style="display: block; padding: 0 10px"> * - Can't cancel execCommands with beforeExecCommand
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-(function(tinymce) {
- var reported;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+(function (tinymce) {
+ var reported;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function noop() {
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function noop() {
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function log(apiCall) {
- if (!reported && window && window.console) {
- reported = true;
- console.log("Deprecated TinyMCE API call: " + apiCall);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function log(apiCall) {
+ if (!reported && window && window.console) {
+ reported = true;
+ console.log("Deprecated TinyMCE API call: " + apiCall);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function Dispatcher(target, newEventName, argsMap, defaultScope) {
- target = target || this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function Dispatcher(target, newEventName, argsMap, defaultScope) {
+ target = target || this;
+ var cbs = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!newEventName) {
- this.add = this.addToTop = this.remove = this.dispatch = noop;
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!newEventName) {
+ this.add = this.addToTop = this.remove = this.dispatch = noop;
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.add = function(callback, scope, prepend) {
- log('<target>.on' + newEventName + ".add(..)");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.add = function (callback, scope, prepend) {
+ log('<target>.on' + newEventName + ".add(..)");
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Convert callback({arg1:x, arg2:x}) -> callback(arg1, arg2)
- function patchedEventCallback(e) {
- var callbackArgs = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Convert callback({arg1:x, arg2:x}) -> callback(arg1, arg2)
+ function patchedEventCallback(e) {
+ var callbackArgs = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof argsMap == "string") {
- argsMap = argsMap.split(" ");
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof argsMap == "string") {
+ argsMap = argsMap.split(" ");
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (argsMap && typeof argsMap != "function") {
- for (var i = 0; i < argsMap.length; i++) {
- callbackArgs.push(e[argsMap[i]]);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (argsMap && typeof argsMap != "function") {
+ for (var i = 0; i < argsMap.length; i++) {
+ callbackArgs.push(e[argsMap[i]]);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof argsMap == "function") {
- callbackArgs = argsMap(newEventName, e, target);
- if (!callbackArgs) {
- return;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof argsMap == "function") {
+ callbackArgs = argsMap(newEventName, e, target);
+ if (!callbackArgs) {
+ return;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!argsMap) {
- callbackArgs = [e];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!argsMap) {
+ callbackArgs = [e];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- callbackArgs.unshift(defaultScope || target);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ callbackArgs.unshift(defaultScope || target);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (callback.apply(scope || defaultScope || target, callbackArgs) === false) {
- e.stopImmediatePropagation();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (callback.apply(scope || defaultScope || target, callbackArgs) === false) {
+ e.stopImmediatePropagation();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- target.on(newEventName, patchedEventCallback, prepend);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ target.on(newEventName, patchedEventCallback, prepend);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return patchedEventCallback;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var handlers = {
+ original: callback,
+ patched: patchedEventCallback
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.addToTop = function(callback, scope) {
- this.add(callback, scope, true);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ cbs.push(handlers);
+ return patchedEventCallback;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.remove = function(callback) {
- return target.off(newEventName, callback);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.addToTop = function (callback, scope) {
+ this.add(callback, scope, true);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.dispatch = function() {
- target.fire(newEventName);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.remove = function (callback) {
+ cbs.forEach(function (item, i) {
+ if (item.original === callback) {
+ cbs.splice(i, 1);
+ return target.off(newEventName, item.patched);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return target.off(newEventName, callback);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tinymce.util.Dispatcher = Dispatcher;
- tinymce.onBeforeUnload = new Dispatcher(tinymce, "BeforeUnload");
- tinymce.onAddEditor = new Dispatcher(tinymce, "AddEditor", "editor");
- tinymce.onRemoveEditor = new Dispatcher(tinymce, "RemoveEditor", "editor");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.dispatch = function () {
+ target.fire(newEventName);
+ return true;
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tinymce.util.Cookie = {
- get: noop, getHash: noop, remove: noop, set: noop, setHash: noop
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ tinymce.util.Dispatcher = Dispatcher;
+ tinymce.onBeforeUnload = new Dispatcher(tinymce, "BeforeUnload");
+ tinymce.onAddEditor = new Dispatcher(tinymce, "AddEditor", "editor");
+ tinymce.onRemoveEditor = new Dispatcher(tinymce, "RemoveEditor", "editor");
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function patchEditor(editor) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ tinymce.util.Cookie = {
+ get: noop, getHash: noop, remove: noop, set: noop, setHash: noop
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function translate(str) {
- var prefix = editor.settings.language || "en";
- var prefixedStr = [prefix, str].join('.');
- var translatedStr = tinymce.i18n.translate(prefixedStr);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function patchEditor(editor) {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return prefixedStr !== translatedStr ? translatedStr : tinymce.i18n.translate(str);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function translate(str) {
+ var prefix = editor.settings.language || "en";
+ var prefixedStr = [prefix, str].join('.');
+ var translatedStr = tinymce.i18n.translate(prefixedStr);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function patchEditorEvents(oldEventNames, argsMap) {
- tinymce.each(oldEventNames.split(" "), function(oldName) {
- editor["on" + oldName] = new Dispatcher(editor, oldName, argsMap);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return prefixedStr !== translatedStr ? translatedStr : tinymce.i18n.translate(str);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function convertUndoEventArgs(type, event, target) {
- return [
- event.level,
- target
- ];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function patchEditorEvents(oldEventNames, argsMap) {
+ tinymce.each(oldEventNames.split(" "), function (oldName) {
+ editor["on" + oldName] = new Dispatcher(editor, oldName, argsMap);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function filterSelectionEvents(needsSelection) {
- return function(type, e) {
- if ((!e.selection && !needsSelection) || e.selection == needsSelection) {
- return [e];
- }
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function convertUndoEventArgs(type, event, target) {
+ return [
+ event.level,
+ target
+ ];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.controlManager) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function filterSelectionEvents(needsSelection) {
+ return function (type, e) {
+ if ((!e.selection && !needsSelection) || e.selection == needsSelection) {
+ return [e];
+ }
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function cmNoop() {
- var obj = {}, methods = 'add addMenu addSeparator collapse createMenu destroy displayColor expand focus ' +
- 'getLength hasMenus hideMenu isActive isCollapsed isDisabled isRendered isSelected mark ' +
- 'postRender remove removeAll renderHTML renderMenu renderNode renderTo select selectByIndex ' +
- 'setActive setAriaProperty setColor setDisabled setSelected setState showMenu update';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.controlManager) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- log('editor.controlManager.*');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function cmNoop() {
+ var obj = {}, methods = 'add addMenu addSeparator collapse createMenu destroy displayColor expand focus ' +
+ 'getLength hasMenus hideMenu isActive isCollapsed isDisabled isRendered isSelected mark ' +
+ 'postRender remove removeAll renderHTML renderMenu renderNode renderTo select selectByIndex ' +
+ 'setActive setAriaProperty setColor setDisabled setSelected setState showMenu update';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function _noop() {
- return cmNoop();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ log('editor.controlManager.*');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tinymce.each(methods.split(' '), function(method) {
- obj[method] = _noop;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function _noop() {
+ return cmNoop();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return obj;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ tinymce.each(methods.split(' '), function (method) {
+ obj[method] = _noop;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.controlManager = {
- buttons: {},
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return obj;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- setDisabled: function(name, state) {
- log("controlManager.setDisabled(..)");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.controlManager = {
+ buttons: {},
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.buttons[name]) {
- this.buttons[name].disabled(state);
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ setDisabled: function (name, state) {
+ log("controlManager.setDisabled(..)");
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- setActive: function(name, state) {
- log("controlManager.setActive(..)");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.buttons[name]) {
+ this.buttons[name].disabled(state);
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.buttons[name]) {
- this.buttons[name].active(state);
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ setActive: function (name, state) {
+ log("controlManager.setActive(..)");
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- onAdd: new Dispatcher(),
- onPostRender: new Dispatcher(),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.buttons[name]) {
+ this.buttons[name].active(state);
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- add: function(obj) {
- return obj;
- },
- createButton: cmNoop,
- createColorSplitButton: cmNoop,
- createControl: cmNoop,
- createDropMenu: cmNoop,
- createListBox: cmNoop,
- createMenuButton: cmNoop,
- createSeparator: cmNoop,
- createSplitButton: cmNoop,
- createToolbar: cmNoop,
- createToolbarGroup: cmNoop,
- destroy: noop,
- get: noop,
- setControlType: cmNoop
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ onAdd: new Dispatcher(),
+ onPostRender: new Dispatcher(),
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- patchEditorEvents("PreInit BeforeRenderUI PostRender Load Init Remove Activate Deactivate", "editor");
- patchEditorEvents("Click MouseUp MouseDown DblClick KeyDown KeyUp KeyPress ContextMenu Paste Submit Reset");
- patchEditorEvents("BeforeExecCommand ExecCommand", "command ui value args"); // args.terminate not supported
- patchEditorEvents("PreProcess PostProcess LoadContent SaveContent Change");
- patchEditorEvents("BeforeSetContent BeforeGetContent SetContent GetContent", filterSelectionEvents(false));
- patchEditorEvents("SetProgressState", "state time");
- patchEditorEvents("VisualAid", "element hasVisual");
- patchEditorEvents("Undo Redo", convertUndoEventArgs);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ add: function (obj) {
+ return obj;
+ },
+ createButton: cmNoop,
+ createColorSplitButton: cmNoop,
+ createControl: cmNoop,
+ createDropMenu: cmNoop,
+ createListBox: cmNoop,
+ createMenuButton: cmNoop,
+ createSeparator: cmNoop,
+ createSplitButton: cmNoop,
+ createToolbar: cmNoop,
+ createToolbarGroup: cmNoop,
+ destroy: noop,
+ get: noop,
+ setControlType: cmNoop
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- patchEditorEvents("NodeChange", function(type, e) {
- return [
- editor.controlManager,
- e.element,
- editor.selection.isCollapsed(),
- e
- ];
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ patchEditorEvents("PreInit BeforeRenderUI PostRender Load Init Remove Activate Deactivate", "editor");
+ patchEditorEvents("Click MouseUp MouseDown DblClick KeyDown KeyUp KeyPress ContextMenu Paste Submit Reset");
+ patchEditorEvents("BeforeExecCommand ExecCommand", "command ui value args"); // args.terminate not supported
+ patchEditorEvents("PreProcess PostProcess LoadContent SaveContent Change");
+ patchEditorEvents("BeforeSetContent BeforeGetContent SetContent GetContent", filterSelectionEvents(false));
+ patchEditorEvents("SetProgressState", "state time");
+ patchEditorEvents("VisualAid", "element hasVisual");
+ patchEditorEvents("Undo Redo", convertUndoEventArgs);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var originalAddButton = editor.addButton;
- editor.addButton = function(name, settings) {
- var originalOnPostRender;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ patchEditorEvents("NodeChange", function (type, e) {
+ return [
+ editor.controlManager,
+ e.element,
+ editor.selection.isCollapsed(),
+ e
+ ];
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function patchedPostRender() {
- editor.controlManager.buttons[name] = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var originalAddButton = editor.addButton;
+ editor.addButton = function (name, settings) {
+ var originalOnPostRender;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (originalOnPostRender) {
- return originalOnPostRender.apply(this, arguments);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function patchedPostRender() {
+ editor.controlManager.buttons[name] = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var key in settings) {
- if (key.toLowerCase() === "onpostrender") {
- originalOnPostRender = settings[key];
- settings.onPostRender = patchedPostRender;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (originalOnPostRender) {
+ return originalOnPostRender.apply(this, arguments);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!originalOnPostRender) {
- settings.onPostRender = patchedPostRender;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (var key in settings) {
+ if (key.toLowerCase() === "onpostrender") {
+ originalOnPostRender = settings[key];
+ settings.onPostRender = patchedPostRender;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.title) {
- settings.title = translate(settings.title);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!originalOnPostRender) {
+ settings.onPostRender = patchedPostRender;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return originalAddButton.call(this, name, settings);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.title) {
+ settings.title = translate(settings.title);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('init', function() {
- var undoManager = editor.undoManager, selection = editor.selection;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return originalAddButton.call(this, name, settings);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- undoManager.onUndo = new Dispatcher(editor, "Undo", convertUndoEventArgs, null, undoManager);
- undoManager.onRedo = new Dispatcher(editor, "Redo", convertUndoEventArgs, null, undoManager);
- undoManager.onBeforeAdd = new Dispatcher(editor, "BeforeAddUndo", null, undoManager);
- undoManager.onAdd = new Dispatcher(editor, "AddUndo", null, undoManager);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('init', function () {
+ var undoManager = editor.undoManager, selection = editor.selection;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- selection.onBeforeGetContent = new Dispatcher(editor, "BeforeGetContent", filterSelectionEvents(true), selection);
- selection.onGetContent = new Dispatcher(editor, "GetContent", filterSelectionEvents(true), selection);
- selection.onBeforeSetContent = new Dispatcher(editor, "BeforeSetContent", filterSelectionEvents(true), selection);
- selection.onSetContent = new Dispatcher(editor, "SetContent", filterSelectionEvents(true), selection);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ undoManager.onUndo = new Dispatcher(editor, "Undo", convertUndoEventArgs, null, undoManager);
+ undoManager.onRedo = new Dispatcher(editor, "Redo", convertUndoEventArgs, null, undoManager);
+ undoManager.onBeforeAdd = new Dispatcher(editor, "BeforeAddUndo", null, undoManager);
+ undoManager.onAdd = new Dispatcher(editor, "AddUndo", null, undoManager);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('BeforeRenderUI', function() {
- var windowManager = editor.windowManager;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ selection.onBeforeGetContent = new Dispatcher(editor, "BeforeGetContent", filterSelectionEvents(true), selection);
+ selection.onGetContent = new Dispatcher(editor, "GetContent", filterSelectionEvents(true), selection);
+ selection.onBeforeSetContent = new Dispatcher(editor, "BeforeSetContent", filterSelectionEvents(true), selection);
+ selection.onSetContent = new Dispatcher(editor, "SetContent", filterSelectionEvents(true), selection);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- windowManager.onOpen = new Dispatcher();
- windowManager.onClose = new Dispatcher();
- windowManager.createInstance = function(className, a, b, c, d, e) {
- log("windowManager.createInstance(..)");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('BeforeRenderUI', function () {
+ var windowManager = editor.windowManager;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var constr = tinymce.resolve(className);
- return new constr(a, b, c, d, e);
- };
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ windowManager.onOpen = new Dispatcher();
+ windowManager.onClose = new Dispatcher();
+ windowManager.createInstance = function (className, a, b, c, d, e) {
+ log("windowManager.createInstance(..)");
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tinymce.on('SetupEditor', patchEditor);
- tinymce.PluginManager.add("compat3x", patchEditor);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var constr = tinymce.resolve(className);
+ return new constr(a, b, c, d, e);
+ };
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tinymce.addI18n = function(prefix, o) {
- var I18n = tinymce.util.I18n, each = tinymce.each;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ tinymce.on('SetupEditor', patchEditor);
+ tinymce.PluginManager.add("compat3x", patchEditor);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof prefix == "string" && prefix.indexOf('.') === -1) {
- I18n.add(prefix, o);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ tinymce.addI18n = function (prefix, o) {
+ var I18n = tinymce.util.I18n, each = tinymce.each;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!tinymce.is(prefix, 'string')) {
- each(prefix, function(o, lc) {
- each(o, function(o, g) {
- each(o, function(o, k) {
- if (g === 'common') {
- I18n.data[lc + '.' + k] = o;
- } else {
- I18n.data[lc + '.' + g + '.' + k] = o;
- }
- });
- });
- });
- } else {
- each(o, function(o, k) {
- I18n.data[prefix + '.' + k] = o;
- });
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof prefix == "string" && prefix.indexOf('.') === -1) {
+ I18n.add(prefix, o);
+ return;
+ }
+
+ if (!tinymce.is(prefix, 'string')) {
+ each(prefix, function (o, lc) {
+ each(o, function (o, g) {
+ each(o, function (o, k) {
+ if (g === 'common') {
+ I18n.data[lc + '.' + k] = o;
+ } else {
+ I18n.data[lc + '.' + g + '.' + k] = o;
+ }
+ });
+ });
+ });
+ } else {
+ each(o, function (o, k) {
+ I18n.data[prefix + '.' + k] = o;
+ });
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px"> })(tinymce);
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginscompat3xpluginminjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/compat3x/plugin.min.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/compat3x/plugin.min.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/compat3x/plugin.min.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1 +1 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-!function(e){function t(){}function n(e){!o&&window&&window.console&&(o=!0,console.log("Deprecated TinyMCE API call: "+e))}function r(e,r,i,o){return e=e||this,r?(this.add=function(t,a,s){function l(n){var s=[];if("string"==typeof i&&(i=i.split(" ")),i&&"function"!=typeof i)for(var l=0;l<i.length;l++)s.push(n[i[l]]);("function"!=typeof i||(s=i(r,n,e)))&&(i||(s=[n]),s.unshift(o||e),t.apply(a||o||e,s)===!1&&n.stopImmediatePropagation())}return n("<target>.on"+r+".add(..)"),e.on(r,l,s),l},this.addToTop=function(e,t){this.add(e,t,!0)},this.remove=function(t){return e.off(r,t)},void(this.dispatch=function(){return e.fire(r),!0})):void(this.add=this.addToTop=this.remove=this.dispatch=t)}function i(i){function o(t){var n=i.settings.language||"en",r=[n,
t].join("."),o=e.i18n.translate(r);return r!==o?o:e.i18n.translate(t)}function a(t,n){e.each(t.split(" "),function(e){i["on"+e]=new r(i,e,n)})}function s(e,t,n){return[t.level,n]}function l(e){return function(t,n){if(!n.selection&&!e||n.selection==e)return[n]}}function u(){function t(){return u()}var r={},i="add addMenu addSeparator collapse createMenu destroy displayColor expand focus getLength hasMenus hideMenu isActive isCollapsed isDisabled isRendered isSelected mark postRender remove removeAll renderHTML renderMenu renderNode renderTo select selectByIndex setActive setAriaProperty setColor setDisabled setSelected setState showMenu update";return n("editor.controlManager.*"),e.each(i.split(" "),function(e){r[e]=t}),r}if(!i.controlManager){i.controlManager={buttons:{},setDisabled:function(e,t){n("controlManager.setDisabled(..)"),this.buttons[e]&&this.buttons[e].disabled(t)},setActive:function(e,
t){n("controlManager.setActive(..)"),this.buttons[e]&&this.buttons[e].active(t)},onAdd:new r,onPostRender:new r,add:function(e){return e},createButton:u,createColorSplitButton:u,createControl:u,createDropMenu:u,createListBox:u,createMenuButton:u,createSeparator:u,createSplitButton:u,createToolbar:u,createToolbarGroup:u,destroy:t,get:t,setControlType:u},a("PreInit BeforeRenderUI PostRender Load Init Remove Activate Deactivate","editor"),a("Click MouseUp MouseDown DblClick KeyDown KeyUp KeyPress ContextMenu Paste Submit Reset"),a("BeforeExecCommand ExecCommand","command ui value args"),a("PreProcess PostProcess LoadContent SaveContent Change"),a("BeforeSetContent BeforeGetContent SetContent GetContent",l(!1)),a("SetProgressState","state time"),a("VisualAid","element hasVisual"),a("Undo Redo",s),a("NodeChange",function(e,t){return[i.control
Manager,t.element,i.selection.isCollapsed(),t]});var c=i.addButton;i.addButton=function(e,t){function n(){if(i.controlManager.buttons[e]=this,r)return r.apply(this,arguments)}var r;for(var a in t)"onpostrender"===a.toLowerCase()&&(r=t[a],t.onPostRender=n);return r||(t.onPostRender=n),t.title&&(t.title=o(t.title)),c.call(this,e,t)},i.on("init",function(){var e=i.undoManager,t=i.selection;e.onUndo=new r(i,"Undo",s,null,e),e.onRedo=new r(i,"Redo",s,null,e),e.onBeforeAdd=new r(i,"BeforeAddUndo",null,e),e.onAdd=new r(i,"AddUndo",null,e),t.onBeforeGetContent=new r(i,"BeforeGetContent",l(!0),t),t.onGetContent=new r(i,"GetContent",l(!0),t),t.onBeforeSetContent=new r(i,"BeforeSetContent",l(!0),t),t.onSetContent=new r(i,"SetContent",l(!0),t)}),i.on("BeforeRenderUI",function(){var t=i.windowManager;t.onOpen=new r,t.onClose=new r,t.createInstance=function(t,r,i,o,a,s){n(
"windowManager.createInstance(..)");var l=e.resolve(t);return new l(r,i,o,a,s)}})}}var o;e.util.Dispatcher=r,e.onBeforeUnload=new r(e,"BeforeUnload"),e.onAddEditor=new r(e,"AddEditor","editor"),e.onRemoveEditor=new r(e,"RemoveEditor","editor"),e.util.Cookie={get:t,getHash:t,remove:t,set:t,setHash:t},e.on("SetupEditor",i),e.PluginManager.add("compat3x",i),e.addI18n=function(t,n){var r=e.util.I18n,i=e.each;return"string"==typeof t&&t.indexOf(".")===-1?void r.add(t,n):void(e.is(t,"string")?i(n,function(e,n){r.data[t+"."+n]=e}):i(t,function(e,t){i(e,function(e,n){i(e,function(e,i){"common"===n?r.data[t+"."+i]=e:r.data[t+"."+n+"."+i]=e})})}))}}(tinymce);
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+!function(a){function b(){}function c(a){!f&&window&&window.console&&(f=!0,console.log("Deprecated TinyMCE API call: "+a))}function d(a,d,e,f){a=a||this;var g=[];return d?(this.add=function(b,h,i){function j(c){var g=[];if("string"==typeof e&&(e=e.split(" ")),e&&"function"!=typeof e)for(var i=0;i<e.length;i++)g.push(c[e[i]]);("function"!=typeof e||(g=e(d,c,a)))&&(e||(g=[c]),g.unshift(f||a),b.apply(h||f||a,g)===!1&&c.stopImmediatePropagation())}c("<target>.on"+d+".add(..)"),a.on(d,j,i);var k={original:b,patched:j};return g.push(k),j},this.addToTop=function(a,b){this.add(a,b,!0)},this.remove=function(b){return g.forEach(function(c,e){if(c.original===b)return g.splice(e,1),a.off(d,c.patched)}),a.off(d,b)},void(this.dispatch=function(){return a.fire(d),!0})):
void(this.add=this.addToTop=this.remove=this.dispatch=b)}function e(e){function f(b){var c=e.settings.language||"en",d=[c,b].join("."),f=a.i18n.translate(d);return d!==f?f:a.i18n.translate(b)}function g(b,c){a.each(b.split(" "),function(a){e["on"+a]=new d(e,a,c)})}function h(a,b,c){return[b.level,c]}function i(a){return function(b,c){if(!c.selection&&!a||c.selection==a)return[c]}}function j(){function b(){return j()}var d={},e="add addMenu addSeparator collapse createMenu destroy displayColor expand focus getLength hasMenus hideMenu isActive isCollapsed isDisabled isRendered isSelected mark postRender remove removeAll renderHTML renderMenu renderNode renderTo select selectByIndex setActive setAriaProperty setColor setDisabled setSelected setState showMenu update";return c("editor.controlManager.*"),a.each(e.split(" "),function(a){d[a]=b}),d}if(!e.controlManager){e.controlManager={buttons:{},setDisabled:fun
ction(a,b){c("controlManager.setDisabled(..)"),this.buttons[a]&&this.buttons[a].disabled(b)},setActive:function(a,b){c("controlManager.setActive(..)"),this.buttons[a]&&this.buttons[a].active(b)},onAdd:new d,onPostRender:new d,add:function(a){return a},createButton:j,createColorSplitButton:j,createControl:j,createDropMenu:j,createListBox:j,createMenuButton:j,createSeparator:j,createSplitButton:j,createToolbar:j,createToolbarGroup:j,destroy:b,get:b,setControlType:j},g("PreInit BeforeRenderUI PostRender Load Init Remove Activate Deactivate","editor"),g("Click MouseUp MouseDown DblClick KeyDown KeyUp KeyPress ContextMenu Paste Submit Reset"),g("BeforeExecCommand ExecCommand","command ui value args"),g("PreProcess PostProcess LoadContent SaveContent Change"),g("BeforeSetContent BeforeGetContent SetContent GetContent",i(!1)),g("SetProgressState","state time"),g(&qu
ot;VisualAid","element hasVisual"),g("Undo Redo",h),g("NodeChange",function(a,b){return[e.controlManager,b.element,e.selection.isCollapsed(),b]});var k=e.addButton;e.addButton=function(a,b){function c(){if(e.controlManager.buttons[a]=this,d)return d.apply(this,arguments)}var d;for(var g in b)"onpostrender"===g.toLowerCase()&&(d=b[g],b.onPostRender=c);return d||(b.onPostRender=c),b.title&&(b.title=f(b.title)),k.call(this,a,b)},e.on("init",function(){var a=e.undoManager,b=e.selection;a.onUndo=new d(e,"Undo",h,null,a),a.onRedo=new d(e,"Redo",h,null,a),a.onBeforeAdd=new d(e,"BeforeAddUndo",null,a),a.onAdd=new d(e,"AddUndo",null,a),b.onBeforeGetContent=new d(e,"BeforeGetContent",i(!0),b),b.onGetContent=new d(e,"GetContent",i(!0),b),b.onBeforeSetContent=new d(e,"BeforeSetContent",i(!0),b),b.onSetContent=new d(e,"SetContent",i(!0),b)}),e.on(
"BeforeRenderUI",function(){var b=e.windowManager;b.onOpen=new d,b.onClose=new d,b.createInstance=function(b,d,e,f,g,h){c("windowManager.createInstance(..)");var i=a.resolve(b);return new i(d,e,f,g,h)}})}}var f;a.util.Dispatcher=d,a.onBeforeUnload=new d(a,"BeforeUnload"),a.onAddEditor=new d(a,"AddEditor","editor"),a.onRemoveEditor=new d(a,"RemoveEditor","editor"),a.util.Cookie={get:b,getHash:b,remove:b,set:b,setHash:b},a.on("SetupEditor",e),a.PluginManager.add("compat3x",e),a.addI18n=function(b,c){var d=a.util.I18n,e=a.each;return"string"==typeof b&&b.indexOf(".")===-1?void d.add(b,c):void(a.is(b,"string")?e(c,function(a,c){d.data[b+"."+c]=a}):e(b,function(a,b){e(a,function(a,c){e(a,function(a,e){"common"===c?d.data[b+"."+e]=a:d.data[b+"."+c+"."+e]=a})})}))}}(tinymce);
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginsdirectionalitypluginjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/directionality/plugin.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/directionality/plugin.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/directionality/plugin.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,64 +1,207 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+(function () {
+
+var defs = {}; // id -> {dependencies, definition, instance (possibly undefined)}
+
+// Used when there is no 'main' module.
+// The name is probably (hopefully) unique so minification removes for releases.
+var register_3795 = function (id) {
+ var module = dem(id);
+ var fragments = id.split('.');
+ var target = Function('return this;')();
+ for (var i = 0; i < fragments.length - 1; ++i) {
+ if (target[fragments[i]] === undefined)
+ target[fragments[i]] = {};
+ target = target[fragments[i]];
+ }
+ target[fragments[fragments.length - 1]] = module;
+};
+
+var instantiate = function (id) {
+ var actual = defs[id];
+ var dependencies = actual.deps;
+ var definition = actual.defn;
+ var len = dependencies.length;
+ var instances = new Array(len);
+ for (var i = 0; i < len; ++i)
+ instances[i] = dem(dependencies[i]);
+ var defResult = definition.apply(null, instances);
+ if (defResult === undefined)
+ throw 'module [' + id + '] returned undefined';
+ actual.instance = defResult;
+};
+
+var def = function (id, dependencies, definition) {
+ if (typeof id !== 'string')
+ throw 'module id must be a string';
+ else if (dependencies === undefined)
+ throw 'no dependencies for ' + id;
+ else if (definition === undefined)
+ throw 'no definition function for ' + id;
+ defs[id] = {
+ deps: dependencies,
+ defn: definition,
+ instance: undefined
+ };
+};
+
+var dem = function (id) {
+ var actual = defs[id];
+ if (actual === undefined)
+ throw 'module [' + id + '] was undefined';
+ else if (actual.instance === undefined)
+ instantiate(id);
+ return actual.instance;
+};
+
+var req = function (ids, callback) {
+ var len = ids.length;
+ var instances = new Array(len);
+ for (var i = 0; i < len; ++i)
+ instances.push(dem(ids[i]));
+ callback.apply(null, callback);
+};
+
+var ephox = {};
+
+ephox.bolt = {
+ module: {
+ api: {
+ define: def,
+ require: req,
+ demand: dem
+ }
+ }
+};
+
+var define = def;
+var require = req;
+var demand = dem;
+// this helps with minificiation when using a lot of global references
+var defineGlobal = function (id, ref) {
+ define(id, [], function () { return ref; });
+};
+/*jsc
+["tinymce.plugins.directionality.Plugin","tinymce.core.PluginManager","tinymce.core.util.Tools","global!tinymce.util.Tools.resolve"]
+jsc*/
+defineGlobal("global!tinymce.util.Tools.resolve", tinymce.util.Tools.resolve);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * plugin.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ResolveGlobal.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/*global tinymce:true */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.PluginManager',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.PluginManager');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-tinymce.PluginManager.add('directionality', function(editor) {
- function setDir(dir) {
- var dom = editor.dom, curDir, blocks = editor.selection.getSelectedBlocks();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (blocks.length) {
- curDir = dom.getAttrib(blocks[0], "dir");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.Tools',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.util.Tools');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tinymce.each(blocks, function(block) {
- // Add dir to block if the parent block doesn't already have that dir
- if (!dom.getParent(block.parentNode, "*[dir='" + dir + "']", dom.getRoot())) {
- if (curDir != dir) {
- dom.setAttrib(block, "dir", dir);
- } else {
- dom.setAttrib(block, "dir", null);
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Plugin.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.nodeChanged();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * This class contains all core logic for the directionality plugin.
+ *
+ * @class tinymce.directionality.Plugin
+ * @private
+ */
+define(
+ 'tinymce.plugins.directionality.Plugin',
+ [
+ 'tinymce.core.PluginManager',
+ 'tinymce.core.util.Tools'
+ ],
+ function (PluginManager, Tools) {
+ PluginManager.add('directionality', function (editor) {
+ function setDir(dir) {
+ var dom = editor.dom, curDir, blocks = editor.selection.getSelectedBlocks();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function generateSelector(dir) {
- var selector = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (blocks.length) {
+ curDir = dom.getAttrib(blocks[0], "dir");
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tinymce.each('h1 h2 h3 h4 h5 h6 div p'.split(' '), function(name) {
- selector.push(name + '[dir=' + dir + ']');
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(blocks, function (block) {
+ // Add dir to block if the parent block doesn't already have that dir
+ if (!dom.getParent(block.parentNode, "*[dir='" + dir + "']", dom.getRoot())) {
+ if (curDir != dir) {
+ dom.setAttrib(block, "dir", dir);
+ } else {
+ dom.setAttrib(block, "dir", null);
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return selector.join(',');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.nodeChanged();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addCommand('mceDirectionLTR', function() {
- setDir("ltr");
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function generateSelector(dir) {
+ var selector = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addCommand('mceDirectionRTL', function() {
- setDir("rtl");
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each('h1 h2 h3 h4 h5 h6 div p'.split(' '), function (name) {
+ selector.push(name + '[dir=' + dir + ']');
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addButton('ltr', {
- title: 'Left to right',
- cmd: 'mceDirectionLTR',
- stateSelector: generateSelector('ltr')
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return selector.join(',');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addButton('rtl', {
- title: 'Right to left',
- cmd: 'mceDirectionRTL',
- stateSelector: generateSelector('rtl')
- });
-});
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addCommand('mceDirectionLTR', function () {
+ setDir("ltr");
+ });
+
+ editor.addCommand('mceDirectionRTL', function () {
+ setDir("rtl");
+ });
+
+ editor.addButton('ltr', {
+ title: 'Left to right',
+ cmd: 'mceDirectionLTR',
+ stateSelector: generateSelector('ltr')
+ });
+
+ editor.addButton('rtl', {
+ title: 'Right to left',
+ cmd: 'mceDirectionRTL',
+ stateSelector: generateSelector('rtl')
+ });
+ });
+
+ return function () { };
+ }
+);
+dem('tinymce.plugins.directionality.Plugin')();
+})();
</ins></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginsdirectionalitypluginminjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/directionality/plugin.min.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/directionality/plugin.min.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/directionality/plugin.min.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1 +1 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-tinymce.PluginManager.add("directionality",function(e){function t(t){var n,r=e.dom,i=e.selection.getSelectedBlocks();i.length&&(n=r.getAttrib(i[0],"dir"),tinymce.each(i,function(e){r.getParent(e.parentNode,"*[dir='"+t+"']",r.getRoot())||(n!=t?r.setAttrib(e,"dir",t):r.setAttrib(e,"dir",null))}),e.nodeChanged())}function n(e){var t=[];return tinymce.each("h1 h2 h3 h4 h5 h6 div p".split(" "),function(n){t.push(n+"[dir="+e+"]")}),t.join(",")}e.addCommand("mceDirectionLTR",function(){t("ltr")}),e.addCommand("mceDirectionRTL",function(){t("rtl")}),e.addButton("ltr",{title:"Left to right",cmd:"mceDirectionLTR",stateSelector:n("ltr")}),e.addButton("rtl",{title:"Right to left",cmd:&
quot;mceDirectionRTL",stateSelector:n("rtl")})});
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+!function(){var a={},b=function(b){for(var c=a[b],e=c.deps,f=c.defn,g=e.length,h=new Array(g),i=0;i<g;++i)h[i]=d(e[i]);var j=f.apply(null,h);if(void 0===j)throw"module ["+b+"] returned undefined";c.instance=j},c=function(b,c,d){if("string"!=typeof b)throw"module id must be a string";if(void 0===c)throw"no dependencies for "+b;if(void 0===d)throw"no definition function for "+b;a[b]={deps:c,defn:d,instance:void 0}},d=function(c){var d=a[c];if(void 0===d)throw"module ["+c+"] was undefined";return void 0===d.instance&&b(c),d.instance},e=function(a,b){for(var c=a.length,e=new Array(c),f=0;f<c;++f)e.push(d(a[f]));b.apply(null,b)},f={};f.bolt={module:{api:{define:c,require:e,demand:d}}};var g=c,h=function(a,b){g(a,[],function(){return b})};h("3",tinymce.util.Tools.resolve),g("1",[&q
uot;3"],function(a){return a("tinymce.PluginManager")}),g("2",["3"],function(a){return a("tinymce.util.Tools")}),g("0",["1","2"],function(a,b){return a.add("directionality",function(a){function c(c){var d,e=a.dom,f=a.selection.getSelectedBlocks();f.length&&(d=e.getAttrib(f[0],"dir"),b.each(f,function(a){e.getParent(a.parentNode,"*[dir='"+c+"']",e.getRoot())||(d!=c?e.setAttrib(a,"dir",c):e.setAttrib(a,"dir",null))}),a.nodeChanged())}function d(a){var c=[];return b.each("h1 h2 h3 h4 h5 h6 div p".split(" "),function(b){c.push(b+"[dir="+a+"]")}),c.join(",")}a.addCommand("mceDirectionLTR",function(){c("ltr")}),a.addCommand("mceDirectionRTL",function(){c("rtl")}),a.addButton("ltr",{title:"Left to right",cmd:"mceDirectionLTR",state
Selector:d("ltr")}),a.addButton("rtl",{title:"Right to left",cmd:"mceDirectionRTL",stateSelector:d("rtl")})}),function(){}}),d("0")()}();
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginsfullscreenpluginjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/fullscreen/plugin.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/fullscreen/plugin.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/fullscreen/plugin.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,154 +1,299 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+(function () {
+
+var defs = {}; // id -> {dependencies, definition, instance (possibly undefined)}
+
+// Used when there is no 'main' module.
+// The name is probably (hopefully) unique so minification removes for releases.
+var register_3795 = function (id) {
+ var module = dem(id);
+ var fragments = id.split('.');
+ var target = Function('return this;')();
+ for (var i = 0; i < fragments.length - 1; ++i) {
+ if (target[fragments[i]] === undefined)
+ target[fragments[i]] = {};
+ target = target[fragments[i]];
+ }
+ target[fragments[fragments.length - 1]] = module;
+};
+
+var instantiate = function (id) {
+ var actual = defs[id];
+ var dependencies = actual.deps;
+ var definition = actual.defn;
+ var len = dependencies.length;
+ var instances = new Array(len);
+ for (var i = 0; i < len; ++i)
+ instances[i] = dem(dependencies[i]);
+ var defResult = definition.apply(null, instances);
+ if (defResult === undefined)
+ throw 'module [' + id + '] returned undefined';
+ actual.instance = defResult;
+};
+
+var def = function (id, dependencies, definition) {
+ if (typeof id !== 'string')
+ throw 'module id must be a string';
+ else if (dependencies === undefined)
+ throw 'no dependencies for ' + id;
+ else if (definition === undefined)
+ throw 'no definition function for ' + id;
+ defs[id] = {
+ deps: dependencies,
+ defn: definition,
+ instance: undefined
+ };
+};
+
+var dem = function (id) {
+ var actual = defs[id];
+ if (actual === undefined)
+ throw 'module [' + id + '] was undefined';
+ else if (actual.instance === undefined)
+ instantiate(id);
+ return actual.instance;
+};
+
+var req = function (ids, callback) {
+ var len = ids.length;
+ var instances = new Array(len);
+ for (var i = 0; i < len; ++i)
+ instances.push(dem(ids[i]));
+ callback.apply(null, callback);
+};
+
+var ephox = {};
+
+ephox.bolt = {
+ module: {
+ api: {
+ define: def,
+ require: req,
+ demand: dem
+ }
+ }
+};
+
+var define = def;
+var require = req;
+var demand = dem;
+// this helps with minificiation when using a lot of global references
+var defineGlobal = function (id, ref) {
+ define(id, [], function () { return ref; });
+};
+/*jsc
+["tinymce.plugins.fullscreen.Plugin","tinymce.core.dom.DOMUtils","tinymce.core.PluginManager","global!tinymce.util.Tools.resolve"]
+jsc*/
+defineGlobal("global!tinymce.util.Tools.resolve", tinymce.util.Tools.resolve);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * plugin.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ResolveGlobal.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/*global tinymce:true */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.DOMUtils',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.dom.DOMUtils');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-tinymce.PluginManager.add('fullscreen', function(editor) {
- var fullscreenState = false, DOM = tinymce.DOM, iframeWidth, iframeHeight, resizeHandler;
- var containerWidth, containerHeight, scrollPos;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.settings.inline) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.PluginManager',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.PluginManager');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getWindowSize() {
- var w, h, win = window, doc = document;
- var body = doc.body;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Plugin.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Old IE
- if (body.offsetWidth) {
- w = body.offsetWidth;
- h = body.offsetHeight;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * This class contains all core logic for the fullscreen plugin.
+ *
+ * @class tinymce.fullscreen.Plugin
+ * @private
+ */
+define(
+ 'tinymce.plugins.fullscreen.Plugin',
+ [
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.core.PluginManager'
+ ],
+ function (DOMUtils, PluginManager) {
+ var DOM = DOMUtils.DOM;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Modern browsers
- if (win.innerWidth && win.innerHeight) {
- w = win.innerWidth;
- h = win.innerHeight;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ PluginManager.add('fullscreen', function (editor) {
+ var fullscreenState = false, iframeWidth, iframeHeight, resizeHandler;
+ var containerWidth, containerHeight, scrollPos;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {w: w, h: h};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.settings.inline) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getScrollPos() {
- var vp = tinymce.DOM.getViewPort();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getWindowSize() {
+ var w, h, win = window, doc = document;
+ var body = doc.body;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- x: vp.x,
- y: vp.y
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Old IE
+ if (body.offsetWidth) {
+ w = body.offsetWidth;
+ h = body.offsetHeight;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setScrollPos(pos) {
- scrollTo(pos.x, pos.y);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Modern browsers
+ if (win.innerWidth && win.innerHeight) {
+ w = win.innerWidth;
+ h = win.innerHeight;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function toggleFullscreen() {
- var body = document.body, documentElement = document.documentElement, editorContainerStyle;
- var editorContainer, iframe, iframeStyle;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return { w: w, h: h };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function resize() {
- DOM.setStyle(iframe, 'height', getWindowSize().h - (editorContainer.clientHeight - iframe.clientHeight));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getScrollPos() {
+ var vp = DOM.getViewPort();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- fullscreenState = !fullscreenState;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ x: vp.x,
+ y: vp.y
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editorContainer = editor.getContainer();
- editorContainerStyle = editorContainer.style;
- iframe = editor.getContentAreaContainer().firstChild;
- iframeStyle = iframe.style;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setScrollPos(pos) {
+ window.scrollTo(pos.x, pos.y);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (fullscreenState) {
- scrollPos = getScrollPos();
- iframeWidth = iframeStyle.width;
- iframeHeight = iframeStyle.height;
- iframeStyle.width = iframeStyle.height = '100%';
- containerWidth = editorContainerStyle.width;
- containerHeight = editorContainerStyle.height;
- editorContainerStyle.width = editorContainerStyle.height = '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function toggleFullscreen() {
+ var body = document.body, documentElement = document.documentElement, editorContainerStyle;
+ var editorContainer, iframe, iframeStyle;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DOM.addClass(body, 'mce-fullscreen');
- DOM.addClass(documentElement, 'mce-fullscreen');
- DOM.addClass(editorContainer, 'mce-fullscreen');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function resize() {
+ DOM.setStyle(iframe, 'height', getWindowSize().h - (editorContainer.clientHeight - iframe.clientHeight));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DOM.bind(window, 'resize', resize);
- resize();
- resizeHandler = resize;
- } else {
- iframeStyle.width = iframeWidth;
- iframeStyle.height = iframeHeight;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ fullscreenState = !fullscreenState;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (containerWidth) {
- editorContainerStyle.width = containerWidth;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editorContainer = editor.getContainer();
+ editorContainerStyle = editorContainer.style;
+ iframe = editor.getContentAreaContainer().firstChild;
+ iframeStyle = iframe.style;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (containerHeight) {
- editorContainerStyle.height = containerHeight;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (fullscreenState) {
+ scrollPos = getScrollPos();
+ iframeWidth = iframeStyle.width;
+ iframeHeight = iframeStyle.height;
+ iframeStyle.width = iframeStyle.height = '100%';
+ containerWidth = editorContainerStyle.width;
+ containerHeight = editorContainerStyle.height;
+ editorContainerStyle.width = editorContainerStyle.height = '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DOM.removeClass(body, 'mce-fullscreen');
- DOM.removeClass(documentElement, 'mce-fullscreen');
- DOM.removeClass(editorContainer, 'mce-fullscreen');
- DOM.unbind(window, 'resize', resizeHandler);
- setScrollPos(scrollPos);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOM.addClass(body, 'mce-fullscreen');
+ DOM.addClass(documentElement, 'mce-fullscreen');
+ DOM.addClass(editorContainer, 'mce-fullscreen');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.fire('FullscreenStateChanged', {state: fullscreenState});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOM.bind(window, 'resize', resize);
+ resize();
+ resizeHandler = resize;
+ } else {
+ iframeStyle.width = iframeWidth;
+ iframeStyle.height = iframeHeight;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('init', function() {
- editor.addShortcut('Ctrl+Shift+F', '', toggleFullscreen);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (containerWidth) {
+ editorContainerStyle.width = containerWidth;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('remove', function() {
- if (resizeHandler) {
- DOM.unbind(window, 'resize', resizeHandler);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (containerHeight) {
+ editorContainerStyle.height = containerHeight;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addCommand('mceFullScreen', toggleFullscreen);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOM.removeClass(body, 'mce-fullscreen');
+ DOM.removeClass(documentElement, 'mce-fullscreen');
+ DOM.removeClass(editorContainer, 'mce-fullscreen');
+ DOM.unbind(window, 'resize', resizeHandler);
+ setScrollPos(scrollPos);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addMenuItem('fullscreen', {
- text: 'Fullscreen',
- shortcut: 'Ctrl+Shift+F',
- selectable: true,
- onClick: function() {
- toggleFullscreen();
- editor.focus();
- },
- onPostRender: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.fire('FullscreenStateChanged', { state: fullscreenState });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('FullscreenStateChanged', function(e) {
- self.active(e.state);
- });
- },
- context: 'view'
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('init', function () {
+ editor.addShortcut('Ctrl+Shift+F', '', toggleFullscreen);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addButton('fullscreen', {
- tooltip: 'Fullscreen',
- shortcut: 'Ctrl+Shift+F',
- onClick: toggleFullscreen,
- onPostRender: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('remove', function () {
+ if (resizeHandler) {
+ DOM.unbind(window, 'resize', resizeHandler);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('FullscreenStateChanged', function(e) {
- self.active(e.state);
- });
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addCommand('mceFullScreen', toggleFullscreen);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- isFullscreen: function() {
- return fullscreenState;
- }
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addMenuItem('fullscreen', {
+ text: 'Fullscreen',
+ shortcut: 'Ctrl+Shift+F',
+ selectable: true,
+ onClick: function () {
+ toggleFullscreen();
+ editor.focus();
+ },
+ onPostRender: function () {
+ var self = this;
+
+ editor.on('FullscreenStateChanged', function (e) {
+ self.active(e.state);
+ });
+ },
+ context: 'view'
+ });
+
+ editor.addButton('fullscreen', {
+ tooltip: 'Fullscreen',
+ shortcut: 'Ctrl+Shift+F',
+ onClick: toggleFullscreen,
+ onPostRender: function () {
+ var self = this;
+
+ editor.on('FullscreenStateChanged', function (e) {
+ self.active(e.state);
+ });
+ }
+ });
+
+ return {
+ isFullscreen: function () {
+ return fullscreenState;
+ }
+ };
+ });
+
+ return function () { };
+ }
+);
+dem('tinymce.plugins.fullscreen.Plugin')();
+})();
</ins></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginsfullscreenpluginminjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/fullscreen/plugin.min.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/fullscreen/plugin.min.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/fullscreen/plugin.min.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1 +1 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-tinymce.PluginManager.add("fullscreen",function(e){function t(){var e,t,n=window,r=document,i=r.body;return i.offsetWidth&&(e=i.offsetWidth,t=i.offsetHeight),n.innerWidth&&n.innerHeight&&(e=n.innerWidth,t=n.innerHeight),{w:e,h:t}}function n(){var e=tinymce.DOM.getViewPort();return{x:e.x,y:e.y}}function r(e){scrollTo(e.x,e.y)}function i(){function i(){f.setStyle(m,"height",t().h-(h.clientHeight-m.clientHeight))}var p,h,m,g,v=document.body,y=document.documentElement;d=!d,h=e.getContainer(),p=h.style,m=e.getContentAreaContainer().firstChild,g=m.style,d?(c=n(),o=g.width,a=g.height,g.width=g.height="100%",l=p.width,u=p.height,p.width=p.height="",f.addClass(v,"mce-fullscreen"),f.addClass(y,"mce-fullscreen"),f.addClass(h,"mce-fullscreen"),f.bind(window,"resize",i),i(),s=i):(g.width=o,g.height
=a,l&&(p.width=l),u&&(p.height=u),f.removeClass(v,"mce-fullscreen"),f.removeClass(y,"mce-fullscreen"),f.removeClass(h,"mce-fullscreen"),f.unbind(window,"resize",s),r(c)),e.fire("FullscreenStateChanged",{state:d})}var o,a,s,l,u,c,d=!1,f=tinymce.DOM;if(!e.settings.inline)return e.on("init",function(){e.addShortcut("Ctrl+Shift+F","",i)}),e.on("remove",function(){s&&f.unbind(window,"resize",s)}),e.addCommand("mceFullScreen",i),e.addMenuItem("fullscreen",{text:"Fullscreen",shortcut:"Ctrl+Shift+F",selectable:!0,onClick:function(){i(),e.focus()},onPostRender:function(){var t=this;e.on("FullscreenStateChanged",function(e){t.active(e.state)})},context:"view"}),e.addButton("fullscreen",{tooltip:"Fullscreen",shortcut:"Ctrl+Shift+F",onClick:i,onPostRender:function(){var t=this;e.on(&q
uot;FullscreenStateChanged",function(e){t.active(e.state)})}}),{isFullscreen:function(){return d}}});
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+!function(){var a={},b=function(b){for(var c=a[b],e=c.deps,f=c.defn,g=e.length,h=new Array(g),i=0;i<g;++i)h[i]=d(e[i]);var j=f.apply(null,h);if(void 0===j)throw"module ["+b+"] returned undefined";c.instance=j},c=function(b,c,d){if("string"!=typeof b)throw"module id must be a string";if(void 0===c)throw"no dependencies for "+b;if(void 0===d)throw"no definition function for "+b;a[b]={deps:c,defn:d,instance:void 0}},d=function(c){var d=a[c];if(void 0===d)throw"module ["+c+"] was undefined";return void 0===d.instance&&b(c),d.instance},e=function(a,b){for(var c=a.length,e=new Array(c),f=0;f<c;++f)e.push(d(a[f]));b.apply(null,b)},f={};f.bolt={module:{api:{define:c,require:e,demand:d}}};var g=c,h=function(a,b){g(a,[],function(){return b})};h("3",tinymce.util.Tools.resolve),g("1",[&q
uot;3"],function(a){return a("tinymce.dom.DOMUtils")}),g("2",["3"],function(a){return a("tinymce.PluginManager")}),g("0",["1","2"],function(a,b){var c=a.DOM;return b.add("fullscreen",function(a){function b(){var a,b,c=window,d=document,e=d.body;return e.offsetWidth&&(a=e.offsetWidth,b=e.offsetHeight),c.innerWidth&&c.innerHeight&&(a=c.innerWidth,b=c.innerHeight),{w:a,h:b}}function d(){var a=c.getViewPort();return{x:a.x,y:a.y}}function e(a){window.scrollTo(a.x,a.y)}function f(){function f(){c.setStyle(p,"height",b().h-(o.clientHeight-p.clientHeight))}var n,o,p,q,r=document.body,s=document.documentElement;m=!m,o=a.getContainer(),n=o.style,p=a.getContentAreaContainer().firstChild,q=p.style,m?(l=d(),g=q.width,h=q.height,q.width=q.height="100%",j=n.width,k=n.height,n.width=n.height="",c.addClass(r,"mce-fullscreen"),c.addClass(s,"mce-full
screen"),c.addClass(o,"mce-fullscreen"),c.bind(window,"resize",f),f(),i=f):(q.width=g,q.height=h,j&&(n.width=j),k&&(n.height=k),c.removeClass(r,"mce-fullscreen"),c.removeClass(s,"mce-fullscreen"),c.removeClass(o,"mce-fullscreen"),c.unbind(window,"resize",i),e(l)),a.fire("FullscreenStateChanged",{state:m})}var g,h,i,j,k,l,m=!1;if(!a.settings.inline)return a.on("init",function(){a.addShortcut("Ctrl+Shift+F","",f)}),a.on("remove",function(){i&&c.unbind(window,"resize",i)}),a.addCommand("mceFullScreen",f),a.addMenuItem("fullscreen",{text:"Fullscreen",shortcut:"Ctrl+Shift+F",selectable:!0,onClick:function(){f(),a.focus()},onPostRender:function(){var b=this;a.on("FullscreenStateChanged",function(a){b.active(a.state)})},context:"view"}),a.addButton("fullscreen",{tooltip:&quo
t;Fullscreen",shortcut:"Ctrl+Shift+F",onClick:f,onPostRender:function(){var b=this;a.on("FullscreenStateChanged",function(a){b.active(a.state)})}}),{isFullscreen:function(){return m}}}),function(){}}),d("0")()}();
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginshrpluginjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/hr/plugin.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/hr/plugin.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/hr/plugin.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,30 +1,152 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+(function () {
+
+var defs = {}; // id -> {dependencies, definition, instance (possibly undefined)}
+
+// Used when there is no 'main' module.
+// The name is probably (hopefully) unique so minification removes for releases.
+var register_3795 = function (id) {
+ var module = dem(id);
+ var fragments = id.split('.');
+ var target = Function('return this;')();
+ for (var i = 0; i < fragments.length - 1; ++i) {
+ if (target[fragments[i]] === undefined)
+ target[fragments[i]] = {};
+ target = target[fragments[i]];
+ }
+ target[fragments[fragments.length - 1]] = module;
+};
+
+var instantiate = function (id) {
+ var actual = defs[id];
+ var dependencies = actual.deps;
+ var definition = actual.defn;
+ var len = dependencies.length;
+ var instances = new Array(len);
+ for (var i = 0; i < len; ++i)
+ instances[i] = dem(dependencies[i]);
+ var defResult = definition.apply(null, instances);
+ if (defResult === undefined)
+ throw 'module [' + id + '] returned undefined';
+ actual.instance = defResult;
+};
+
+var def = function (id, dependencies, definition) {
+ if (typeof id !== 'string')
+ throw 'module id must be a string';
+ else if (dependencies === undefined)
+ throw 'no dependencies for ' + id;
+ else if (definition === undefined)
+ throw 'no definition function for ' + id;
+ defs[id] = {
+ deps: dependencies,
+ defn: definition,
+ instance: undefined
+ };
+};
+
+var dem = function (id) {
+ var actual = defs[id];
+ if (actual === undefined)
+ throw 'module [' + id + '] was undefined';
+ else if (actual.instance === undefined)
+ instantiate(id);
+ return actual.instance;
+};
+
+var req = function (ids, callback) {
+ var len = ids.length;
+ var instances = new Array(len);
+ for (var i = 0; i < len; ++i)
+ instances.push(dem(ids[i]));
+ callback.apply(null, callback);
+};
+
+var ephox = {};
+
+ephox.bolt = {
+ module: {
+ api: {
+ define: def,
+ require: req,
+ demand: dem
+ }
+ }
+};
+
+var define = def;
+var require = req;
+var demand = dem;
+// this helps with minificiation when using a lot of global references
+var defineGlobal = function (id, ref) {
+ define(id, [], function () { return ref; });
+};
+/*jsc
+["tinymce.plugins.hr.Plugin","tinymce.core.PluginManager","global!tinymce.util.Tools.resolve"]
+jsc*/
+defineGlobal("global!tinymce.util.Tools.resolve", tinymce.util.Tools.resolve);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * plugin.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ResolveGlobal.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/*global tinymce:true */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.PluginManager',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.PluginManager');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-tinymce.PluginManager.add('hr', function(editor) {
- editor.addCommand('InsertHorizontalRule', function() {
- editor.execCommand('mceInsertContent', false, '<hr />');
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Plugin.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addButton('hr', {
- icon: 'hr',
- tooltip: 'Horizontal line',
- cmd: 'InsertHorizontalRule'
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * This class contains all core logic for the hr plugin.
+ *
+ * @class tinymce.hr.Plugin
+ * @private
+ */
+define(
+ 'tinymce.plugins.hr.Plugin',
+ [
+ 'tinymce.core.PluginManager'
+ ],
+ function (PluginManager) {
+ PluginManager.add('hr', function (editor) {
+ editor.addCommand('InsertHorizontalRule', function () {
+ editor.execCommand('mceInsertContent', false, '<hr />');
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addMenuItem('hr', {
- icon: 'hr',
- text: 'Horizontal line',
- cmd: 'InsertHorizontalRule',
- context: 'insert'
- });
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addButton('hr', {
+ icon: 'hr',
+ tooltip: 'Horizontal line',
+ cmd: 'InsertHorizontalRule'
+ });
+
+ editor.addMenuItem('hr', {
+ icon: 'hr',
+ text: 'Horizontal line',
+ cmd: 'InsertHorizontalRule',
+ context: 'insert'
+ });
+ });
+
+ return function () { };
+ }
+);
+dem('tinymce.plugins.hr.Plugin')();
+})();
</ins></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginshrpluginminjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/hr/plugin.min.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/hr/plugin.min.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/hr/plugin.min.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1 +1 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-tinymce.PluginManager.add("hr",function(e){e.addCommand("InsertHorizontalRule",function(){e.execCommand("mceInsertContent",!1,"<hr />")}),e.addButton("hr",{icon:"hr",tooltip:"Horizontal line",cmd:"InsertHorizontalRule"}),e.addMenuItem("hr",{icon:"hr",text:"Horizontal line",cmd:"InsertHorizontalRule",context:"insert"})});
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+!function(){var a={},b=function(b){for(var c=a[b],e=c.deps,f=c.defn,g=e.length,h=new Array(g),i=0;i<g;++i)h[i]=d(e[i]);var j=f.apply(null,h);if(void 0===j)throw"module ["+b+"] returned undefined";c.instance=j},c=function(b,c,d){if("string"!=typeof b)throw"module id must be a string";if(void 0===c)throw"no dependencies for "+b;if(void 0===d)throw"no definition function for "+b;a[b]={deps:c,defn:d,instance:void 0}},d=function(c){var d=a[c];if(void 0===d)throw"module ["+c+"] was undefined";return void 0===d.instance&&b(c),d.instance},e=function(a,b){for(var c=a.length,e=new Array(c),f=0;f<c;++f)e.push(d(a[f]));b.apply(null,b)},f={};f.bolt={module:{api:{define:c,require:e,demand:d}}};var g=c,h=function(a,b){g(a,[],function(){return b})};h("2",tinymce.util.Tools.resolve),g("1",[&q
uot;2"],function(a){return a("tinymce.PluginManager")}),g("0",["1"],function(a){return a.add("hr",function(a){a.addCommand("InsertHorizontalRule",function(){a.execCommand("mceInsertContent",!1,"<hr />")}),a.addButton("hr",{icon:"hr",tooltip:"Horizontal line",cmd:"InsertHorizontalRule"}),a.addMenuItem("hr",{icon:"hr",text:"Horizontal line",cmd:"InsertHorizontalRule",context:"insert"})}),function(){}}),d("0")()}();
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginsimagepluginjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/image/plugin.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/image/plugin.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/image/plugin.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,655 +1,844 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+(function () {
+
+var defs = {}; // id -> {dependencies, definition, instance (possibly undefined)}
+
+// Used when there is no 'main' module.
+// The name is probably (hopefully) unique so minification removes for releases.
+var register_3795 = function (id) {
+ var module = dem(id);
+ var fragments = id.split('.');
+ var target = Function('return this;')();
+ for (var i = 0; i < fragments.length - 1; ++i) {
+ if (target[fragments[i]] === undefined)
+ target[fragments[i]] = {};
+ target = target[fragments[i]];
+ }
+ target[fragments[fragments.length - 1]] = module;
+};
+
+var instantiate = function (id) {
+ var actual = defs[id];
+ var dependencies = actual.deps;
+ var definition = actual.defn;
+ var len = dependencies.length;
+ var instances = new Array(len);
+ for (var i = 0; i < len; ++i)
+ instances[i] = dem(dependencies[i]);
+ var defResult = definition.apply(null, instances);
+ if (defResult === undefined)
+ throw 'module [' + id + '] returned undefined';
+ actual.instance = defResult;
+};
+
+var def = function (id, dependencies, definition) {
+ if (typeof id !== 'string')
+ throw 'module id must be a string';
+ else if (dependencies === undefined)
+ throw 'no dependencies for ' + id;
+ else if (definition === undefined)
+ throw 'no definition function for ' + id;
+ defs[id] = {
+ deps: dependencies,
+ defn: definition,
+ instance: undefined
+ };
+};
+
+var dem = function (id) {
+ var actual = defs[id];
+ if (actual === undefined)
+ throw 'module [' + id + '] was undefined';
+ else if (actual.instance === undefined)
+ instantiate(id);
+ return actual.instance;
+};
+
+var req = function (ids, callback) {
+ var len = ids.length;
+ var instances = new Array(len);
+ for (var i = 0; i < len; ++i)
+ instances.push(dem(ids[i]));
+ callback.apply(null, callback);
+};
+
+var ephox = {};
+
+ephox.bolt = {
+ module: {
+ api: {
+ define: def,
+ require: req,
+ demand: dem
+ }
+ }
+};
+
+var define = def;
+var require = req;
+var demand = dem;
+// this helps with minificiation when using a lot of global references
+var defineGlobal = function (id, ref) {
+ define(id, [], function () { return ref; });
+};
+/*jsc
+["tinymce.plugins.image.Plugin","tinymce.core.Env","tinymce.core.PluginManager","tinymce.core.util.JSON","tinymce.core.util.Tools","tinymce.core.util.XHR","global!tinymce.util.Tools.resolve"]
+jsc*/
+defineGlobal("global!tinymce.util.Tools.resolve", tinymce.util.Tools.resolve);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * plugin.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ResolveGlobal.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/*global tinymce:true */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.Env',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.Env');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-tinymce.PluginManager.add('image', function(editor) {
- function getImageSize(url, callback) {
- var img = document.createElement('img');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function done(width, height) {
- if (img.parentNode) {
- img.parentNode.removeChild(img);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.PluginManager',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.PluginManager');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- callback({width: width, height: height});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- img.onload = function() {
- done(Math.max(img.width, img.clientWidth), Math.max(img.height, img.clientHeight));
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.JSON',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.util.JSON');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- img.onerror = function() {
- done();
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var style = img.style;
- style.visibility = 'hidden';
- style.position = 'fixed';
- style.bottom = style.left = 0;
- style.width = style.height = 'auto';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.Tools',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.util.Tools');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- document.body.appendChild(img);
- img.src = url;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function buildListItems(inputList, itemCallback, startItems) {
- function appendItems(values, output) {
- output = output || [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.XHR',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.util.XHR');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tinymce.each(values, function(item) {
- var menuItem = {text: item.text || item.title};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Plugin.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (item.menu) {
- menuItem.menu = appendItems(item.menu);
- } else {
- menuItem.value = item.value;
- itemCallback(menuItem);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * This class contains all core logic for the image plugin.
+ *
+ * @class tinymce.image.Plugin
+ * @private
+ */
+define(
+ 'tinymce.plugins.image.Plugin',
+ [
+ 'tinymce.core.Env',
+ 'tinymce.core.PluginManager',
+ 'tinymce.core.util.JSON',
+ 'tinymce.core.util.Tools',
+ 'tinymce.core.util.XHR'
+ ],
+ function (Env, PluginManager, JSON, Tools, XHR) {
+ PluginManager.add('image', function (editor) {
+ function getImageSize(url, callback) {
+ var img = document.createElement('img');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- output.push(menuItem);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function done(width, height) {
+ if (img.parentNode) {
+ img.parentNode.removeChild(img);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return output;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ callback({ width: width, height: height });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return appendItems(inputList, startItems || []);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ img.onload = function () {
+ done(Math.max(img.width, img.clientWidth), Math.max(img.height, img.clientHeight));
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function createImageList(callback) {
- return function() {
- var imageList = editor.settings.image_list;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ img.onerror = function () {
+ done();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof imageList == "string") {
- tinymce.util.XHR.send({
- url: imageList,
- success: function(text) {
- callback(tinymce.util.JSON.parse(text));
- }
- });
- } else if (typeof imageList == "function") {
- imageList(callback);
- } else {
- callback(imageList);
- }
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var style = img.style;
+ style.visibility = 'hidden';
+ style.position = 'fixed';
+ style.bottom = style.left = 0;
+ style.width = style.height = 'auto';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function showDialog(imageList) {
- var win, data = {}, dom = editor.dom, imgElm, figureElm;
- var width, height, imageListCtrl, classListCtrl, imageDimensions = editor.settings.image_dimensions !== false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ document.body.appendChild(img);
+ img.src = url;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function recalcSize() {
- var widthCtrl, heightCtrl, newWidth, newHeight;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function buildListItems(inputList, itemCallback, startItems) {
+ function appendItems(values, output) {
+ output = output || [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- widthCtrl = win.find('#width')[0];
- heightCtrl = win.find('#height')[0];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(values, function (item) {
+ var menuItem = { text: item.text || item.title };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!widthCtrl || !heightCtrl) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (item.menu) {
+ menuItem.menu = appendItems(item.menu);
+ } else {
+ menuItem.value = item.value;
+ itemCallback(menuItem);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- newWidth = widthCtrl.value();
- newHeight = heightCtrl.value();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ output.push(menuItem);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (win.find('#constrain')[0].checked() && width && height && newWidth && newHeight) {
- if (width != newWidth) {
- newHeight = Math.round((newWidth / width) * newHeight);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return output;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isNaN(newHeight)) {
- heightCtrl.value(newHeight);
- }
- } else {
- newWidth = Math.round((newHeight / height) * newWidth);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return appendItems(inputList, startItems || []);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isNaN(newWidth)) {
- widthCtrl.value(newWidth);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function createImageList(callback) {
+ return function () {
+ var imageList = editor.settings.image_list;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- width = newWidth;
- height = newHeight;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof imageList == "string") {
+ XHR.send({
+ url: imageList,
+ success: function (text) {
+ callback(JSON.parse(text));
+ }
+ });
+ } else if (typeof imageList == "function") {
+ imageList(callback);
+ } else {
+ callback(imageList);
+ }
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function onSubmitForm() {
- var figureElm, oldImg;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function showDialog(imageList) {
+ var win, data = {}, dom = editor.dom, imgElm, figureElm;
+ var width, height, imageListCtrl, classListCtrl, imageDimensions = editor.settings.image_dimensions !== false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function waitLoad(imgElm) {
- function selectImage() {
- imgElm.onload = imgElm.onerror = null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function recalcSize() {
+ var widthCtrl, heightCtrl, newWidth, newHeight;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.selection) {
- editor.selection.select(imgElm);
- editor.nodeChanged();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ widthCtrl = win.find('#width')[0];
+ heightCtrl = win.find('#height')[0];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- imgElm.onload = function() {
- if (!data.width && !data.height && imageDimensions) {
- dom.setAttribs(imgElm, {
- width: imgElm.clientWidth,
- height: imgElm.clientHeight
- });
- //WP
- editor.fire( 'wpNewImageRefresh', { node: imgElm } );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!widthCtrl || !heightCtrl) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- selectImage();
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ newWidth = widthCtrl.value();
+ newHeight = heightCtrl.value();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- imgElm.onerror = selectImage;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (win.find('#constrain')[0].checked() && width && height && newWidth && newHeight) {
+ if (width != newWidth) {
+ newHeight = Math.round((newWidth / width) * newHeight);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- updateStyle();
- recalcSize();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isNaN(newHeight)) {
+ heightCtrl.value(newHeight);
+ }
+ } else {
+ newWidth = Math.round((newHeight / height) * newWidth);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- data = tinymce.extend(data, win.toJSON());
- var wpcaption = data.wpcaption; // WP
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isNaN(newWidth)) {
+ widthCtrl.value(newWidth);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!data.alt) {
- data.alt = '';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ width = newWidth;
+ height = newHeight;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!data.title) {
- data.title = '';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function onSubmitForm() {
+ var figureElm, oldImg;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (data.width === '') {
- data.width = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function waitLoad(imgElm) {
+ function selectImage() {
+ imgElm.onload = imgElm.onerror = null;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (data.height === '') {
- data.height = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.selection) {
+ editor.selection.select(imgElm);
+ editor.nodeChanged();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!data.style) {
- data.style = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ imgElm.onload = function () {
+ if (!data.width && !data.height && imageDimensions) {
+ dom.setAttribs(imgElm, {
+ width: imgElm.clientWidth,
+ height: imgElm.clientHeight
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup new data excluding style properties
- /*eslint dot-notation: 0*/
- data = {
- src: data.src,
- alt: data.alt,
- title: data.title,
- width: data.width,
- height: data.height,
- style: data.style,
- caption: data.caption,
- "class": data["class"]
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ selectImage();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.undoManager.transact(function() {
- // WP
- var eventData = { node: imgElm, data: data, wpcaption: wpcaption };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ imgElm.onerror = selectImage;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.fire( 'wpImageFormSubmit', { imgData: eventData } );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ updateStyle();
+ recalcSize();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( eventData.cancel ) {
- waitLoad( eventData.node );
- return;
- }
- // WP end
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ data = Tools.extend(data, win.toJSON());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!data.src) {
- if (imgElm) {
- dom.remove(imgElm);
- editor.focus();
- editor.nodeChanged();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!data.alt) {
+ data.alt = '';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!data.title) {
+ data.title = '';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (data.title === "") {
- data.title = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (data.width === '') {
+ data.width = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!imgElm) {
- data.id = '__mcenew';
- editor.focus();
- editor.selection.setContent(dom.createHTML('img', data));
- imgElm = dom.get('__mcenew');
- dom.setAttrib(imgElm, 'id', null);
- } else {
- dom.setAttribs(imgElm, data);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (data.height === '') {
+ data.height = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.editorUpload.uploadImagesAuto();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!data.style) {
+ data.style = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (data.caption === false) {
- if (dom.is(imgElm.parentNode, 'figure.image')) {
- figureElm = imgElm.parentNode;
- dom.insertAfter(imgElm, figureElm);
- dom.remove(figureElm);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup new data excluding style properties
+ /*eslint dot-notation: 0*/
+ data = {
+ src: data.src,
+ alt: data.alt,
+ title: data.title,
+ width: data.width,
+ height: data.height,
+ style: data.style,
+ caption: data.caption,
+ "class": data["class"]
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isTextBlock(node) {
- return editor.schema.getTextBlockElements()[node.nodeName];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.undoManager.transact(function () {
+ if (!data.src) {
+ if (imgElm) {
+ dom.remove(imgElm);
+ editor.focus();
+ editor.nodeChanged();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (data.caption === true) {
- if (!dom.is(imgElm.parentNode, 'figure.image')) {
- oldImg = imgElm;
- imgElm = imgElm.cloneNode(true);
- figureElm = dom.create('figure', {'class': 'image'});
- figureElm.appendChild(imgElm);
- figureElm.appendChild(dom.create('figcaption', {contentEditable: true}, 'Caption'));
- figureElm.contentEditable = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var textBlock = dom.getParent(oldImg, isTextBlock);
- if (textBlock) {
- dom.split(textBlock, oldImg, figureElm);
- } else {
- dom.replace(figureElm, oldImg);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (data.title === "") {
+ data.title = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.selection.select(figureElm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!imgElm) {
+ data.id = '__mcenew';
+ editor.focus();
+ editor.selection.setContent(dom.createHTML('img', data));
+ imgElm = dom.get('__mcenew');
+ dom.setAttrib(imgElm, 'id', null);
+ } else {
+ dom.setAttribs(imgElm, data);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.editorUpload.uploadImagesAuto();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- waitLoad(imgElm);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (data.caption === false) {
+ if (dom.is(imgElm.parentNode, 'figure.image')) {
+ figureElm = imgElm.parentNode;
+ dom.insertAfter(imgElm, figureElm);
+ dom.remove(figureElm);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function removePixelSuffix(value) {
- if (value) {
- value = value.replace(/px$/, '');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isTextBlock(node) {
+ return editor.schema.getTextBlockElements()[node.nodeName];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return value;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (data.caption === true) {
+ if (!dom.is(imgElm.parentNode, 'figure.image')) {
+ oldImg = imgElm;
+ imgElm = imgElm.cloneNode(true);
+ figureElm = dom.create('figure', { 'class': 'image' });
+ figureElm.appendChild(imgElm);
+ figureElm.appendChild(dom.create('figcaption', { contentEditable: true }, 'Caption'));
+ figureElm.contentEditable = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function srcChange(e) {
- var srcURL, prependURL, absoluteURLPattern, meta = e.meta || {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var textBlock = dom.getParent(oldImg, isTextBlock);
+ if (textBlock) {
+ dom.split(textBlock, oldImg, figureElm);
+ } else {
+ dom.replace(figureElm, oldImg);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (imageListCtrl) {
- imageListCtrl.value(editor.convertURL(this.value(), 'src'));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.selection.select(figureElm);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tinymce.each(meta, function(value, key) {
- win.find('#' + key).value(value);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!meta.width && !meta.height) {
- srcURL = editor.convertURL(this.value(), 'src');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ waitLoad(imgElm);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Pattern test the src url and make sure we haven't already prepended the url
- prependURL = editor.settings.image_prepend_url;
- absoluteURLPattern = new RegExp('^(?:[a-z]+:)?//', 'i');
- if (prependURL && !absoluteURLPattern.test(srcURL) && srcURL.substring(0, prependURL.length) !== prependURL) {
- srcURL = prependURL + srcURL;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function removePixelSuffix(value) {
+ if (value) {
+ value = value.replace(/px$/, '');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.value(srcURL);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return value;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- getImageSize(editor.documentBaseURI.toAbsolute(this.value()), function(data) {
- if (data.width && data.height && imageDimensions) {
- width = data.width;
- height = data.height;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function srcChange(e) {
+ var srcURL, prependURL, absoluteURLPattern, meta = e.meta || {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- win.find('#width').value(width);
- win.find('#height').value(height);
- }
- });
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (imageListCtrl) {
+ imageListCtrl.value(editor.convertURL(this.value(), 'src'));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function onBeforeCall(e) {
- e.meta = win.toJSON();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(meta, function (value, key) {
+ win.find('#' + key).value(value);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- imgElm = editor.selection.getNode();
- figureElm = dom.getParent(imgElm, 'figure.image');
- if (figureElm) {
- imgElm = dom.select('img', figureElm)[0];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!meta.width && !meta.height) {
+ srcURL = editor.convertURL(this.value(), 'src');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (imgElm && (imgElm.nodeName != 'IMG' || imgElm.getAttribute('data-mce-object') || imgElm.getAttribute('data-mce-placeholder'))) {
- imgElm = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Pattern test the src url and make sure we haven't already prepended the url
+ prependURL = editor.settings.image_prepend_url;
+ absoluteURLPattern = new RegExp('^(?:[a-z]+:)?//', 'i');
+ if (prependURL && !absoluteURLPattern.test(srcURL) && srcURL.substring(0, prependURL.length) !== prependURL) {
+ srcURL = prependURL + srcURL;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (imgElm) {
- width = dom.getAttrib(imgElm, 'width');
- height = dom.getAttrib(imgElm, 'height');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.value(srcURL);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- data = {
- src: dom.getAttrib(imgElm, 'src'),
- alt: dom.getAttrib(imgElm, 'alt'),
- title: dom.getAttrib(imgElm, 'title'),
- "class": dom.getAttrib(imgElm, 'class'),
- width: width,
- height: height,
- caption: !!figureElm
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ getImageSize(editor.documentBaseURI.toAbsolute(this.value()), function (data) {
+ if (data.width && data.height && imageDimensions) {
+ width = data.width;
+ height = data.height;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // WP
- editor.fire( 'wpLoadImageData', { imgData: { data: data, node: imgElm } } );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ win.find('#width').value(width);
+ win.find('#height').value(height);
+ }
+ });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (imageList) {
- imageListCtrl = {
- type: 'listbox',
- label: 'Image list',
- values: buildListItems(
- imageList,
- function(item) {
- item.value = editor.convertURL(item.value || item.url, 'src');
- },
- [{text: 'None', value: ''}]
- ),
- value: data.src && editor.convertURL(data.src, 'src'),
- onselect: function(e) {
- var altCtrl = win.find('#alt');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function onBeforeCall(e) {
+ e.meta = win.toJSON();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!altCtrl.value() || (e.lastControl && altCtrl.value() == e.lastControl.text())) {
- altCtrl.value(e.control.text());
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ imgElm = editor.selection.getNode();
+ figureElm = dom.getParent(imgElm, 'figure.image');
+ if (figureElm) {
+ imgElm = dom.select('img', figureElm)[0];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- win.find('#src').value(e.control.value()).fire('change');
- },
- onPostRender: function() {
- /*eslint consistent-this: 0*/
- imageListCtrl = this;
- }
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (imgElm &&
+ (imgElm.nodeName != 'IMG' ||
+ imgElm.getAttribute('data-mce-object') ||
+ imgElm.getAttribute('data-mce-placeholder'))) {
+ imgElm = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.settings.image_class_list) {
- classListCtrl = {
- name: 'class',
- type: 'listbox',
- label: 'Class',
- values: buildListItems(
- editor.settings.image_class_list,
- function(item) {
- if (item.value) {
- item.textStyle = function() {
- return editor.formatter.getCssText({inline: 'img', classes: [item.value]});
- };
- }
- }
- )
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (imgElm) {
+ width = dom.getAttrib(imgElm, 'width');
+ height = dom.getAttrib(imgElm, 'height');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // General settings shared between simple and advanced dialogs
- var generalFormItems = [
- {
- name: 'src',
- type: 'filepicker',
- filetype: 'image',
- label: 'Source',
- autofocus: true,
- onchange: srcChange,
- onbeforecall: onBeforeCall
- },
- imageListCtrl
- ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ data = {
+ src: dom.getAttrib(imgElm, 'src'),
+ alt: dom.getAttrib(imgElm, 'alt'),
+ title: dom.getAttrib(imgElm, 'title'),
+ "class": dom.getAttrib(imgElm, 'class'),
+ width: width,
+ height: height,
+ caption: !!figureElm
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.settings.image_description !== false) {
- generalFormItems.push({name: 'alt', type: 'textbox', label: 'Image description'});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (imageList) {
+ imageListCtrl = {
+ type: 'listbox',
+ label: 'Image list',
+ values: buildListItems(
+ imageList,
+ function (item) {
+ item.value = editor.convertURL(item.value || item.url, 'src');
+ },
+ [{ text: 'None', value: '' }]
+ ),
+ value: data.src && editor.convertURL(data.src, 'src'),
+ onselect: function (e) {
+ var altCtrl = win.find('#alt');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.settings.image_title) {
- generalFormItems.push({name: 'title', type: 'textbox', label: 'Image Title'});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!altCtrl.value() || (e.lastControl && altCtrl.value() == e.lastControl.text())) {
+ altCtrl.value(e.control.text());
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (imageDimensions) {
- generalFormItems.push({
- type: 'container',
- label: 'Dimensions',
- layout: 'flex',
- direction: 'row',
- align: 'center',
- spacing: 5,
- items: [
- {name: 'width', type: 'textbox', maxLength: 5, size: 3, onchange: recalcSize, ariaLabel: 'Width'},
- {type: 'label', text: 'x'},
- {name: 'height', type: 'textbox', maxLength: 5, size: 3, onchange: recalcSize, ariaLabel: 'Height'},
- {name: 'constrain', type: 'checkbox', checked: true, text: 'Constrain proportions'}
- ]
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ win.find('#src').value(e.control.value()).fire('change');
+ },
+ onPostRender: function () {
+ /*eslint consistent-this: 0*/
+ imageListCtrl = this;
+ }
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- generalFormItems.push(classListCtrl);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.settings.image_class_list) {
+ classListCtrl = {
+ name: 'class',
+ type: 'listbox',
+ label: 'Class',
+ values: buildListItems(
+ editor.settings.image_class_list,
+ function (item) {
+ if (item.value) {
+ item.textStyle = function () {
+ return editor.formatter.getCssText({ inline: 'img', classes: [item.value] });
+ };
+ }
+ }
+ )
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.settings.image_caption && tinymce.Env.ceFalse) {
- generalFormItems.push({name: 'caption', type: 'checkbox', label: 'Caption'});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // General settings shared between simple and advanced dialogs
+ var generalFormItems = [
+ {
+ name: 'src',
+ type: 'filepicker',
+ filetype: 'image',
+ label: 'Source',
+ autofocus: true,
+ onchange: srcChange,
+ onbeforecall: onBeforeCall
+ },
+ imageListCtrl
+ ];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // WP
- editor.fire( 'wpLoadImageForm', { data: generalFormItems } );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.settings.image_description !== false) {
+ generalFormItems.push({ name: 'alt', type: 'textbox', label: 'Image description' });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function mergeMargins(css) {
- if (css.margin) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.settings.image_title) {
+ generalFormItems.push({ name: 'title', type: 'textbox', label: 'Image Title' });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var splitMargin = css.margin.split(" ");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (imageDimensions) {
+ generalFormItems.push({
+ type: 'container',
+ label: 'Dimensions',
+ layout: 'flex',
+ direction: 'row',
+ align: 'center',
+ spacing: 5,
+ items: [
+ { name: 'width', type: 'textbox', maxLength: 5, size: 3, onchange: recalcSize, ariaLabel: 'Width' },
+ { type: 'label', text: 'x' },
+ { name: 'height', type: 'textbox', maxLength: 5, size: 3, onchange: recalcSize, ariaLabel: 'Height' },
+ { name: 'constrain', type: 'checkbox', checked: true, text: 'Constrain proportions' }
+ ]
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- switch (splitMargin.length) {
- case 1: //margin: toprightbottomleft;
- css['margin-top'] = css['margin-top'] || splitMargin[0];
- css['margin-right'] = css['margin-right'] || splitMargin[0];
- css['margin-bottom'] = css['margin-bottom'] || splitMargin[0];
- css['margin-left'] = css['margin-left'] || splitMargin[0];
- break;
- case 2: //margin: topbottom rightleft;
- css['margin-top'] = css['margin-top'] || splitMargin[0];
- css['margin-right'] = css['margin-right'] || splitMargin[1];
- css['margin-bottom'] = css['margin-bottom'] || splitMargin[0];
- css['margin-left'] = css['margin-left'] || splitMargin[1];
- break;
- case 3: //margin: top rightleft bottom;
- css['margin-top'] = css['margin-top'] || splitMargin[0];
- css['margin-right'] = css['margin-right'] || splitMargin[1];
- css['margin-bottom'] = css['margin-bottom'] || splitMargin[2];
- css['margin-left'] = css['margin-left'] || splitMargin[1];
- break;
- case 4: //margin: top right bottom left;
- css['margin-top'] = css['margin-top'] || splitMargin[0];
- css['margin-right'] = css['margin-right'] || splitMargin[1];
- css['margin-bottom'] = css['margin-bottom'] || splitMargin[2];
- css['margin-left'] = css['margin-left'] || splitMargin[3];
- }
- delete css.margin;
- }
- return css;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ generalFormItems.push(classListCtrl);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function updateStyle() {
- function addPixelSuffix(value) {
- if (value.length > 0 && /^[0-9]+$/.test(value)) {
- value += 'px';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.settings.image_caption && Env.ceFalse) {
+ generalFormItems.push({ name: 'caption', type: 'checkbox', label: 'Caption' });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return value;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function mergeMargins(css) {
+ if (css.margin) {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!editor.settings.image_advtab) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var splitMargin = css.margin.split(" ");
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var data = win.toJSON(),
- css = dom.parseStyle(data.style);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ switch (splitMargin.length) {
+ case 1: //margin: toprightbottomleft;
+ css['margin-top'] = css['margin-top'] || splitMargin[0];
+ css['margin-right'] = css['margin-right'] || splitMargin[0];
+ css['margin-bottom'] = css['margin-bottom'] || splitMargin[0];
+ css['margin-left'] = css['margin-left'] || splitMargin[0];
+ break;
+ case 2: //margin: topbottom rightleft;
+ css['margin-top'] = css['margin-top'] || splitMargin[0];
+ css['margin-right'] = css['margin-right'] || splitMargin[1];
+ css['margin-bottom'] = css['margin-bottom'] || splitMargin[0];
+ css['margin-left'] = css['margin-left'] || splitMargin[1];
+ break;
+ case 3: //margin: top rightleft bottom;
+ css['margin-top'] = css['margin-top'] || splitMargin[0];
+ css['margin-right'] = css['margin-right'] || splitMargin[1];
+ css['margin-bottom'] = css['margin-bottom'] || splitMargin[2];
+ css['margin-left'] = css['margin-left'] || splitMargin[1];
+ break;
+ case 4: //margin: top right bottom left;
+ css['margin-top'] = css['margin-top'] || splitMargin[0];
+ css['margin-right'] = css['margin-right'] || splitMargin[1];
+ css['margin-bottom'] = css['margin-bottom'] || splitMargin[2];
+ css['margin-left'] = css['margin-left'] || splitMargin[3];
+ }
+ delete css.margin;
+ }
+ return css;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- css = mergeMargins(css);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function updateStyle() {
+ function addPixelSuffix(value) {
+ if (value.length > 0 && /^[0-9]+$/.test(value)) {
+ value += 'px';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (data.vspace) {
- css['margin-top'] = css['margin-bottom'] = addPixelSuffix(data.vspace);
- }
- if (data.hspace) {
- css['margin-left'] = css['margin-right'] = addPixelSuffix(data.hspace);
- }
- if (data.border) {
- css['border-width'] = addPixelSuffix(data.border);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return value;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- win.find('#style').value(dom.serializeStyle(dom.parseStyle(dom.serializeStyle(css))));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!editor.settings.image_advtab) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function updateVSpaceHSpaceBorder() {
- if (!editor.settings.image_advtab) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var data = win.toJSON(),
+ css = dom.parseStyle(data.style);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var data = win.toJSON(),
- css = dom.parseStyle(data.style);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ css = mergeMargins(css);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- win.find('#vspace').value("");
- win.find('#hspace').value("");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (data.vspace) {
+ css['margin-top'] = css['margin-bottom'] = addPixelSuffix(data.vspace);
+ }
+ if (data.hspace) {
+ css['margin-left'] = css['margin-right'] = addPixelSuffix(data.hspace);
+ }
+ if (data.border) {
+ css['border-width'] = addPixelSuffix(data.border);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- css = mergeMargins(css);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ win.find('#style').value(dom.serializeStyle(dom.parseStyle(dom.serializeStyle(css))));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- //Move opposite equal margins to vspace/hspace field
- if ((css['margin-top'] && css['margin-bottom']) || (css['margin-right'] && css['margin-left'])) {
- if (css['margin-top'] === css['margin-bottom']) {
- win.find('#vspace').value(removePixelSuffix(css['margin-top']));
- } else {
- win.find('#vspace').value('');
- }
- if (css['margin-right'] === css['margin-left']) {
- win.find('#hspace').value(removePixelSuffix(css['margin-right']));
- } else {
- win.find('#hspace').value('');
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function updateVSpaceHSpaceBorder() {
+ if (!editor.settings.image_advtab) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- //Move border-width
- if (css['border-width']) {
- win.find('#border').value(removePixelSuffix(css['border-width']));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var data = win.toJSON(),
+ css = dom.parseStyle(data.style);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- win.find('#style').value(dom.serializeStyle(dom.parseStyle(dom.serializeStyle(css))));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ win.find('#vspace').value("");
+ win.find('#hspace').value("");
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ css = mergeMargins(css);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.settings.image_advtab) {
- // Parse styles from img
- if (imgElm) {
- if (imgElm.style.marginLeft && imgElm.style.marginRight && imgElm.style.marginLeft === imgElm.style.marginRight) {
- data.hspace = removePixelSuffix(imgElm.style.marginLeft);
- }
- if (imgElm.style.marginTop && imgElm.style.marginBottom && imgElm.style.marginTop === imgElm.style.marginBottom) {
- data.vspace = removePixelSuffix(imgElm.style.marginTop);
- }
- if (imgElm.style.borderWidth) {
- data.border = removePixelSuffix(imgElm.style.borderWidth);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ //Move opposite equal margins to vspace/hspace field
+ if ((css['margin-top'] && css['margin-bottom']) || (css['margin-right'] && css['margin-left'])) {
+ if (css['margin-top'] === css['margin-bottom']) {
+ win.find('#vspace').value(removePixelSuffix(css['margin-top']));
+ } else {
+ win.find('#vspace').value('');
+ }
+ if (css['margin-right'] === css['margin-left']) {
+ win.find('#hspace').value(removePixelSuffix(css['margin-right']));
+ } else {
+ win.find('#hspace').value('');
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- data.style = editor.dom.serializeStyle(editor.dom.parseStyle(editor.dom.getAttrib(imgElm, 'style')));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ //Move border-width
+ if (css['border-width']) {
+ win.find('#border').value(removePixelSuffix(css['border-width']));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Advanced dialog shows general+advanced tabs
- win = editor.windowManager.open({
- title: 'Insert/edit image',
- data: data,
- bodyType: 'tabpanel',
- body: [
- {
- title: 'General',
- type: 'form',
- items: generalFormItems
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ win.find('#style').value(dom.serializeStyle(dom.parseStyle(dom.serializeStyle(css))));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- {
- title: 'Advanced',
- type: 'form',
- pack: 'start',
- items: [
- {
- label: 'Style',
- name: 'style',
- type: 'textbox',
- onchange: updateVSpaceHSpaceBorder
- },
- {
- type: 'form',
- layout: 'grid',
- packV: 'start',
- columns: 2,
- padding: 0,
- alignH: ['left', 'right'],
- defaults: {
- type: 'textbox',
- maxWidth: 50,
- onchange: updateStyle
- },
- items: [
- {label: 'Vertical space', name: 'vspace'},
- {label: 'Horizontal space', name: 'hspace'},
- {label: 'Border', name: 'border'}
- ]
- }
- ]
- }
- ],
- onSubmit: onSubmitForm
- });
- } else {
- // Simple default dialog
- win = editor.windowManager.open({
- title: 'Insert/edit image',
- data: data,
- body: generalFormItems,
- onSubmit: onSubmitForm
- });
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('preInit', function() {
- function hasImageClass(node) {
- var className = node.attr('class');
- return className && /\bimage\b/.test(className);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.settings.image_advtab) {
+ // Parse styles from img
+ if (imgElm) {
+ if (imgElm.style.marginLeft && imgElm.style.marginRight && imgElm.style.marginLeft === imgElm.style.marginRight) {
+ data.hspace = removePixelSuffix(imgElm.style.marginLeft);
+ }
+ if (imgElm.style.marginTop && imgElm.style.marginBottom && imgElm.style.marginTop === imgElm.style.marginBottom) {
+ data.vspace = removePixelSuffix(imgElm.style.marginTop);
+ }
+ if (imgElm.style.borderWidth) {
+ data.border = removePixelSuffix(imgElm.style.borderWidth);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function toggleContentEditableState(state) {
- return function(nodes) {
- var i = nodes.length, node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ data.style = editor.dom.serializeStyle(editor.dom.parseStyle(editor.dom.getAttrib(imgElm, 'style')));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function toggleContentEditable(node) {
- node.attr('contenteditable', state ? 'true' : null);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Advanced dialog shows general+advanced tabs
+ win = editor.windowManager.open({
+ title: 'Insert/edit image',
+ data: data,
+ bodyType: 'tabpanel',
+ body: [
+ {
+ title: 'General',
+ type: 'form',
+ items: generalFormItems
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ {
+ title: 'Advanced',
+ type: 'form',
+ pack: 'start',
+ items: [
+ {
+ label: 'Style',
+ name: 'style',
+ type: 'textbox',
+ onchange: updateVSpaceHSpaceBorder
+ },
+ {
+ type: 'form',
+ layout: 'grid',
+ packV: 'start',
+ columns: 2,
+ padding: 0,
+ alignH: ['left', 'right'],
+ defaults: {
+ type: 'textbox',
+ maxWidth: 50,
+ onchange: updateStyle
+ },
+ items: [
+ { label: 'Vertical space', name: 'vspace' },
+ { label: 'Horizontal space', name: 'hspace' },
+ { label: 'Border', name: 'border' }
+ ]
+ }
+ ]
+ }
+ ],
+ onSubmit: onSubmitForm
+ });
+ } else {
+ // Simple default dialog
+ win = editor.windowManager.open({
+ title: 'Insert/edit image',
+ data: data,
+ body: generalFormItems,
+ onSubmit: onSubmitForm
+ });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (hasImageClass(node)) {
- node.attr('contenteditable', state ? 'false' : null);
- tinymce.each(node.getAll('figcaption'), toggleContentEditable);
- }
- }
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('preInit', function () {
+ function hasImageClass(node) {
+ var className = node.attr('class');
+ return className && /\bimage\b/.test(className);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.parser.addNodeFilter('figure', toggleContentEditableState(true));
- editor.serializer.addNodeFilter('figure', toggleContentEditableState(false));
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function toggleContentEditableState(state) {
+ return function (nodes) {
+ var i = nodes.length, node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addButton('image', {
- icon: 'image',
- tooltip: 'Insert/edit image',
- onclick: createImageList(showDialog),
- stateSelector: 'img:not([data-mce-object],[data-mce-placeholder]),figure.image'
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function toggleContentEditable(node) {
+ node.attr('contenteditable', state ? 'true' : null);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addMenuItem('image', {
- icon: 'image',
- text: 'Image',
- onclick: createImageList(showDialog),
- context: 'insert',
- prependToContext: true
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addCommand('mceImage', createImageList(showDialog));
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (hasImageClass(node)) {
+ node.attr('contenteditable', state ? 'false' : null);
+ Tools.each(node.getAll('figcaption'), toggleContentEditable);
+ }
+ }
+ };
+ }
+
+ editor.parser.addNodeFilter('figure', toggleContentEditableState(true));
+ editor.serializer.addNodeFilter('figure', toggleContentEditableState(false));
+ });
+
+ editor.addButton('image', {
+ icon: 'image',
+ tooltip: 'Insert/edit image',
+ onclick: createImageList(showDialog),
+ stateSelector: 'img:not([data-mce-object],[data-mce-placeholder]),figure.image'
+ });
+
+ editor.addMenuItem('image', {
+ icon: 'image',
+ text: 'Image',
+ onclick: createImageList(showDialog),
+ context: 'insert',
+ prependToContext: true
+ });
+
+ editor.addCommand('mceImage', createImageList(showDialog));
+ });
+
+ return function () { };
+ }
+);
+dem('tinymce.plugins.image.Plugin')();
+})();
</ins></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginsimagepluginminjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/image/plugin.min.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/image/plugin.min.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/image/plugin.min.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1 +1 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-tinymce.PluginManager.add("image",function(a){function b(a,b){function c(a,c){d.parentNode&&d.parentNode.removeChild(d),b({width:a,height:c})}var d=document.createElement("img");d.onload=function(){c(Math.max(d.width,d.clientWidth),Math.max(d.height,d.clientHeight))},d.onerror=function(){c()};var e=d.style;e.visibility="hidden",e.position="fixed",e.bottom=e.left=0,e.width=e.height="auto",document.body.appendChild(d),d.src=a}function c(a,b,c){function d(a,c){return c=c||[],tinymce.each(a,function(a){var e={text:a.text||a.title};a.menu?e.menu=d(a.menu):(e.value=a.value,b(e)),c.push(e)}),c}return d(a,c||[])}function d(b){return function(){var c=a.settings.image_list;"string"==typeof c?tinymce.util.XHR.send({url:c,success:function(a){b(tinymce.util.JSON.parse(a))}}):"function"==typeof c?c(b):b(c)}}function e(d){fun
ction e(){var a,b,c,d;a=m.find("#width")[0],b=m.find("#height")[0],a&&b&&(c=a.value(),d=b.value(),m.find("#constrain")[0].checked()&&p&&q&&c&&d&&(p!=c?(d=Math.round(c/p*d),isNaN(d)||b.value(d)):(c=Math.round(d/q*c),isNaN(c)||a.value(c))),p=c,q=d)}function f(){function b(b){function c(){b.onload=b.onerror=null,a.selection&&(a.selection.select(b),a.nodeChanged())}b.onload=function(){t.width||t.height||!v||(u.setAttribs(b,{width:b.clientWidth,height:b.clientHeight}),a.fire("wpNewImageRefresh",{node:b})),c()},b.onerror=c}var c,d;k(),e(),t=tinymce.extend(t,m.toJSON());var f=t.wpcaption;t.alt||(t.alt=""),t.title||(t.title=""),""===t.width&&(t.width=null),""===t.height&&(t.height=null),t.style||(t.style=null),t={src:t.src,alt:t.alt,title:t.title,width:t.width,height:t.height,style:t.style,caption:t.caption,"class":t["
class"]},a.undoManager.transact(function(){function e(b){return a.schema.getTextBlockElements()[b.nodeName]}var g={node:n,data:t,wpcaption:f};if(a.fire("wpImageFormSubmit",{imgData:g}),g.cancel)return void b(g.node);if(!t.src)return void(n&&(u.remove(n),a.focus(),a.nodeChanged()));if(""===t.title&&(t.title=null),n?u.setAttribs(n,t):(t.id="__mcenew",a.focus(),a.selection.setContent(u.createHTML("img",t)),n=u.get("__mcenew"),u.setAttrib(n,"id",null)),a.editorUpload.uploadImagesAuto(),t.caption===!1&&u.is(n.parentNode,"figure.image")&&(c=n.parentNode,u.insertAfter(n,c),u.remove(c)),t.caption!==!0)b(n);else if(!u.is(n.parentNode,"figure.image")){d=n,n=n.cloneNode(!0),c=u.create("figure",{"class":"image"}),c.appendChild(n),c.appendChild(u.create("figcaption",{contentEditable:!0},"Caption")),c.contentEditable=!1;var h=u.getP
arent(d,e);h?u.split(h,d,c):u.replace(c,d),a.selection.select(c)}})}function g(a){return a&&(a=a.replace(/px$/,"")),a}function h(c){var d,e,f,g=c.meta||{};r&&r.value(a.convertURL(this.value(),"src")),tinymce.each(g,function(a,b){m.find("#"+b).value(a)}),g.width||g.height||(d=a.convertURL(this.value(),"src"),e=a.settings.image_prepend_url,f=new RegExp("^(?:[a-z]+:)?//","i"),e&&!f.test(d)&&d.substring(0,e.length)!==e&&(d=e+d),this.value(d),b(a.documentBaseURI.toAbsolute(this.value()),function(a){a.width&&a.height&&v&&(p=a.width,q=a.height,m.find("#width").value(p),m.find("#height").value(q))}))}function i(a){a.meta=m.toJSON()}function j(a){if(a.margin){var b=a.margin.split(" ");switch(b.length){case 1:a["margin-top"]=a["margin-top"]||b[0],a["margin-right"]=a["margin-right"]||b[0],a["margin
-bottom"]=a["margin-bottom"]||b[0],a["margin-left"]=a["margin-left"]||b[0];break;case 2:a["margin-top"]=a["margin-top"]||b[0],a["margin-right"]=a["margin-right"]||b[1],a["margin-bottom"]=a["margin-bottom"]||b[0],a["margin-left"]=a["margin-left"]||b[1];break;case 3:a["margin-top"]=a["margin-top"]||b[0],a["margin-right"]=a["margin-right"]||b[1],a["margin-bottom"]=a["margin-bottom"]||b[2],a["margin-left"]=a["margin-left"]||b[1];break;case 4:a["margin-top"]=a["margin-top"]||b[0],a["margin-right"]=a["margin-right"]||b[1],a["margin-bottom"]=a["margin-bottom"]||b[2],a["margin-left"]=a["margin-left"]||b[3]}delete a.margin}return a}function k(){function b(a){return a.length>0&&/^[0-9]+$/.test(a)&&(a+=&q
uot;px"),a}if(a.settings.image_advtab){var c=m.toJSON(),d=u.parseStyle(c.style);d=j(d),c.vspace&&(d["margin-top"]=d["margin-bottom"]=b(c.vspace)),c.hspace&&(d["margin-left"]=d["margin-right"]=b(c.hspace)),c.border&&(d["border-width"]=b(c.border)),m.find("#style").value(u.serializeStyle(u.parseStyle(u.serializeStyle(d))))}}function l(){if(a.settings.image_advtab){var b=m.toJSON(),c=u.parseStyle(b.style);m.find("#vspace").value(""),m.find("#hspace").value(""),c=j(c),(c["margin-top"]&&c["margin-bottom"]||c["margin-right"]&&c["margin-left"])&&(c["margin-top"]===c["margin-bottom"]?m.find("#vspace").value(g(c["margin-top"])):m.find("#vspace").value(""),c["margin-right"]===c["margin-left"]?m.find("#hspace").valu
e(g(c["margin-right"])):m.find("#hspace").value("")),c["border-width"]&&m.find("#border").value(g(c["border-width"])),m.find("#style").value(u.serializeStyle(u.parseStyle(u.serializeStyle(c))))}}var m,n,o,p,q,r,s,t={},u=a.dom,v=a.settings.image_dimensions!==!1;n=a.selection.getNode(),o=u.getParent(n,"figure.image"),o&&(n=u.select("img",o)[0]),n&&("IMG"!=n.nodeName||n.getAttribute("data-mce-object")||n.getAttribute("data-mce-placeholder"))&&(n=null),n&&(p=u.getAttrib(n,"width"),q=u.getAttrib(n,"height"),t={src:u.getAttrib(n,"src"),alt:u.getAttrib(n,"alt"),title:u.getAttrib(n,"title"),"class":u.getAttrib(n,"class"),width:p,height:q,caption:!!o},a.fire("wpLoadImageData",{imgData:{data:t,node:n}})),d&&(r={type:"listbox",label:"I
mage list",values:c(d,function(b){b.value=a.convertURL(b.value||b.url,"src")},[{text:"None",value:""}]),value:t.src&&a.convertURL(t.src,"src"),onselect:function(a){var b=m.find("#alt");(!b.value()||a.lastControl&&b.value()==a.lastControl.text())&&b.value(a.control.text()),m.find("#src").value(a.control.value()).fire("change")},onPostRender:function(){r=this}}),a.settings.image_class_list&&(s={name:"class",type:"listbox",label:"Class",values:c(a.settings.image_class_list,function(b){b.value&&(b.textStyle=function(){return a.formatter.getCssText({inline:"img",classes:[b.value]})})})});var w=[{name:"src",type:"filepicker",filetype:"image",label:"Source",autofocus:!0,onchange:h,onbeforecall:i},r];a.settings.image_description!==!1&&w.push({name:"alt",type:"textbox",lab
el:"Image description"}),a.settings.image_title&&w.push({name:"title",type:"textbox",label:"Image Title"}),v&&w.push({type:"container",label:"Dimensions",layout:"flex",direction:"row",align:"center",spacing:5,items:[{name:"width",type:"textbox",maxLength:5,size:3,onchange:e,ariaLabel:"Width"},{type:"label",text:"x"},{name:"height",type:"textbox",maxLength:5,size:3,onchange:e,ariaLabel:"Height"},{name:"constrain",type:"checkbox",checked:!0,text:"Constrain proportions"}]}),w.push(s),a.settings.image_caption&&tinymce.Env.ceFalse&&w.push({name:"caption",type:"checkbox",label:"Caption"}),a.fire("wpLoadImageForm",{data:w}),a.settings.image_advtab?(n&&(n.style.marginLeft&&n.style.marginRight&&n.styl
e.marginLeft===n.style.marginRight&&(t.hspace=g(n.style.marginLeft)),n.style.marginTop&&n.style.marginBottom&&n.style.marginTop===n.style.marginBottom&&(t.vspace=g(n.style.marginTop)),n.style.borderWidth&&(t.border=g(n.style.borderWidth)),t.style=a.dom.serializeStyle(a.dom.parseStyle(a.dom.getAttrib(n,"style")))),m=a.windowManager.open({title:"Insert/edit image",data:t,bodyType:"tabpanel",body:[{title:"General",type:"form",items:w},{title:"Advanced",type:"form",pack:"start",items:[{label:"Style",name:"style",type:"textbox",onchange:l},{type:"form",layout:"grid",packV:"start",columns:2,padding:0,alignH:["left","right"],defaults:{type:"textbox",maxWidth:50,onchange:k},items:[{label:"Vertical space",name:"vspace"},{label:"Horizontal space",name:"
;hspace"},{label:"Border",name:"border"}]}]}],onSubmit:f})):m=a.windowManager.open({title:"Insert/edit image",data:t,body:w,onSubmit:f})}a.on("preInit",function(){function b(a){var b=a.attr("class");return b&&/\bimage\b/.test(b)}function c(a){return function(c){function d(b){b.attr("contenteditable",a?"true":null)}for(var e,f=c.length;f--;)e=c[f],b(e)&&(e.attr("contenteditable",a?"false":null),tinymce.each(e.getAll("figcaption"),d))}}a.parser.addNodeFilter("figure",c(!0)),a.serializer.addNodeFilter("figure",c(!1))}),a.addButton("image",{icon:"image",tooltip:"Insert/edit image",onclick:d(e),stateSelector:"img:not([data-mce-object],[data-mce-placeholder]),figure.image"}),a.addMenuItem("image",{icon:"image",text:"Image",onclick:d(e),context:"insert",prependToContext:!0
}),a.addCommand("mceImage",d(e))});
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+!function(){var a={},b=function(b){for(var c=a[b],e=c.deps,f=c.defn,g=e.length,h=new Array(g),i=0;i<g;++i)h[i]=d(e[i]);var j=f.apply(null,h);if(void 0===j)throw"module ["+b+"] returned undefined";c.instance=j},c=function(b,c,d){if("string"!=typeof b)throw"module id must be a string";if(void 0===c)throw"no dependencies for "+b;if(void 0===d)throw"no definition function for "+b;a[b]={deps:c,defn:d,instance:void 0}},d=function(c){var d=a[c];if(void 0===d)throw"module ["+c+"] was undefined";return void 0===d.instance&&b(c),d.instance},e=function(a,b){for(var c=a.length,e=new Array(c),f=0;f<c;++f)e.push(d(a[f]));b.apply(null,b)},f={};f.bolt={module:{api:{define:c,require:e,demand:d}}};var g=c,h=function(a,b){g(a,[],function(){return b})};h("6",tinymce.util.Tools.resolve),g("1",[&q
uot;6"],function(a){return a("tinymce.Env")}),g("2",["6"],function(a){return a("tinymce.PluginManager")}),g("3",["6"],function(a){return a("tinymce.util.JSON")}),g("4",["6"],function(a){return a("tinymce.util.Tools")}),g("5",["6"],function(a){return a("tinymce.util.XHR")}),g("0",["1","2","3","4","5"],function(a,b,c,d,e){return b.add("image",function(b){function f(a,b){function c(a,c){d.parentNode&&d.parentNode.removeChild(d),b({width:a,height:c})}var d=document.createElement("img");d.onload=function(){c(Math.max(d.width,d.clientWidth),Math.max(d.height,d.clientHeight))},d.onerror=function(){c()};var e=d.style;e.visibility="hidden",e.position="fixed",e.bottom=e.left=0,e.width=e.height="auto",document.body.appendChild(d),d.src=a}functio
n g(a,b,c){function e(a,c){return c=c||[],d.each(a,function(a){var d={text:a.text||a.title};a.menu?d.menu=e(a.menu):(d.value=a.value,b(d)),c.push(d)}),c}return e(a,c||[])}function h(a){return function(){var d=b.settings.image_list;"string"==typeof d?e.send({url:d,success:function(b){a(c.parse(b))}}):"function"==typeof d?d(a):a(d)}}function i(c){function e(){var a,b,c,d;a=o.find("#width")[0],b=o.find("#height")[0],a&&b&&(c=a.value(),d=b.value(),o.find("#constrain")[0].checked()&&r&&s&&c&&d&&(r!=c?(d=Math.round(c/r*d),isNaN(d)||b.value(d)):(c=Math.round(d/s*c),isNaN(c)||a.value(c))),r=c,s=d)}function h(){function a(a){function c(){a.onload=a.onerror=null,b.selection&&(b.selection.select(a),b.nodeChanged())}a.onload=function(){v.width||v.height||!x||w.setAttribs(a,{width:a.clientWidth,height:a.clientHeight}),c()},a.onerror=c}var c,f;m(),e(),v=d.extend(v,o.toJSON()),v.alt||(
v.alt=""),v.title||(v.title=""),""===v.width&&(v.width=null),""===v.height&&(v.height=null),v.style||(v.style=null),v={src:v.src,alt:v.alt,title:v.title,width:v.width,height:v.height,style:v.style,caption:v.caption,"class":v["class"]},b.undoManager.transact(function(){function d(a){return b.schema.getTextBlockElements()[a.nodeName]}if(!v.src)return void(p&&(w.remove(p),b.focus(),b.nodeChanged()));if(""===v.title&&(v.title=null),p?w.setAttribs(p,v):(v.id="__mcenew",b.focus(),b.selection.setContent(w.createHTML("img",v)),p=w.get("__mcenew"),w.setAttrib(p,"id",null)),b.editorUpload.uploadImagesAuto(),v.caption===!1&&w.is(p.parentNode,"figure.image")&&(c=p.parentNode,w.insertAfter(p,c),w.remove(c)),v.caption!==!0)a(p);else if(!w.is(p.parentNode,"figure.image")){f=p,p=p.cloneNode(!0),c=w.create("figure"
,{"class":"image"}),c.appendChild(p),c.appendChild(w.create("figcaption",{contentEditable:!0},"Caption")),c.contentEditable=!1;var e=w.getParent(f,d);e?w.split(e,f,c):w.replace(c,f),b.selection.select(c)}})}function i(a){return a&&(a=a.replace(/px$/,"")),a}function j(a){var c,e,g,h=a.meta||{};t&&t.value(b.convertURL(this.value(),"src")),d.each(h,function(a,b){o.find("#"+b).value(a)}),h.width||h.height||(c=b.convertURL(this.value(),"src"),e=b.settings.image_prepend_url,g=new RegExp("^(?:[a-z]+:)?//","i"),e&&!g.test(c)&&c.substring(0,e.length)!==e&&(c=e+c),this.value(c),f(b.documentBaseURI.toAbsolute(this.value()),function(a){a.width&&a.height&&x&&(r=a.width,s=a.height,o.find("#width").value(r),o.find("#height").value(s))}))}function k(a){a.meta=o.toJSON()}function l(a){if(a.margin){var b=a.margin.split(
" ");switch(b.length){case 1:a["margin-top"]=a["margin-top"]||b[0],a["margin-right"]=a["margin-right"]||b[0],a["margin-bottom"]=a["margin-bottom"]||b[0],a["margin-left"]=a["margin-left"]||b[0];break;case 2:a["margin-top"]=a["margin-top"]||b[0],a["margin-right"]=a["margin-right"]||b[1],a["margin-bottom"]=a["margin-bottom"]||b[0],a["margin-left"]=a["margin-left"]||b[1];break;case 3:a["margin-top"]=a["margin-top"]||b[0],a["margin-right"]=a["margin-right"]||b[1],a["margin-bottom"]=a["margin-bottom"]||b[2],a["margin-left"]=a["margin-left"]||b[1];break;case 4:a["margin-top"]=a["margin-top"]||b[0],a["margin-right"]=a["margin-right"]||b[1],a["margin-bottom"]=a["margin-bottom"]||b[2],a[&
quot;margin-left"]=a["margin-left"]||b[3]}delete a.margin}return a}function m(){function a(a){return a.length>0&&/^[0-9]+$/.test(a)&&(a+="px"),a}if(b.settings.image_advtab){var c=o.toJSON(),d=w.parseStyle(c.style);d=l(d),c.vspace&&(d["margin-top"]=d["margin-bottom"]=a(c.vspace)),c.hspace&&(d["margin-left"]=d["margin-right"]=a(c.hspace)),c.border&&(d["border-width"]=a(c.border)),o.find("#style").value(w.serializeStyle(w.parseStyle(w.serializeStyle(d))))}}function n(){if(b.settings.image_advtab){var a=o.toJSON(),c=w.parseStyle(a.style);o.find("#vspace").value(""),o.find("#hspace").value(""),c=l(c),(c["margin-top"]&&c["margin-bottom"]||c["margin-right"]&&c["margin-left"])&&(c["margin-top"]===c["margin-bottom"]?o.find("#vspace").
value(i(c["margin-top"])):o.find("#vspace").value(""),c["margin-right"]===c["margin-left"]?o.find("#hspace").value(i(c["margin-right"])):o.find("#hspace").value("")),c["border-width"]&&o.find("#border").value(i(c["border-width"])),o.find("#style").value(w.serializeStyle(w.parseStyle(w.serializeStyle(c))))}}var o,p,q,r,s,t,u,v={},w=b.dom,x=b.settings.image_dimensions!==!1;p=b.selection.getNode(),q=w.getParent(p,"figure.image"),q&&(p=w.select("img",q)[0]),p&&("IMG"!=p.nodeName||p.getAttribute("data-mce-object")||p.getAttribute("data-mce-placeholder"))&&(p=null),p&&(r=w.getAttrib(p,"width"),s=w.getAttrib(p,"height"),v={src:w.getAttrib(p,"src"),alt:w.getAttrib(p,"alt"),title:w.getAttrib(p,"title"),"class":w.getA
ttrib(p,"class"),width:r,height:s,caption:!!q}),c&&(t={type:"listbox",label:"Image list",values:g(c,function(a){a.value=b.convertURL(a.value||a.url,"src")},[{text:"None",value:""}]),value:v.src&&b.convertURL(v.src,"src"),onselect:function(a){var b=o.find("#alt");(!b.value()||a.lastControl&&b.value()==a.lastControl.text())&&b.value(a.control.text()),o.find("#src").value(a.control.value()).fire("change")},onPostRender:function(){t=this}}),b.settings.image_class_list&&(u={name:"class",type:"listbox",label:"Class",values:g(b.settings.image_class_list,function(a){a.value&&(a.textStyle=function(){return b.formatter.getCssText({inline:"img",classes:[a.value]})})})});var y=[{name:"src",type:"filepicker",filetype:"image",label:"Source",autofocus:!0,onchange:j,onbefore
call:k},t];b.settings.image_description!==!1&&y.push({name:"alt",type:"textbox",label:"Image description"}),b.settings.image_title&&y.push({name:"title",type:"textbox",label:"Image Title"}),x&&y.push({type:"container",label:"Dimensions",layout:"flex",direction:"row",align:"center",spacing:5,items:[{name:"width",type:"textbox",maxLength:5,size:3,onchange:e,ariaLabel:"Width"},{type:"label",text:"x"},{name:"height",type:"textbox",maxLength:5,size:3,onchange:e,ariaLabel:"Height"},{name:"constrain",type:"checkbox",checked:!0,text:"Constrain proportions"}]}),y.push(u),b.settings.image_caption&&a.ceFalse&&y.push({name:"caption",type:"checkbox",label:"Caption"}),b.settings.image_advtab?(p&&(p.style
.marginLeft&&p.style.marginRight&&p.style.marginLeft===p.style.marginRight&&(v.hspace=i(p.style.marginLeft)),p.style.marginTop&&p.style.marginBottom&&p.style.marginTop===p.style.marginBottom&&(v.vspace=i(p.style.marginTop)),p.style.borderWidth&&(v.border=i(p.style.borderWidth)),v.style=b.dom.serializeStyle(b.dom.parseStyle(b.dom.getAttrib(p,"style")))),o=b.windowManager.open({title:"Insert/edit image",data:v,bodyType:"tabpanel",body:[{title:"General",type:"form",items:y},{title:"Advanced",type:"form",pack:"start",items:[{label:"Style",name:"style",type:"textbox",onchange:n},{type:"form",layout:"grid",packV:"start",columns:2,padding:0,alignH:["left","right"],defaults:{type:"textbox",maxWidth:50,onchange:m},items:[{label:"Vertical space",name:"vspa
ce"},{label:"Horizontal space",name:"hspace"},{label:"Border",name:"border"}]}]}],onSubmit:h})):o=b.windowManager.open({title:"Insert/edit image",data:v,body:y,onSubmit:h})}b.on("preInit",function(){function a(a){var b=a.attr("class");return b&&/\bimage\b/.test(b)}function c(b){return function(c){function e(a){a.attr("contenteditable",b?"true":null)}for(var f,g=c.length;g--;)f=c[g],a(f)&&(f.attr("contenteditable",b?"false":null),d.each(f.getAll("figcaption"),e))}}b.parser.addNodeFilter("figure",c(!0)),b.serializer.addNodeFilter("figure",c(!1))}),b.addButton("image",{icon:"image",tooltip:"Insert/edit image",onclick:h(i),stateSelector:"img:not([data-mce-object],[data-mce-placeholder]),figure.image"}),b.addMenuItem("image",{icon:"image",text:"Image",onclick:h
(i),context:"insert",prependToContext:!0}),b.addCommand("mceImage",h(i))}),function(){}}),d("0")()}();
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginslistspluginjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/lists/plugin.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/lists/plugin.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/lists/plugin.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -81,12 +81,90 @@
</span><span class="cx" style="display: block; padding: 0 10px"> define(id, [], function () { return ref; });
</span><span class="cx" style="display: block; padding: 0 10px"> };
</span><span class="cx" style="display: block; padding: 0 10px"> /*jsc
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-["tinymce.lists.Plugin","global!tinymce.PluginManager","global!tinymce.util.Tools","global!tinymce.util.VK","tinymce.lists.core.NodeType","tinymce.lists.core.Delete","tinymce.lists.actions.Indent","tinymce.lists.actions.Outdent","tinymce.lists.actions.ToggleList","global!tinymce.dom.TreeWalker","global!tinymce.dom.RangeUtils","tinymce.lists.core.Selection","tinymce.lists.core.Bookmark","tinymce.lists.core.Range","tinymce.lists.core.NormalizeLists","global!tinymce.dom.BookmarkManager","tinymce.lists.core.SplitList","global!tinymce.dom.DOMUtils.DOM","tinymce.lists.core.TextBlock","global!tinymce.Env"]
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+["tinymce.plugins.lists.Plugin","tinymce.core.PluginManager","tinymce.core.util.Tools","tinymce.core.util.VK","tinymce.plugins.lists.actions.Indent","tinymce.plugins.lists.actions.Outdent","tinymce.plugins.lists.actions.ToggleList","tinymce.plugins.lists.core.Delete","tinymce.plugins.lists.core.NodeType","global!tinymce.util.Tools.resolve","tinymce.core.dom.DOMUtils","tinymce.plugins.lists.core.Bookmark","tinymce.plugins.lists.core.Selection","tinymce.plugins.lists.core.NormalizeLists","tinymce.plugins.lists.core.SplitList","tinymce.plugins.lists.core.TextBlock","tinymce.core.dom.BookmarkManager","tinymce.core.dom.RangeUtils","tinymce.core.dom.TreeWalker","tinymce.plugins.lists.core.Range",&q
uot;tinymce.core.Env"]
</ins><span class="cx" style="display: block; padding: 0 10px"> jsc*/
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-defineGlobal("global!tinymce.PluginManager", tinymce.PluginManager);
-defineGlobal("global!tinymce.util.Tools", tinymce.util.Tools);
-defineGlobal("global!tinymce.util.VK", tinymce.util.VK);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+defineGlobal("global!tinymce.util.Tools.resolve", tinymce.util.Tools.resolve);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.core.PluginManager',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.PluginManager');
+ }
+);
+
+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.core.util.Tools',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.util.Tools');
+ }
+);
+
+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.core.util.VK',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.util.VK');
+ }
+);
+
+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.core.dom.DOMUtils',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.dom.DOMUtils');
+ }
+);
+
+/**
</ins><span class="cx" style="display: block; padding: 0 10px"> * NodeType.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -96,81 +174,83 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce.lists.core.NodeType", [
-], function () {
- var isTextNode = function (node) {
- return node && node.nodeType === 3;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.lists.core.NodeType',
+ [
+ ],
+ function () {
+ var isTextNode = function (node) {
+ return node && node.nodeType === 3;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isListNode = function (node) {
- return node && (/^(OL|UL|DL)$/).test(node.nodeName);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isListNode = function (node) {
+ return node && (/^(OL|UL|DL)$/).test(node.nodeName);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isListItemNode = function (node) {
- return node && /^(LI|DT|DD)$/.test(node.nodeName);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isListItemNode = function (node) {
+ return node && /^(LI|DT|DD)$/.test(node.nodeName);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isBr = function (node) {
- return node && node.nodeName === 'BR';
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isBr = function (node) {
+ return node && node.nodeName === 'BR';
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isFirstChild = function (node) {
- return node.parentNode.firstChild === node;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isFirstChild = function (node) {
+ return node.parentNode.firstChild === node;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isLastChild = function (node) {
- return node.parentNode.lastChild === node;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isLastChild = function (node) {
+ return node.parentNode.lastChild === node;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isTextBlock = function (editor, node) {
- return node && !!editor.schema.getTextBlockElements()[node.nodeName];
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isTextBlock = function (editor, node) {
+ return node && !!editor.schema.getTextBlockElements()[node.nodeName];
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isBogusBr = function (dom, node) {
- if (!isBr(node)) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isBogusBr = function (dom, node) {
+ if (!isBr(node)) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (dom.isBlock(node.nextSibling) && !isBr(node.previousSibling)) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (dom.isBlock(node.nextSibling) && !isBr(node.previousSibling)) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isEmpty = function (dom, elm, keepBookmarks) {
- var empty = dom.isEmpty(elm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isEmpty = function (dom, elm, keepBookmarks) {
+ var empty = dom.isEmpty(elm);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (keepBookmarks && dom.select('span[data-mce-type=bookmark]', elm).length > 0) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (keepBookmarks && dom.select('span[data-mce-type=bookmark]', elm).length > 0) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return empty;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return empty;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isChildOfBody = function (dom, elm) {
- return dom.isChildOf(elm, dom.getRoot());
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isChildOfBody = function (dom, elm) {
+ return dom.isChildOf(elm, dom.getRoot());
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- isTextNode: isTextNode,
- isListNode: isListNode,
- isListItemNode: isListItemNode,
- isBr: isBr,
- isFirstChild: isFirstChild,
- isLastChild: isLastChild,
- isTextBlock: isTextBlock,
- isBogusBr: isBogusBr,
- isEmpty: isEmpty,
- isChildOfBody: isChildOfBody
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ isTextNode: isTextNode,
+ isListNode: isListNode,
+ isListItemNode: isListItemNode,
+ isBr: isBr,
+ isFirstChild: isFirstChild,
+ isLastChild: isLastChild,
+ isTextBlock: isTextBlock,
+ isBogusBr: isBogusBr,
+ isEmpty: isEmpty,
+ isChildOfBody: isChildOfBody
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-defineGlobal("global!tinymce.dom.TreeWalker", tinymce.dom.TreeWalker);
-defineGlobal("global!tinymce.dom.RangeUtils", tinymce.dom.RangeUtils);
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Selection.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ResolveGlobal.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="cx" style="display: block; padding: 0 10px"> * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -179,23 +259,16 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce.lists.core.Selection", [
- "global!tinymce.util.Tools",
- "tinymce.lists.core.NodeType"
-], function (Tools, NodeType) {
- var getSelectedListItems = function (editor) {
- return Tools.grep(editor.selection.getSelectedBlocks(), function (block) {
- return NodeType.isListItemNode(block);
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.RangeUtils',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.dom.RangeUtils');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- getSelectedListItems: getSelectedListItems
- };
-});
-
-
-defineGlobal("global!tinymce.dom.DOMUtils.DOM", tinymce.dom.DOMUtils.DOM);
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Range.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -206,38 +279,42 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce.lists.core.Range", [
- "global!tinymce.dom.RangeUtils",
- "tinymce.lists.core.NodeType"
-], function (RangeUtils, NodeType) {
- var getNormalizedEndPoint = function (container, offset) {
- var node = RangeUtils.getNode(container, offset);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.lists.core.Range',
+ [
+ 'tinymce.core.dom.RangeUtils',
+ 'tinymce.plugins.lists.core.NodeType'
+ ],
+ function (RangeUtils, NodeType) {
+ var getNormalizedEndPoint = function (container, offset) {
+ var node = RangeUtils.getNode(container, offset);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (NodeType.isListItemNode(container) && NodeType.isTextNode(node)) {
- var textNodeOffset = offset >= container.childNodes.length ? node.data.length : 0;
- return {container: node, offset: textNodeOffset};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (NodeType.isListItemNode(container) && NodeType.isTextNode(node)) {
+ var textNodeOffset = offset >= container.childNodes.length ? node.data.length : 0;
+ return { container: node, offset: textNodeOffset };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {container: container, offset: offset};
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return { container: container, offset: offset };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var normalizeRange = function (rng) {
- var outRng = rng.cloneRange();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var normalizeRange = function (rng) {
+ var outRng = rng.cloneRange();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var rangeStart = getNormalizedEndPoint(rng.startContainer, rng.startOffset);
- outRng.setStart(rangeStart.container, rangeStart.offset);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var rangeStart = getNormalizedEndPoint(rng.startContainer, rng.startOffset);
+ outRng.setStart(rangeStart.container, rangeStart.offset);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var rangeEnd = getNormalizedEndPoint(rng.endContainer, rng.endOffset);
- outRng.setEnd(rangeEnd.container, rangeEnd.offset);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var rangeEnd = getNormalizedEndPoint(rng.endContainer, rng.endOffset);
+ outRng.setEnd(rangeEnd.container, rangeEnd.offset);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return outRng;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return outRng;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- getNormalizedEndPoint: getNormalizedEndPoint,
- normalizeRange: normalizeRange
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ getNormalizedEndPoint: getNormalizedEndPoint,
+ normalizeRange: normalizeRange
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -250,125 +327,268 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce.lists.core.Bookmark", [
- "global!tinymce.dom.DOMUtils.DOM",
- "tinymce.lists.core.NodeType",
- "tinymce.lists.core.Range"
-], function (DOM, NodeType, Range) {
- /**
- * Returns a range bookmark. This will convert indexed bookmarks into temporary span elements with
- * index 0 so that they can be restored properly after the DOM has been modified. Text bookmarks will not have spans
- * added to them since they can be restored after a dom operation.
- *
- * So this: <p><b>|</b><b>|</b></p>
- * becomes: <p><b><span data-mce-type="bookmark">|</span></b><b data-mce-type="bookmark">|</span></b></p>
- *
- * @param {DOMRange} rng DOM Range to get bookmark on.
- * @return {Object} Bookmark object.
- */
- var createBookmark = function (rng) {
- var bookmark = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.lists.core.Bookmark',
+ [
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.plugins.lists.core.NodeType',
+ 'tinymce.plugins.lists.core.Range'
+ ],
+ function (DOMUtils, NodeType, Range) {
+ var DOM = DOMUtils.DOM;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var setupEndPoint = function (start) {
- var offsetNode, container, offset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a range bookmark. This will convert indexed bookmarks into temporary span elements with
+ * index 0 so that they can be restored properly after the DOM has been modified. Text bookmarks will not have spans
+ * added to them since they can be restored after a dom operation.
+ *
+ * So this: <p><b>|</b><b>|</b></p>
+ * becomes: <p><b><span data-mce-type="bookmark">|</span></b><b data-mce-type="bookmark">|</span></b></p>
+ *
+ * @param {DOMRange} rng DOM Range to get bookmark on.
+ * @return {Object} Bookmark object.
+ */
+ var createBookmark = function (rng) {
+ var bookmark = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = rng[start ? 'startContainer' : 'endContainer'];
- offset = rng[start ? 'startOffset' : 'endOffset'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var setupEndPoint = function (start) {
+ var offsetNode, container, offset;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (container.nodeType === 1) {
- offsetNode = DOM.create('span', {'data-mce-type': 'bookmark'});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = rng[start ? 'startContainer' : 'endContainer'];
+ offset = rng[start ? 'startOffset' : 'endOffset'];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (container.hasChildNodes()) {
- offset = Math.min(offset, container.childNodes.length - 1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (container.nodeType === 1) {
+ offsetNode = DOM.create('span', { 'data-mce-type': 'bookmark' });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (start) {
- container.insertBefore(offsetNode, container.childNodes[offset]);
- } else {
- DOM.insertAfter(offsetNode, container.childNodes[offset]);
- }
- } else {
- container.appendChild(offsetNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (container.hasChildNodes()) {
+ offset = Math.min(offset, container.childNodes.length - 1);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = offsetNode;
- offset = 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (start) {
+ container.insertBefore(offsetNode, container.childNodes[offset]);
+ } else {
+ DOM.insertAfter(offsetNode, container.childNodes[offset]);
+ }
+ } else {
+ container.appendChild(offsetNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bookmark[start ? 'startContainer' : 'endContainer'] = container;
- bookmark[start ? 'startOffset' : 'endOffset'] = offset;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = offsetNode;
+ offset = 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- setupEndPoint(true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bookmark[start ? 'startContainer' : 'endContainer'] = container;
+ bookmark[start ? 'startOffset' : 'endOffset'] = offset;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!rng.collapsed) {
- setupEndPoint();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ setupEndPoint(true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return bookmark;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!rng.collapsed) {
+ setupEndPoint();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var resolveBookmark = function (bookmark) {
- function restoreEndPoint (start) {
- var container, offset, node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return bookmark;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var nodeIndex = function (container) {
- var node = container.parentNode.firstChild, idx = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var resolveBookmark = function (bookmark) {
+ function restoreEndPoint(start) {
+ var container, offset, node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (node) {
- if (node === container) {
- return idx;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var nodeIndex = function (container) {
+ var node = container.parentNode.firstChild, idx = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Skip data-mce-type=bookmark nodes
- if (node.nodeType !== 1 || node.getAttribute('data-mce-type') !== 'bookmark') {
- idx++;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (node) {
+ if (node === container) {
+ return idx;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.nextSibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Skip data-mce-type=bookmark nodes
+ if (node.nodeType !== 1 || node.getAttribute('data-mce-type') !== 'bookmark') {
+ idx++;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return -1;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node.nextSibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = node = bookmark[start ? 'startContainer' : 'endContainer'];
- offset = bookmark[start ? 'startOffset' : 'endOffset'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return -1;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!container) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = node = bookmark[start ? 'startContainer' : 'endContainer'];
+ offset = bookmark[start ? 'startOffset' : 'endOffset'];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (container.nodeType === 1) {
- offset = nodeIndex(container);
- container = container.parentNode;
- DOM.remove(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!container) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bookmark[start ? 'startContainer' : 'endContainer'] = container;
- bookmark[start ? 'startOffset' : 'endOffset'] = offset;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (container.nodeType === 1) {
+ offset = nodeIndex(container);
+ container = container.parentNode;
+ DOM.remove(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- restoreEndPoint(true);
- restoreEndPoint();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bookmark[start ? 'startContainer' : 'endContainer'] = container;
+ bookmark[start ? 'startOffset' : 'endOffset'] = offset;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var rng = DOM.createRng();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ restoreEndPoint(true);
+ restoreEndPoint();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng.setStart(bookmark.startContainer, bookmark.startOffset);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var rng = DOM.createRng();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (bookmark.endContainer) {
- rng.setEnd(bookmark.endContainer, bookmark.endOffset);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng.setStart(bookmark.startContainer, bookmark.startOffset);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Range.normalizeRange(rng);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (bookmark.endContainer) {
+ rng.setEnd(bookmark.endContainer, bookmark.endOffset);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- createBookmark: createBookmark,
- resolveBookmark: resolveBookmark
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Range.normalizeRange(rng);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ createBookmark: createBookmark,
+ resolveBookmark: resolveBookmark
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Selection.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.plugins.lists.core.Selection',
+ [
+ 'tinymce.core.util.Tools',
+ 'tinymce.plugins.lists.core.NodeType'
+ ],
+ function (Tools, NodeType) {
+ var getSelectedListItems = function (editor) {
+ return Tools.grep(editor.selection.getSelectedBlocks(), function (block) {
+ return NodeType.isListItemNode(block);
+ });
+ };
+
+ return {
+ getSelectedListItems: getSelectedListItems
+ };
+ }
+);
+
+
+/**
+ * Indent.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.plugins.lists.actions.Indent',
+ [
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.plugins.lists.core.Bookmark',
+ 'tinymce.plugins.lists.core.NodeType',
+ 'tinymce.plugins.lists.core.Selection'
+ ],
+ function (DOMUtils, Bookmark, NodeType, Selection) {
+ var DOM = DOMUtils.DOM;
+
+ var mergeLists = function (from, to) {
+ var node;
+
+ if (NodeType.isListNode(from)) {
+ while ((node = from.firstChild)) {
+ to.appendChild(node);
+ }
+
+ DOM.remove(from);
+ }
+ };
+
+ var indent = function (li) {
+ var sibling, newList, listStyle;
+
+ if (li.nodeName === 'DT') {
+ DOM.rename(li, 'DD');
+ return true;
+ }
+
+ sibling = li.previousSibling;
+
+ if (sibling && NodeType.isListNode(sibling)) {
+ sibling.appendChild(li);
+ return true;
+ }
+
+ if (sibling && sibling.nodeName === 'LI' && NodeType.isListNode(sibling.lastChild)) {
+ sibling.lastChild.appendChild(li);
+ mergeLists(li.lastChild, sibling.lastChild);
+ return true;
+ }
+
+ sibling = li.nextSibling;
+
+ if (sibling && NodeType.isListNode(sibling)) {
+ sibling.insertBefore(li, sibling.firstChild);
+ return true;
+ }
+
+ /*if (sibling && sibling.nodeName === 'LI' && isListNode(li.lastChild)) {
+ return false;
+ }*/
+
+ sibling = li.previousSibling;
+ if (sibling && sibling.nodeName === 'LI') {
+ newList = DOM.create(li.parentNode.nodeName);
+ listStyle = DOM.getStyle(li.parentNode, 'listStyleType');
+ if (listStyle) {
+ DOM.setStyle(newList, 'listStyleType', listStyle);
+ }
+ sibling.appendChild(newList);
+ newList.appendChild(li);
+ mergeLists(li.lastChild, newList);
+ return true;
+ }
+
+ return false;
+ };
+
+ var indentSelection = function (editor) {
+ var listElements = Selection.getSelectedListItems(editor);
+
+ if (listElements.length) {
+ var bookmark = Bookmark.createBookmark(editor.selection.getRng(true));
+
+ for (var i = 0; i < listElements.length; i++) {
+ if (!indent(listElements[i]) && i === 0) {
+ break;
+ }
+ }
+
+ editor.selection.setRng(Bookmark.resolveBookmark(bookmark));
+ editor.nodeChanged();
+
+ return true;
+ }
+ };
+
+ return {
+ indentSelection: indentSelection
+ };
+ }
+);
+
+
+/**
</ins><span class="cx" style="display: block; padding: 0 10px"> * NormalizeLists.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -378,53 +598,77 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce.lists.core.NormalizeLists", [
- "global!tinymce.dom.DOMUtils.DOM",
- "global!tinymce.util.Tools",
- "tinymce.lists.core.NodeType"
-], function (DOM, Tools, NodeType) {
- var normalizeList = function (dom, ul) {
- var sibling, parentNode = ul.parentNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.lists.core.NormalizeLists',
+ [
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.core.util.Tools',
+ 'tinymce.plugins.lists.core.NodeType'
+ ],
+ function (DOMUtils, Tools, NodeType) {
+ var DOM = DOMUtils.DOM;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move UL/OL to previous LI if it's the only child of a LI
- if (parentNode.nodeName === 'LI' && parentNode.firstChild === ul) {
- sibling = parentNode.previousSibling;
- if (sibling && sibling.nodeName === 'LI') {
- sibling.appendChild(ul);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var normalizeList = function (dom, ul) {
+ var sibling, parentNode = ul.parentNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (NodeType.isEmpty(dom, parentNode)) {
- DOM.remove(parentNode);
- }
- } else {
- DOM.setStyle(parentNode, 'listStyleType', 'none');
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move UL/OL to previous LI if it's the only child of a LI
+ if (parentNode.nodeName === 'LI' && parentNode.firstChild === ul) {
+ sibling = parentNode.previousSibling;
+ if (sibling && sibling.nodeName === 'LI') {
+ sibling.appendChild(ul);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Append OL/UL to previous LI if it's in a parent OL/UL i.e. old HTML4
- if (NodeType.isListNode(parentNode)) {
- sibling = parentNode.previousSibling;
- if (sibling && sibling.nodeName === 'LI') {
- sibling.appendChild(ul);
- }
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (NodeType.isEmpty(dom, parentNode)) {
+ DOM.remove(parentNode);
+ }
+ } else {
+ DOM.setStyle(parentNode, 'listStyleType', 'none');
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var normalizeLists = function (dom, element) {
- Tools.each(Tools.grep(dom.select('ol,ul', element)), function (ul) {
- normalizeList(dom, ul);
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Append OL/UL to previous LI if it's in a parent OL/UL i.e. old HTML4
+ if (NodeType.isListNode(parentNode)) {
+ sibling = parentNode.previousSibling;
+ if (sibling && sibling.nodeName === 'LI') {
+ sibling.appendChild(ul);
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- normalizeList: normalizeList,
- normalizeLists: normalizeLists
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var normalizeLists = function (dom, element) {
+ Tools.each(Tools.grep(dom.select('ol,ul', element)), function (ul) {
+ normalizeList(dom, ul);
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ normalizeList: normalizeList,
+ normalizeLists: normalizeLists
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-defineGlobal("global!tinymce.dom.BookmarkManager", tinymce.dom.BookmarkManager);
-defineGlobal("global!tinymce.Env", tinymce.Env);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.core.Env',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.Env');
+ }
+);
+
+/**
</ins><span class="cx" style="display: block; padding: 0 10px"> * TextBlock.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -434,71 +678,77 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce.lists.core.TextBlock", [
- "global!tinymce.dom.DOMUtils.DOM",
- "global!tinymce.Env"
-], function (DOM, Env) {
- var createNewTextBlock = function (editor, contentNode, blockName) {
- var node, textBlock, fragment = DOM.createFragment(), hasContentNode;
- var blockElements = editor.schema.getBlockElements();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.lists.core.TextBlock',
+ [
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.core.Env'
+ ],
+ function (DOMUtils, Env) {
+ var DOM = DOMUtils.DOM;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.settings.forced_root_block) {
- blockName = blockName || editor.settings.forced_root_block;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createNewTextBlock = function (editor, contentNode, blockName) {
+ var node, textBlock, fragment = DOM.createFragment(), hasContentNode;
+ var blockElements = editor.schema.getBlockElements();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (blockName) {
- textBlock = DOM.create(blockName);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.settings.forced_root_block) {
+ blockName = blockName || editor.settings.forced_root_block;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (textBlock.tagName === editor.settings.forced_root_block) {
- DOM.setAttribs(textBlock, editor.settings.forced_root_block_attrs);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (blockName) {
+ textBlock = DOM.create(blockName);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- fragment.appendChild(textBlock);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (textBlock.tagName === editor.settings.forced_root_block) {
+ DOM.setAttribs(textBlock, editor.settings.forced_root_block_attrs);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (contentNode) {
- while ((node = contentNode.firstChild)) {
- var nodeName = node.nodeName;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ fragment.appendChild(textBlock);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!hasContentNode && (nodeName !== 'SPAN' || node.getAttribute('data-mce-type') !== 'bookmark')) {
- hasContentNode = true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (contentNode) {
+ while ((node = contentNode.firstChild)) {
+ var nodeName = node.nodeName;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (blockElements[nodeName]) {
- fragment.appendChild(node);
- textBlock = null;
- } else {
- if (blockName) {
- if (!textBlock) {
- textBlock = DOM.create(blockName);
- fragment.appendChild(textBlock);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!hasContentNode && (nodeName !== 'SPAN' || node.getAttribute('data-mce-type') !== 'bookmark')) {
+ hasContentNode = true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- textBlock.appendChild(node);
- } else {
- fragment.appendChild(node);
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (blockElements[nodeName]) {
+ fragment.appendChild(node);
+ textBlock = null;
+ } else {
+ if (blockName) {
+ if (!textBlock) {
+ textBlock = DOM.create(blockName);
+ fragment.appendChild(textBlock);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!editor.settings.forced_root_block) {
- fragment.appendChild(DOM.create('br'));
- } else {
- // BR is needed in empty blocks on non IE browsers
- if (!hasContentNode && (!Env.ie || Env.ie > 10)) {
- textBlock.appendChild(DOM.create('br', {'data-mce-bogus': '1'}));
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ textBlock.appendChild(node);
+ } else {
+ fragment.appendChild(node);
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return fragment;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!editor.settings.forced_root_block) {
+ fragment.appendChild(DOM.create('br'));
+ } else {
+ // BR is needed in empty blocks on non IE browsers
+ if (!hasContentNode && (!Env.ie || Env.ie > 10)) {
+ textBlock.appendChild(DOM.create('br', { 'data-mce-bogus': '1' }));
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- createNewTextBlock: createNewTextBlock
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return fragment;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ createNewTextBlock: createNewTextBlock
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * SplitList.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -509,60 +759,66 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce.lists.core.SplitList", [
- "global!tinymce.dom.DOMUtils.DOM",
- "global!tinymce.util.Tools",
- "tinymce.lists.core.TextBlock",
- "tinymce.lists.core.NodeType"
-], function (DOM, Tools, TextBlock, NodeType) {
- var splitList = function (editor, ul, li, newBlock) {
- var tmpRng, fragment, bookmarks, node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.lists.core.SplitList',
+ [
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.plugins.lists.core.NodeType',
+ 'tinymce.plugins.lists.core.TextBlock',
+ 'tinymce.core.util.Tools'
+ ],
+ function (DOMUtils, NodeType, TextBlock, Tools) {
+ var DOM = DOMUtils.DOM;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var removeAndKeepBookmarks = function (targetNode) {
- Tools.each(bookmarks, function (node) {
- targetNode.parentNode.insertBefore(node, li.parentNode);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var splitList = function (editor, ul, li, newBlock) {
+ var tmpRng, fragment, bookmarks, node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DOM.remove(targetNode);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var removeAndKeepBookmarks = function (targetNode) {
+ Tools.each(bookmarks, function (node) {
+ targetNode.parentNode.insertBefore(node, li.parentNode);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bookmarks = DOM.select('span[data-mce-type="bookmark"]', ul);
- newBlock = newBlock || TextBlock.createNewTextBlock(editor, li);
- tmpRng = DOM.createRng();
- tmpRng.setStartAfter(li);
- tmpRng.setEndAfter(ul);
- fragment = tmpRng.extractContents();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOM.remove(targetNode);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (node = fragment.firstChild; node; node = node.firstChild) {
- if (node.nodeName === 'LI' && editor.dom.isEmpty(node)) {
- DOM.remove(node);
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bookmarks = DOM.select('span[data-mce-type="bookmark"]', ul);
+ newBlock = newBlock || TextBlock.createNewTextBlock(editor, li);
+ tmpRng = DOM.createRng();
+ tmpRng.setStartAfter(li);
+ tmpRng.setEndAfter(ul);
+ fragment = tmpRng.extractContents();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!editor.dom.isEmpty(fragment)) {
- DOM.insertAfter(fragment, ul);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (node = fragment.firstChild; node; node = node.firstChild) {
+ if (node.nodeName === 'LI' && editor.dom.isEmpty(node)) {
+ DOM.remove(node);
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DOM.insertAfter(newBlock, ul);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!editor.dom.isEmpty(fragment)) {
+ DOM.insertAfter(fragment, ul);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (NodeType.isEmpty(editor.dom, li.parentNode)) {
- removeAndKeepBookmarks(li.parentNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOM.insertAfter(newBlock, ul);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DOM.remove(li);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (NodeType.isEmpty(editor.dom, li.parentNode)) {
+ removeAndKeepBookmarks(li.parentNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (NodeType.isEmpty(editor.dom, ul)) {
- DOM.remove(ul);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOM.remove(li);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- splitList: splitList
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (NodeType.isEmpty(editor.dom, ul)) {
+ DOM.remove(ul);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ splitList: splitList
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Outdent.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -573,132 +829,158 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce.lists.actions.Outdent", [
- "global!tinymce.dom.DOMUtils.DOM",
- "tinymce.lists.core.NodeType",
- "tinymce.lists.core.Bookmark",
- "tinymce.lists.core.Selection",
- "tinymce.lists.core.SplitList",
- "tinymce.lists.core.NormalizeLists",
- "tinymce.lists.core.TextBlock"
-], function (DOM, NodeType, Bookmark, Selection, SplitList, NormalizeLists, TextBlock) {
- var removeEmptyLi = function (dom, li) {
- if (NodeType.isEmpty(dom, li)) {
- DOM.remove(li);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.lists.actions.Outdent',
+ [
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.plugins.lists.core.Bookmark',
+ 'tinymce.plugins.lists.core.NodeType',
+ 'tinymce.plugins.lists.core.NormalizeLists',
+ 'tinymce.plugins.lists.core.Selection',
+ 'tinymce.plugins.lists.core.SplitList',
+ 'tinymce.plugins.lists.core.TextBlock'
+ ],
+ function (DOMUtils, Bookmark, NodeType, NormalizeLists, Selection, SplitList, TextBlock) {
+ var DOM = DOMUtils.DOM;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var outdent = function (editor, li) {
- var ul = li.parentNode, ulParent = ul.parentNode, newBlock;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var removeEmptyLi = function (dom, li) {
+ if (NodeType.isEmpty(dom, li)) {
+ DOM.remove(li);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (ul === editor.getBody()) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var outdent = function (editor, li) {
+ var ul = li.parentNode, ulParent = ul.parentNode, newBlock;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (li.nodeName === 'DD') {
- DOM.rename(li, 'DT');
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (ul === editor.getBody()) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (NodeType.isFirstChild(li) && NodeType.isLastChild(li)) {
- if (ulParent.nodeName === "LI") {
- DOM.insertAfter(li, ulParent);
- removeEmptyLi(editor.dom, ulParent);
- DOM.remove(ul);
- } else if (NodeType.isListNode(ulParent)) {
- DOM.remove(ul, true);
- } else {
- ulParent.insertBefore(TextBlock.createNewTextBlock(editor, li), ul);
- DOM.remove(ul);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (li.nodeName === 'DD') {
+ DOM.rename(li, 'DT');
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- } else if (NodeType.isFirstChild(li)) {
- if (ulParent.nodeName === "LI") {
- DOM.insertAfter(li, ulParent);
- li.appendChild(ul);
- removeEmptyLi(editor.dom, ulParent);
- } else if (NodeType.isListNode(ulParent)) {
- ulParent.insertBefore(li, ul);
- } else {
- ulParent.insertBefore(TextBlock.createNewTextBlock(editor, li), ul);
- DOM.remove(li);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (NodeType.isFirstChild(li) && NodeType.isLastChild(li)) {
+ if (ulParent.nodeName === "LI") {
+ DOM.insertAfter(li, ulParent);
+ removeEmptyLi(editor.dom, ulParent);
+ DOM.remove(ul);
+ } else if (NodeType.isListNode(ulParent)) {
+ DOM.remove(ul, true);
+ } else {
+ ulParent.insertBefore(TextBlock.createNewTextBlock(editor, li), ul);
+ DOM.remove(ul);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- } else if (NodeType.isLastChild(li)) {
- if (ulParent.nodeName === "LI") {
- DOM.insertAfter(li, ulParent);
- } else if (NodeType.isListNode(ulParent)) {
- DOM.insertAfter(li, ul);
- } else {
- DOM.insertAfter(TextBlock.createNewTextBlock(editor, li), ul);
- DOM.remove(li);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ } else if (NodeType.isFirstChild(li)) {
+ if (ulParent.nodeName === "LI") {
+ DOM.insertAfter(li, ulParent);
+ li.appendChild(ul);
+ removeEmptyLi(editor.dom, ulParent);
+ } else if (NodeType.isListNode(ulParent)) {
+ ulParent.insertBefore(li, ul);
+ } else {
+ ulParent.insertBefore(TextBlock.createNewTextBlock(editor, li), ul);
+ DOM.remove(li);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ } else if (NodeType.isLastChild(li)) {
+ if (ulParent.nodeName === "LI") {
+ DOM.insertAfter(li, ulParent);
+ } else if (NodeType.isListNode(ulParent)) {
+ DOM.insertAfter(li, ul);
+ } else {
+ DOM.insertAfter(TextBlock.createNewTextBlock(editor, li), ul);
+ DOM.remove(li);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (ulParent.nodeName === 'LI') {
- ul = ulParent;
- newBlock = TextBlock.createNewTextBlock(editor, li, 'LI');
- } else if (NodeType.isListNode(ulParent)) {
- newBlock = TextBlock.createNewTextBlock(editor, li, 'LI');
- } else {
- newBlock = TextBlock.createNewTextBlock(editor, li);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- SplitList.splitList(editor, ul, li, newBlock);
- NormalizeLists.normalizeLists(editor.dom, ul.parentNode);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (ulParent.nodeName === 'LI') {
+ ul = ulParent;
+ newBlock = TextBlock.createNewTextBlock(editor, li, 'LI');
+ } else if (NodeType.isListNode(ulParent)) {
+ newBlock = TextBlock.createNewTextBlock(editor, li, 'LI');
+ } else {
+ newBlock = TextBlock.createNewTextBlock(editor, li);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ SplitList.splitList(editor, ul, li, newBlock);
+ NormalizeLists.normalizeLists(editor.dom, ul.parentNode);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var outdentSelection = function (editor) {
- var listElements = Selection.getSelectedListItems(editor);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (listElements.length) {
- var bookmark = Bookmark.createBookmark(editor.selection.getRng(true));
- var i, y, root = editor.getBody();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var outdentSelection = function (editor) {
+ var listElements = Selection.getSelectedListItems(editor);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- i = listElements.length;
- while (i--) {
- var node = listElements[i].parentNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (listElements.length) {
+ var bookmark = Bookmark.createBookmark(editor.selection.getRng(true));
+ var i, y, root = editor.getBody();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (node && node !== root) {
- y = listElements.length;
- while (y--) {
- if (listElements[y] === node) {
- listElements.splice(i, 1);
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ i = listElements.length;
+ while (i--) {
+ var node = listElements[i].parentNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.parentNode;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (node && node !== root) {
+ y = listElements.length;
+ while (y--) {
+ if (listElements[y] === node) {
+ listElements.splice(i, 1);
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0; i < listElements.length; i++) {
- if (!outdent(editor, listElements[i]) && i === 0) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node.parentNode;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.selection.setRng(Bookmark.resolveBookmark(bookmark));
- editor.nodeChanged();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0; i < listElements.length; i++) {
+ if (!outdent(editor, listElements[i]) && i === 0) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.selection.setRng(Bookmark.resolveBookmark(bookmark));
+ editor.nodeChanged();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- outdent: outdent,
- outdentSelection: outdentSelection
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ outdent: outdent,
+ outdentSelection: outdentSelection
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.core.dom.BookmarkManager',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.dom.BookmarkManager');
+ }
+);
+
+/**
</ins><span class="cx" style="display: block; padding: 0 10px"> * ToggleList.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -708,276 +990,280 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce.lists.actions.ToggleList", [
- "global!tinymce.util.Tools",
- "global!tinymce.dom.BookmarkManager",
- "tinymce.lists.core.Selection",
- "tinymce.lists.core.NodeType",
- "tinymce.lists.core.Bookmark",
- "tinymce.lists.core.SplitList",
- "tinymce.lists.core.NormalizeLists",
- "tinymce.lists.actions.Outdent"
-], function (Tools, BookmarkManager, Selection, NodeType, Bookmark, SplitList, NormalizeLists, Outdent) {
- var updateListStyle = function (dom, el, detail) {
- var type = detail['list-style-type'] ? detail['list-style-type'] : null;
- dom.setStyle(el, 'list-style-type', type);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.lists.actions.ToggleList',
+ [
+ 'tinymce.core.dom.BookmarkManager',
+ 'tinymce.core.util.Tools',
+ 'tinymce.plugins.lists.actions.Outdent',
+ 'tinymce.plugins.lists.core.Bookmark',
+ 'tinymce.plugins.lists.core.NodeType',
+ 'tinymce.plugins.lists.core.NormalizeLists',
+ 'tinymce.plugins.lists.core.Selection',
+ 'tinymce.plugins.lists.core.SplitList'
+ ],
+ function (BookmarkManager, Tools, Outdent, Bookmark, NodeType, NormalizeLists, Selection, SplitList) {
+ var updateListStyle = function (dom, el, detail) {
+ var type = detail['list-style-type'] ? detail['list-style-type'] : null;
+ dom.setStyle(el, 'list-style-type', type);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var setAttribs = function (elm, attrs) {
- Tools.each(attrs, function (value, key) {
- elm.setAttribute(key, value);
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var setAttribs = function (elm, attrs) {
+ Tools.each(attrs, function (value, key) {
+ elm.setAttribute(key, value);
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var updateListAttrs = function (dom, el, detail) {
- setAttribs(el, detail['list-attributes']);
- Tools.each(dom.select('li', el), function (li) {
- setAttribs(li, detail['list-item-attributes']);
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var updateListAttrs = function (dom, el, detail) {
+ setAttribs(el, detail['list-attributes']);
+ Tools.each(dom.select('li', el), function (li) {
+ setAttribs(li, detail['list-item-attributes']);
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var updateListWithDetails = function (dom, el, detail) {
- updateListStyle(dom, el, detail);
- updateListAttrs(dom, el, detail);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var updateListWithDetails = function (dom, el, detail) {
+ updateListStyle(dom, el, detail);
+ updateListAttrs(dom, el, detail);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getEndPointNode = function (editor, rng, start) {
- var container, offset, root = editor.getBody();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getEndPointNode = function (editor, rng, start) {
+ var container, offset, root = editor.getBody();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = rng[start ? 'startContainer' : 'endContainer'];
- offset = rng[start ? 'startOffset' : 'endOffset'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = rng[start ? 'startContainer' : 'endContainer'];
+ offset = rng[start ? 'startOffset' : 'endOffset'];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Resolve node index
- if (container.nodeType === 1) {
- container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Resolve node index
+ if (container.nodeType === 1) {
+ container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (container.parentNode !== root) {
- if (NodeType.isTextBlock(editor, container)) {
- return container;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (container.parentNode !== root) {
+ if (NodeType.isTextBlock(editor, container)) {
+ return container;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (/^(TD|TH)$/.test(container.parentNode.nodeName)) {
- return container;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (/^(TD|TH)$/.test(container.parentNode.nodeName)) {
+ return container;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = container.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = container.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return container;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return container;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getSelectedTextBlocks = function (editor, rng) {
- var textBlocks = [], root = editor.getBody(), dom = editor.dom;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getSelectedTextBlocks = function (editor, rng) {
+ var textBlocks = [], root = editor.getBody(), dom = editor.dom;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var startNode = getEndPointNode(editor, rng, true);
- var endNode = getEndPointNode(editor, rng, false);
- var block, siblings = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var startNode = getEndPointNode(editor, rng, true);
+ var endNode = getEndPointNode(editor, rng, false);
+ var block, siblings = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var node = startNode; node; node = node.nextSibling) {
- siblings.push(node);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (var node = startNode; node; node = node.nextSibling) {
+ siblings.push(node);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node === endNode) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node === endNode) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(siblings, function (node) {
- if (NodeType.isTextBlock(editor, node)) {
- textBlocks.push(node);
- block = null;
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(siblings, function (node) {
+ if (NodeType.isTextBlock(editor, node)) {
+ textBlocks.push(node);
+ block = null;
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (dom.isBlock(node) || NodeType.isBr(node)) {
- if (NodeType.isBr(node)) {
- dom.remove(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (dom.isBlock(node) || NodeType.isBr(node)) {
+ if (NodeType.isBr(node)) {
+ dom.remove(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- block = null;
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ block = null;
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var nextSibling = node.nextSibling;
- if (BookmarkManager.isBookmarkNode(node)) {
- if (NodeType.isTextBlock(editor, nextSibling) || (!nextSibling && node.parentNode === root)) {
- block = null;
- return;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var nextSibling = node.nextSibling;
+ if (BookmarkManager.isBookmarkNode(node)) {
+ if (NodeType.isTextBlock(editor, nextSibling) || (!nextSibling && node.parentNode === root)) {
+ block = null;
+ return;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!block) {
- block = dom.create('p');
- node.parentNode.insertBefore(block, node);
- textBlocks.push(block);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!block) {
+ block = dom.create('p');
+ node.parentNode.insertBefore(block, node);
+ textBlocks.push(block);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- block.appendChild(node);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ block.appendChild(node);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return textBlocks;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return textBlocks;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var applyList = function (editor, listName, detail) {
- var rng = editor.selection.getRng(true), bookmark, listItemName = 'LI';
- var dom = editor.dom;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var applyList = function (editor, listName, detail) {
+ var rng = editor.selection.getRng(true), bookmark, listItemName = 'LI';
+ var dom = editor.dom;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- detail = detail ? detail : {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ detail = detail ? detail : {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (dom.getContentEditable(editor.selection.getNode()) === "false") {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (dom.getContentEditable(editor.selection.getNode()) === "false") {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- listName = listName.toUpperCase();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ listName = listName.toUpperCase();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (listName === 'DL') {
- listItemName = 'DT';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (listName === 'DL') {
+ listItemName = 'DT';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bookmark = Bookmark.createBookmark(rng);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bookmark = Bookmark.createBookmark(rng);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(getSelectedTextBlocks(editor, rng), function (block) {
- var listBlock, sibling;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(getSelectedTextBlocks(editor, rng), function (block) {
+ var listBlock, sibling;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var hasCompatibleStyle = function (sib) {
- var sibStyle = dom.getStyle(sib, 'list-style-type');
- var detailStyle = detail ? detail['list-style-type'] : '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var hasCompatibleStyle = function (sib) {
+ var sibStyle = dom.getStyle(sib, 'list-style-type');
+ var detailStyle = detail ? detail['list-style-type'] : '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- detailStyle = detailStyle === null ? '' : detailStyle;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ detailStyle = detailStyle === null ? '' : detailStyle;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return sibStyle === detailStyle;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return sibStyle === detailStyle;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- sibling = block.previousSibling;
- if (sibling && NodeType.isListNode(sibling) && sibling.nodeName === listName && hasCompatibleStyle(sibling)) {
- listBlock = sibling;
- block = dom.rename(block, listItemName);
- sibling.appendChild(block);
- } else {
- listBlock = dom.create(listName);
- block.parentNode.insertBefore(listBlock, block);
- listBlock.appendChild(block);
- block = dom.rename(block, listItemName);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ sibling = block.previousSibling;
+ if (sibling && NodeType.isListNode(sibling) && sibling.nodeName === listName && hasCompatibleStyle(sibling)) {
+ listBlock = sibling;
+ block = dom.rename(block, listItemName);
+ sibling.appendChild(block);
+ } else {
+ listBlock = dom.create(listName);
+ block.parentNode.insertBefore(listBlock, block);
+ listBlock.appendChild(block);
+ block = dom.rename(block, listItemName);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- updateListWithDetails(dom, listBlock, detail);
- mergeWithAdjacentLists(editor.dom, listBlock);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ updateListWithDetails(dom, listBlock, detail);
+ mergeWithAdjacentLists(editor.dom, listBlock);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.selection.setRng(Bookmark.resolveBookmark(bookmark));
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.selection.setRng(Bookmark.resolveBookmark(bookmark));
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var removeList = function (editor) {
- var bookmark = Bookmark.createBookmark(editor.selection.getRng(true)), root = editor.getBody();
- var listItems = Selection.getSelectedListItems(editor);
- var emptyListItems = Tools.grep(listItems, function (li) {
- return editor.dom.isEmpty(li);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var removeList = function (editor) {
+ var bookmark = Bookmark.createBookmark(editor.selection.getRng(true)), root = editor.getBody();
+ var listItems = Selection.getSelectedListItems(editor);
+ var emptyListItems = Tools.grep(listItems, function (li) {
+ return editor.dom.isEmpty(li);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- listItems = Tools.grep(listItems, function (li) {
- return !editor.dom.isEmpty(li);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ listItems = Tools.grep(listItems, function (li) {
+ return !editor.dom.isEmpty(li);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(emptyListItems, function (li) {
- if (NodeType.isEmpty(editor.dom, li)) {
- Outdent.outdent(editor, li);
- return;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(emptyListItems, function (li) {
+ if (NodeType.isEmpty(editor.dom, li)) {
+ Outdent.outdent(editor, li);
+ return;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(listItems, function (li) {
- var node, rootList;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(listItems, function (li) {
+ var node, rootList;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (li.parentNode === editor.getBody()) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (li.parentNode === editor.getBody()) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (node = li; node && node !== root; node = node.parentNode) {
- if (NodeType.isListNode(node)) {
- rootList = node;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (node = li; node && node !== root; node = node.parentNode) {
+ if (NodeType.isListNode(node)) {
+ rootList = node;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- SplitList.splitList(editor, rootList, li);
- NormalizeLists.normalizeLists(editor.dom, rootList.parentNode);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ SplitList.splitList(editor, rootList, li);
+ NormalizeLists.normalizeLists(editor.dom, rootList.parentNode);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.selection.setRng(Bookmark.resolveBookmark(bookmark));
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.selection.setRng(Bookmark.resolveBookmark(bookmark));
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isValidLists = function (list1, list2) {
- return list1 && list2 && NodeType.isListNode(list1) && list1.nodeName === list2.nodeName;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isValidLists = function (list1, list2) {
+ return list1 && list2 && NodeType.isListNode(list1) && list1.nodeName === list2.nodeName;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var hasSameListStyle = function (dom, list1, list2) {
- var targetStyle = dom.getStyle(list1, 'list-style-type', true);
- var style = dom.getStyle(list2, 'list-style-type', true);
- return targetStyle === style;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var hasSameListStyle = function (dom, list1, list2) {
+ var targetStyle = dom.getStyle(list1, 'list-style-type', true);
+ var style = dom.getStyle(list2, 'list-style-type', true);
+ return targetStyle === style;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var hasSameClasses = function (elm1, elm2) {
- return elm1.className === elm2.className;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var hasSameClasses = function (elm1, elm2) {
+ return elm1.className === elm2.className;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var shouldMerge = function (dom, list1, list2) {
- return isValidLists(list1, list2) && hasSameListStyle(dom, list1, list2) && hasSameClasses(list1, list2);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var shouldMerge = function (dom, list1, list2) {
+ return isValidLists(list1, list2) && hasSameListStyle(dom, list1, list2) && hasSameClasses(list1, list2);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var mergeWithAdjacentLists = function (dom, listBlock) {
- var sibling, node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var mergeWithAdjacentLists = function (dom, listBlock) {
+ var sibling, node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- sibling = listBlock.nextSibling;
- if (shouldMerge(dom, listBlock, sibling)) {
- while ((node = sibling.firstChild)) {
- listBlock.appendChild(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ sibling = listBlock.nextSibling;
+ if (shouldMerge(dom, listBlock, sibling)) {
+ while ((node = sibling.firstChild)) {
+ listBlock.appendChild(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.remove(sibling);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.remove(sibling);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- sibling = listBlock.previousSibling;
- if (shouldMerge(dom, listBlock, sibling)) {
- while ((node = sibling.lastChild)) {
- listBlock.insertBefore(node, listBlock.firstChild);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ sibling = listBlock.previousSibling;
+ if (shouldMerge(dom, listBlock, sibling)) {
+ while ((node = sibling.lastChild)) {
+ listBlock.insertBefore(node, listBlock.firstChild);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.remove(sibling);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.remove(sibling);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var toggleList = function (editor, listName, detail) {
- var parentList = editor.dom.getParent(editor.selection.getStart(), 'OL,UL,DL');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var toggleList = function (editor, listName, detail) {
+ var parentList = editor.dom.getParent(editor.selection.getStart(), 'OL,UL,DL');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- detail = detail ? detail : {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ detail = detail ? detail : {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (parentList === editor.getBody()) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parentList === editor.getBody()) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (parentList) {
- if (parentList.nodeName === listName) {
- removeList(editor, listName);
- } else {
- var bookmark = Bookmark.createBookmark(editor.selection.getRng(true));
- updateListWithDetails(editor.dom, parentList, detail);
- mergeWithAdjacentLists(editor.dom, editor.dom.rename(parentList, listName));
- editor.selection.setRng(Bookmark.resolveBookmark(bookmark));
- }
- } else {
- applyList(editor, listName, detail);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parentList) {
+ if (parentList.nodeName === listName) {
+ removeList(editor, listName);
+ } else {
+ var bookmark = Bookmark.createBookmark(editor.selection.getRng(true));
+ updateListWithDetails(editor.dom, parentList, detail);
+ mergeWithAdjacentLists(editor.dom, editor.dom.rename(parentList, listName));
+ editor.selection.setRng(Bookmark.resolveBookmark(bookmark));
+ }
+ } else {
+ applyList(editor, listName, detail);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- toggleList: toggleList,
- removeList: removeList,
- mergeWithAdjacentLists: mergeWithAdjacentLists
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ toggleList: toggleList,
+ removeList: removeList,
+ mergeWithAdjacentLists: mergeWithAdjacentLists
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Delete.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ResolveGlobal.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="cx" style="display: block; padding: 0 10px"> * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -986,302 +1272,223 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce.lists.core.Delete", [
- "global!tinymce.dom.TreeWalker",
- "global!tinymce.dom.RangeUtils",
- "global!tinymce.util.VK",
- "tinymce.lists.core.Selection",
- "tinymce.lists.core.NodeType",
- "tinymce.lists.core.Bookmark",
- "tinymce.lists.core.Range",
- "tinymce.lists.core.NormalizeLists",
- "tinymce.lists.actions.ToggleList"
-], function (
- TreeWalker, RangeUtils, VK, Selection, NodeType, Bookmark, Range, NormalizeLists, ToggleList
-) {
- var findNextCaretContainer = function (editor, rng, isForward) {
- var node = rng.startContainer, offset = rng.startOffset;
- var nonEmptyBlocks, walker;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.TreeWalker',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.dom.TreeWalker');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.nodeType === 3 && (isForward ? offset < node.data.length : offset > 0)) {
- return node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Delete.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- nonEmptyBlocks = editor.schema.getNonEmptyElements();
- if (node.nodeType === 1) {
- node = RangeUtils.getNode(node, offset);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.lists.core.Delete',
+ [
+ 'tinymce.core.dom.RangeUtils',
+ 'tinymce.core.dom.TreeWalker',
+ 'tinymce.core.util.VK',
+ 'tinymce.plugins.lists.actions.ToggleList',
+ 'tinymce.plugins.lists.core.Bookmark',
+ 'tinymce.plugins.lists.core.NodeType',
+ 'tinymce.plugins.lists.core.NormalizeLists',
+ 'tinymce.plugins.lists.core.Range',
+ 'tinymce.plugins.lists.core.Selection'
+ ],
+ function (RangeUtils, TreeWalker, VK, ToggleList, Bookmark, NodeType, NormalizeLists, Range, Selection) {
+ var findNextCaretContainer = function (editor, rng, isForward) {
+ var node = rng.startContainer, offset = rng.startOffset;
+ var nonEmptyBlocks, walker;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- walker = new TreeWalker(node, editor.getBody());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.nodeType === 3 && (isForward ? offset < node.data.length : offset > 0)) {
+ return node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Delete at <li>|<br></li> then jump over the bogus br
- if (isForward) {
- if (NodeType.isBogusBr(editor.dom, node)) {
- walker.next();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ nonEmptyBlocks = editor.schema.getNonEmptyElements();
+ if (node.nodeType === 1) {
+ node = RangeUtils.getNode(node, offset);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while ((node = walker[isForward ? 'next' : 'prev2']())) {
- if (node.nodeName === 'LI' && !node.hasChildNodes()) {
- return node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ walker = new TreeWalker(node, editor.getBody());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (nonEmptyBlocks[node.nodeName]) {
- return node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Delete at <li>|<br></li> then jump over the bogus br
+ if (isForward) {
+ if (NodeType.isBogusBr(editor.dom, node)) {
+ walker.next();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.nodeType === 3 && node.data.length > 0) {
- return node;
- }
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while ((node = walker[isForward ? 'next' : 'prev2']())) {
+ if (node.nodeName === 'LI' && !node.hasChildNodes()) {
+ return node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var mergeLiElements = function (dom, fromElm, toElm) {
- var node, listNode, ul = fromElm.parentNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (nonEmptyBlocks[node.nodeName]) {
+ return node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!NodeType.isChildOfBody(dom, fromElm) || !NodeType.isChildOfBody(dom, toElm)) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.nodeType === 3 && node.data.length > 0) {
+ return node;
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (NodeType.isListNode(toElm.lastChild)) {
- listNode = toElm.lastChild;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var mergeLiElements = function (dom, fromElm, toElm) {
+ var node, listNode, ul = fromElm.parentNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (ul === toElm.lastChild) {
- if (NodeType.isBr(ul.previousSibling)) {
- dom.remove(ul.previousSibling);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!NodeType.isChildOfBody(dom, fromElm) || !NodeType.isChildOfBody(dom, toElm)) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = toElm.lastChild;
- if (node && NodeType.isBr(node) && fromElm.hasChildNodes()) {
- dom.remove(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (NodeType.isListNode(toElm.lastChild)) {
+ listNode = toElm.lastChild;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (NodeType.isEmpty(dom, toElm, true)) {
- dom.$(toElm).empty();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (ul === toElm.lastChild) {
+ if (NodeType.isBr(ul.previousSibling)) {
+ dom.remove(ul.previousSibling);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!NodeType.isEmpty(dom, fromElm, true)) {
- while ((node = fromElm.firstChild)) {
- toElm.appendChild(node);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = toElm.lastChild;
+ if (node && NodeType.isBr(node) && fromElm.hasChildNodes()) {
+ dom.remove(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (listNode) {
- toElm.appendChild(listNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (NodeType.isEmpty(dom, toElm, true)) {
+ dom.$(toElm).empty();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.remove(fromElm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!NodeType.isEmpty(dom, fromElm, true)) {
+ while ((node = fromElm.firstChild)) {
+ toElm.appendChild(node);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (NodeType.isEmpty(dom, ul) && ul !== dom.getRoot()) {
- dom.remove(ul);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (listNode) {
+ toElm.appendChild(listNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var backspaceDeleteFromListToListCaret = function (editor, isForward) {
- var dom = editor.dom, selection = editor.selection;
- var li = dom.getParent(selection.getStart(), 'LI'), ul, rng, otherLi;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.remove(fromElm);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (li) {
- ul = li.parentNode;
- if (ul === editor.getBody() && NodeType.isEmpty(dom, ul)) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (NodeType.isEmpty(dom, ul) && ul !== dom.getRoot()) {
+ dom.remove(ul);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng = Range.normalizeRange(selection.getRng(true));
- otherLi = dom.getParent(findNextCaretContainer(editor, rng, isForward), 'LI');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var backspaceDeleteFromListToListCaret = function (editor, isForward) {
+ var dom = editor.dom, selection = editor.selection;
+ var li = dom.getParent(selection.getStart(), 'LI'), ul, rng, otherLi;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (otherLi && otherLi !== li) {
- var bookmark = Bookmark.createBookmark(rng);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (li) {
+ ul = li.parentNode;
+ if (ul === editor.getBody() && NodeType.isEmpty(dom, ul)) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isForward) {
- mergeLiElements(dom, otherLi, li);
- } else {
- mergeLiElements(dom, li, otherLi);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng = Range.normalizeRange(selection.getRng(true));
+ otherLi = dom.getParent(findNextCaretContainer(editor, rng, isForward), 'LI');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.selection.setRng(Bookmark.resolveBookmark(bookmark));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (otherLi && otherLi !== li) {
+ var bookmark = Bookmark.createBookmark(rng);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- } else if (!otherLi) {
- if (!isForward && ToggleList.removeList(editor, ul.nodeName)) {
- return true;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isForward) {
+ mergeLiElements(dom, otherLi, li);
+ } else {
+ mergeLiElements(dom, li, otherLi);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.selection.setRng(Bookmark.resolveBookmark(bookmark));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var backspaceDeleteIntoListCaret = function (editor, isForward) {
- var dom = editor.dom;
- var block = dom.getParent(editor.selection.getStart(), dom.isBlock);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ } else if (!otherLi) {
+ if (!isForward && ToggleList.removeList(editor, ul.nodeName)) {
+ return true;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (block && dom.isEmpty(block)) {
- var rng = Range.normalizeRange(editor.selection.getRng(true));
- var otherLi = dom.getParent(findNextCaretContainer(editor, rng, isForward), 'LI');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (otherLi) {
- editor.undoManager.transact(function () {
- dom.remove(block);
- ToggleList.mergeWithAdjacentLists(dom, otherLi.parentNode);
- editor.selection.select(otherLi, true);
- editor.selection.collapse(isForward);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var backspaceDeleteIntoListCaret = function (editor, isForward) {
+ var dom = editor.dom;
+ var block = dom.getParent(editor.selection.getStart(), dom.isBlock);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (block && dom.isEmpty(block)) {
+ var rng = Range.normalizeRange(editor.selection.getRng(true));
+ var otherLi = dom.getParent(findNextCaretContainer(editor, rng, isForward), 'LI');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (otherLi) {
+ editor.undoManager.transact(function () {
+ dom.remove(block);
+ ToggleList.mergeWithAdjacentLists(dom, otherLi.parentNode);
+ editor.selection.select(otherLi, true);
+ editor.selection.collapse(isForward);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var backspaceDeleteCaret = function (editor, isForward) {
- return backspaceDeleteFromListToListCaret(editor, isForward) || backspaceDeleteIntoListCaret(editor, isForward);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var backspaceDeleteRange = function (editor) {
- var startListParent = editor.dom.getParent(editor.selection.getStart(), 'LI,DT,DD');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (startListParent || Selection.getSelectedListItems(editor).length > 0) {
- editor.undoManager.transact(function () {
- editor.execCommand('Delete');
- NormalizeLists.normalizeLists(editor.dom, editor.getBody());
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var backspaceDeleteCaret = function (editor, isForward) {
+ return backspaceDeleteFromListToListCaret(editor, isForward) || backspaceDeleteIntoListCaret(editor, isForward);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var backspaceDeleteRange = function (editor) {
+ var startListParent = editor.dom.getParent(editor.selection.getStart(), 'LI,DT,DD');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (startListParent || Selection.getSelectedListItems(editor).length > 0) {
+ editor.undoManager.transact(function () {
+ editor.execCommand('Delete');
+ NormalizeLists.normalizeLists(editor.dom, editor.getBody());
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var backspaceDelete = function (editor, isForward) {
- return editor.selection.isCollapsed() ? backspaceDeleteCaret(editor, isForward) : backspaceDeleteRange(editor);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var setup = function (editor) {
- editor.on('keydown', function (e) {
- if (e.keyCode === VK.BACKSPACE) {
- if (backspaceDelete(editor, false)) {
- e.preventDefault();
- }
- } else if (e.keyCode === VK.DELETE) {
- if (backspaceDelete(editor, true)) {
- e.preventDefault();
- }
- }
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- setup: setup,
- backspaceDelete: backspaceDelete
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var backspaceDelete = function (editor, isForward) {
+ return editor.selection.isCollapsed() ? backspaceDeleteCaret(editor, isForward) : backspaceDeleteRange(editor);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var setup = function (editor) {
+ editor.on('keydown', function (e) {
+ if (e.keyCode === VK.BACKSPACE) {
+ if (backspaceDelete(editor, false)) {
+ e.preventDefault();
+ }
+ } else if (e.keyCode === VK.DELETE) {
+ if (backspaceDelete(editor, true)) {
+ e.preventDefault();
+ }
+ }
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Indent.js
- *
- * Released under LGPL License.
- * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ setup: setup,
+ backspaceDelete: backspaceDelete
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce.lists.actions.Indent", [
- "global!tinymce.dom.DOMUtils.DOM",
- "tinymce.lists.core.NodeType",
- "tinymce.lists.core.Bookmark",
- "tinymce.lists.core.Selection"
-], function (DOM, NodeType, Bookmark, Selection) {
- var mergeLists = function (from, to) {
- var node;
</del><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (NodeType.isListNode(from)) {
- while ((node = from.firstChild)) {
- to.appendChild(node);
- }
-
- DOM.remove(from);
- }
- };
-
- var indent = function (li) {
- var sibling, newList, listStyle;
-
- if (li.nodeName === 'DT') {
- DOM.rename(li, 'DD');
- return true;
- }
-
- sibling = li.previousSibling;
-
- if (sibling && NodeType.isListNode(sibling)) {
- sibling.appendChild(li);
- return true;
- }
-
- if (sibling && sibling.nodeName === 'LI' && NodeType.isListNode(sibling.lastChild)) {
- sibling.lastChild.appendChild(li);
- mergeLists(li.lastChild, sibling.lastChild);
- return true;
- }
-
- sibling = li.nextSibling;
-
- if (sibling && NodeType.isListNode(sibling)) {
- sibling.insertBefore(li, sibling.firstChild);
- return true;
- }
-
- /*if (sibling && sibling.nodeName === 'LI' && isListNode(li.lastChild)) {
- return false;
- }*/
-
- sibling = li.previousSibling;
- if (sibling && sibling.nodeName === 'LI') {
- newList = DOM.create(li.parentNode.nodeName);
- listStyle = DOM.getStyle(li.parentNode, 'listStyleType');
- if (listStyle) {
- DOM.setStyle(newList, 'listStyleType', listStyle);
- }
- sibling.appendChild(newList);
- newList.appendChild(li);
- mergeLists(li.lastChild, newList);
- return true;
- }
-
- return false;
- };
-
- var indentSelection = function (editor) {
- var listElements = Selection.getSelectedListItems(editor);
-
- if (listElements.length) {
- var bookmark = Bookmark.createBookmark(editor.selection.getRng(true));
-
- for (var i = 0; i < listElements.length; i++) {
- if (!indent(listElements[i]) && i === 0) {
- break;
- }
- }
-
- editor.selection.setRng(Bookmark.resolveBookmark(bookmark));
- editor.nodeChanged();
-
- return true;
- }
- };
-
- return {
- indentSelection: indentSelection
- };
-});
-
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * plugin.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1292,156 +1499,160 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce.lists.Plugin", [
- "global!tinymce.PluginManager",
- "global!tinymce.util.Tools",
- "global!tinymce.util.VK",
- "tinymce.lists.core.NodeType",
- "tinymce.lists.core.Delete",
- "tinymce.lists.actions.Indent",
- "tinymce.lists.actions.Outdent",
- "tinymce.lists.actions.ToggleList"
-], function (PluginManager, Tools, VK, NodeType, Delete, Indent, Outdent, ToggleList) {
- var queryListCommandState = function (editor, listName) {
- return function () {
- var parentList = editor.dom.getParent(editor.selection.getStart(), 'UL,OL,DL');
- return parentList && parentList.nodeName === listName;
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.lists.Plugin',
+ [
+ 'tinymce.core.PluginManager',
+ 'tinymce.core.util.Tools',
+ 'tinymce.core.util.VK',
+ 'tinymce.plugins.lists.actions.Indent',
+ 'tinymce.plugins.lists.actions.Outdent',
+ 'tinymce.plugins.lists.actions.ToggleList',
+ 'tinymce.plugins.lists.core.Delete',
+ 'tinymce.plugins.lists.core.NodeType'
+ ],
+ function (PluginManager, Tools, VK, Indent, Outdent, ToggleList, Delete, NodeType) {
+ var queryListCommandState = function (editor, listName) {
+ return function () {
+ var parentList = editor.dom.getParent(editor.selection.getStart(), 'UL,OL,DL');
+ return parentList && parentList.nodeName === listName;
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var setupCommands = function (editor) {
- editor.on('BeforeExecCommand', function (e) {
- var cmd = e.command.toLowerCase(), isHandled;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var setupCommands = function (editor) {
+ editor.on('BeforeExecCommand', function (e) {
+ var cmd = e.command.toLowerCase(), isHandled;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (cmd === "indent") {
- if (Indent.indentSelection(editor)) {
- isHandled = true;
- }
- } else if (cmd === "outdent") {
- if (Outdent.outdentSelection(editor)) {
- isHandled = true;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (cmd === "indent") {
+ if (Indent.indentSelection(editor)) {
+ isHandled = true;
+ }
+ } else if (cmd === "outdent") {
+ if (Outdent.outdentSelection(editor)) {
+ isHandled = true;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isHandled) {
- editor.fire('ExecCommand', {command: e.command});
- e.preventDefault();
- return true;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isHandled) {
+ editor.fire('ExecCommand', { command: e.command });
+ e.preventDefault();
+ return true;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addCommand('InsertUnorderedList', function (ui, detail) {
- ToggleList.toggleList(editor, 'UL', detail);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addCommand('InsertUnorderedList', function (ui, detail) {
+ ToggleList.toggleList(editor, 'UL', detail);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addCommand('InsertOrderedList', function (ui, detail) {
- ToggleList.toggleList(editor, 'OL', detail);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addCommand('InsertOrderedList', function (ui, detail) {
+ ToggleList.toggleList(editor, 'OL', detail);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addCommand('InsertDefinitionList', function (ui, detail) {
- ToggleList.toggleList(editor, 'DL', detail);
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addCommand('InsertDefinitionList', function (ui, detail) {
+ ToggleList.toggleList(editor, 'DL', detail);
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var setupStateHandlers = function (editor) {
- editor.addQueryStateHandler('InsertUnorderedList', queryListCommandState(editor, 'UL'));
- editor.addQueryStateHandler('InsertOrderedList', queryListCommandState(editor, 'OL'));
- editor.addQueryStateHandler('InsertDefinitionList', queryListCommandState(editor, 'DL'));
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var setupStateHandlers = function (editor) {
+ editor.addQueryStateHandler('InsertUnorderedList', queryListCommandState(editor, 'UL'));
+ editor.addQueryStateHandler('InsertOrderedList', queryListCommandState(editor, 'OL'));
+ editor.addQueryStateHandler('InsertDefinitionList', queryListCommandState(editor, 'DL'));
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var setupTabKey = function (editor) {
- editor.on('keydown', function (e) {
- // Check for tab but not ctrl/cmd+tab since it switches browser tabs
- if (e.keyCode !== 9 || VK.metaKeyPressed(e)) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var setupTabKey = function (editor) {
+ editor.on('keydown', function (e) {
+ // Check for tab but not ctrl/cmd+tab since it switches browser tabs
+ if (e.keyCode !== 9 || VK.metaKeyPressed(e)) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.dom.getParent(editor.selection.getStart(), 'LI,DT,DD')) {
- e.preventDefault();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.dom.getParent(editor.selection.getStart(), 'LI,DT,DD')) {
+ e.preventDefault();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.shiftKey) {
- Outdent.outdentSelection(editor);
- } else {
- Indent.indentSelection(editor);
- }
- }
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.shiftKey) {
+ Outdent.outdentSelection(editor);
+ } else {
+ Indent.indentSelection(editor);
+ }
+ }
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var setupUi = function (editor) {
- var listState = function (listName) {
- return function () {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var setupUi = function (editor) {
+ var listState = function (listName) {
+ return function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('NodeChange', function (e) {
- var lists = Tools.grep(e.parents, NodeType.isListNode);
- self.active(lists.length > 0 && lists[0].nodeName === listName);
- });
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('NodeChange', function (e) {
+ var lists = Tools.grep(e.parents, NodeType.isListNode);
+ self.active(lists.length > 0 && lists[0].nodeName === listName);
+ });
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var hasPlugin = function (editor, plugin) {
- var plugins = editor.settings.plugins ? editor.settings.plugins : '';
- return Tools.inArray(plugins.split(/[ ,]/), plugin) !== -1;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var hasPlugin = function (editor, plugin) {
+ var plugins = editor.settings.plugins ? editor.settings.plugins : '';
+ return Tools.inArray(plugins.split(/[ ,]/), plugin) !== -1;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!hasPlugin(editor, 'advlist')) {
- editor.addButton('numlist', {
- title: 'Numbered list',
- cmd: 'InsertOrderedList',
- onPostRender: listState('OL')
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!hasPlugin(editor, 'advlist')) {
+ editor.addButton('numlist', {
+ title: 'Numbered list',
+ cmd: 'InsertOrderedList',
+ onPostRender: listState('OL')
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addButton('bullist', {
- title: 'Bullet list',
- cmd: 'InsertUnorderedList',
- onPostRender: listState('UL')
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addButton('bullist', {
+ title: 'Bullet list',
+ cmd: 'InsertUnorderedList',
+ onPostRender: listState('UL')
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addButton('indent', {
- icon: 'indent',
- title: 'Increase indent',
- cmd: 'Indent',
- onPostRender: function (e) {
- var ctrl = e.control;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addButton('indent', {
+ icon: 'indent',
+ title: 'Increase indent',
+ cmd: 'Indent',
+ onPostRender: function (e) {
+ var ctrl = e.control;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('nodechange', function () {
- var blocks = editor.selection.getSelectedBlocks();
- var disable = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('nodechange', function () {
+ var blocks = editor.selection.getSelectedBlocks();
+ var disable = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var i = 0, l = blocks.length; !disable && i < l; i++) {
- var tag = blocks[i].nodeName;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (var i = 0, l = blocks.length; !disable && i < l; i++) {
+ var tag = blocks[i].nodeName;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- disable = (tag === 'LI' && NodeType.isFirstChild(blocks[i]) || tag === 'UL' || tag === 'OL' || tag === 'DD');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ disable = (tag === 'LI' && NodeType.isFirstChild(blocks[i]) || tag === 'UL' || tag === 'OL' || tag === 'DD');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ctrl.disabled(disable);
- });
- }
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ctrl.disabled(disable);
+ });
+ }
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- PluginManager.add('lists', function (editor) {
- setupUi(editor);
- Delete.setup(editor);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ PluginManager.add('lists', function (editor) {
+ setupUi(editor);
+ Delete.setup(editor);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('init', function () {
- setupCommands(editor);
- setupStateHandlers(editor);
- setupTabKey(editor);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('init', function () {
+ setupCommands(editor);
+ setupStateHandlers(editor);
+ setupTabKey(editor);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- backspaceDelete: function (isForward) {
- Delete.backspaceDelete(editor, isForward);
- }
- };
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ backspaceDelete: function (isForward) {
+ Delete.backspaceDelete(editor, isForward);
+ }
+ };
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function () {};
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function () { };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-dem('tinymce.lists.Plugin')();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+dem('tinymce.plugins.lists.Plugin')();
</ins><span class="cx" style="display: block; padding: 0 10px"> })();
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginslistspluginminjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/lists/plugin.min.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/lists/plugin.min.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/lists/plugin.min.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1 +1 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-!function(){var e={},t=function(t){for(var n=e[t],i=n.deps,o=n.defn,a=i.length,s=new Array(a),l=0;l<a;++l)s[l]=r(i[l]);var u=o.apply(null,s);if(void 0===u)throw"module ["+t+"] returned undefined";n.instance=u},n=function(t,n,r){if("string"!=typeof t)throw"module id must be a string";if(void 0===n)throw"no dependencies for "+t;if(void 0===r)throw"no definition function for "+t;e[t]={deps:n,defn:r,instance:void 0}},r=function(n){var r=e[n];if(void 0===r)throw"module ["+n+"] was undefined";return void 0===r.instance&&t(n),r.instance},i=function(e,t){for(var n=e.length,i=new Array(n),o=0;o<n;++o)i.push(r(e[o]));t.apply(null,t)},o={};o.bolt={module:{api:{define:n,require:i,demand:r}}};var a=n,s=function(e,t){a(e,[],function(){return t})};s("1",tinymce.PluginManager),s("2",tinymce.
util.Tools),s("3",tinymce.util.VK),a("4",[],function(){var e=function(e){return e&&3===e.nodeType},t=function(e){return e&&/^(OL|UL|DL)$/.test(e.nodeName)},n=function(e){return e&&/^(LI|DT|DD)$/.test(e.nodeName)},r=function(e){return e&&"BR"===e.nodeName},i=function(e){return e.parentNode.firstChild===e},o=function(e){return e.parentNode.lastChild===e},a=function(e,t){return t&&!!e.schema.getTextBlockElements()[t.nodeName]},s=function(e,t){return!!r(t)&&!(!e.isBlock(t.nextSibling)||r(t.previousSibling))},l=function(e,t,n){var r=e.isEmpty(t);return!(n&&e.select("span[data-mce-type=bookmark]",t).length>0)&&r},u=function(e,t){return e.isChildOf(t,e.getRoot())};return{isTextNode:e,isListNode:t,isListItemNode:n,isBr:r,isFirstChild:i,isLastChild:o,isTextBlock:a,isBogusBr:s,isEmpty:l,isChildOfBody:u}}),s("9",tinymce.dom.TreeWalker),s("a",tinymce.dom.RangeUtils),a(&
quot;b",["2","4"],function(e,t){var n=function(n){return e.grep(n.selection.getSelectedBlocks(),function(e){return t.isListItemNode(e)})};return{getSelectedListItems:n}}),s("h",tinymce.dom.DOMUtils.DOM),a("d",["a","4"],function(e,t){var n=function(n,r){var i=e.getNode(n,r);if(t.isListItemNode(n)&&t.isTextNode(i)){var o=r>=n.childNodes.length?i.data.length:0;return{container:i,offset:o}}return{container:n,offset:r}},r=function(e){var t=e.cloneRange(),r=n(e.startContainer,e.startOffset);t.setStart(r.container,r.offset);var i=n(e.endContainer,e.endOffset);return t.setEnd(i.container,i.offset),t};return{getNormalizedEndPoint:n,normalizeRange:r}}),a("c",["h","4","d"],function(e,t,n){var r=function(t){var n={},r=function(r){var i,o,a;o=t[r?"startContainer":"endContainer"],a=t[r?"startOffset":"endOffset"],1===o.nodeType&&(i=e.cr
eate("span",{"data-mce-type":"bookmark"}),o.hasChildNodes()?(a=Math.min(a,o.childNodes.length-1),r?o.insertBefore(i,o.childNodes[a]):e.insertAfter(i,o.childNodes[a])):o.appendChild(i),o=i,a=0),n[r?"startContainer":"endContainer"]=o,n[r?"startOffset":"endOffset"]=a};return r(!0),t.collapsed||r(),n},i=function(t){function r(n){var r,i,o,a=function(e){for(var t=e.parentNode.firstChild,n=0;t;){if(t===e)return n;1===t.nodeType&&"bookmark"===t.getAttribute("data-mce-type")||n++,t=t.nextSibling}return-1};r=o=t[n?"startContainer":"endContainer"],i=t[n?"startOffset":"endOffset"],r&&(1===r.nodeType&&(i=a(r),r=r.parentNode,e.remove(o)),t[n?"startContainer":"endContainer"]=r,t[n?"startOffset":"endOffset"]=i)}r(!0),r();var i=e.createRng();return i.setStart(t.startContainer,t.startOffset),t.endContainer&am
p;&i.setEnd(t.endContainer,t.endOffset),n.normalizeRange(i)};return{createBookmark:r,resolveBookmark:i}}),a("e",["h","2","4"],function(e,t,n){var r=function(t,r){var i,o=r.parentNode;"LI"===o.nodeName&&o.firstChild===r&&(i=o.previousSibling,i&&"LI"===i.nodeName?(i.appendChild(r),n.isEmpty(t,o)&&e.remove(o)):e.setStyle(o,"listStyleType","none")),n.isListNode(o)&&(i=o.previousSibling,i&&"LI"===i.nodeName&&i.appendChild(r))},i=function(e,n){t.each(t.grep(e.select("ol,ul",n)),function(t){r(e,t)})};return{normalizeList:r,normalizeLists:i}}),s("f",tinymce.dom.BookmarkManager),s("j",tinymce.Env),a("i",["h","j"],function(e,t){var n=function(n,r,i){var o,a,s,l=e.createFragment(),u=n.schema.getBlockElements();if(n.settings.forced_root_block&&(i=i||n.settings.forced_root_block),i
&&(a=e.create(i),a.tagName===n.settings.forced_root_block&&e.setAttribs(a,n.settings.forced_root_block_attrs),l.appendChild(a)),r)for(;o=r.firstChild;){var c=o.nodeName;s||"SPAN"===c&&"bookmark"===o.getAttribute("data-mce-type")||(s=!0),u[c]?(l.appendChild(o),a=null):i?(a||(a=e.create(i),l.appendChild(a)),a.appendChild(o)):l.appendChild(o)}return n.settings.forced_root_block?s||t.ie&&!(t.ie>10)||a.appendChild(e.create("br",{"data-mce-bogus":"1"})):l.appendChild(e.create("br")),l};return{createNewTextBlock:n}}),a("g",["h","2","i","4"],function(e,t,n,r){var i=function(i,o,a,s){var l,u,c,d,f=function(n){t.each(c,function(e){n.parentNode.insertBefore(e,a.parentNode)}),e.remove(n)};for(c=e.select('span[data-mce-type="bookmark"]',o),s=s||n.createNewTextBlock(i,a),l=e.createRng(),l.setStartAfter(a),l.setEndAfter(o),u=l.extractC
ontents(),d=u.firstChild;d;d=d.firstChild)if("LI"===d.nodeName&&i.dom.isEmpty(d)){e.remove(d);break}i.dom.isEmpty(u)||e.insertAfter(u,o),e.insertAfter(s,o),r.isEmpty(i.dom,a.parentNode)&&f(a.parentNode),e.remove(a),r.isEmpty(i.dom,o)&&e.remove(o)};return{splitList:i}}),a("7",["h","4","c","b","g","e","i"],function(e,t,n,r,i,o,a){var s=function(n,r){t.isEmpty(n,r)&&e.remove(r)},l=function(n,r){var l,u=r.parentNode,c=u.parentNode;return u===n.getBody()||("DD"===r.nodeName?(e.rename(r,"DT"),!0):t.isFirstChild(r)&&t.isLastChild(r)?("LI"===c.nodeName?(e.insertAfter(r,c),s(n.dom,c),e.remove(u)):t.isListNode(c)?e.remove(u,!0):(c.insertBefore(a.createNewTextBlock(n,r),u),e.remove(u)),!0):t.isFirstChild(r)?("LI"===c.nodeName?(e.insertAfter(r,c),r.appendChild(u),s(n.dom,c)):t.isListNode(c)?c.insertBefore(r,u):(c.insertBefore(a
.createNewTextBlock(n,r),u),e.remove(r)),!0):t.isLastChild(r)?("LI"===c.nodeName?e.insertAfter(r,c):t.isListNode(c)?e.insertAfter(r,u):(e.insertAfter(a.createNewTextBlock(n,r),u),e.remove(r)),!0):("LI"===c.nodeName?(u=c,l=a.createNewTextBlock(n,r,"LI")):l=t.isListNode(c)?a.createNewTextBlock(n,r,"LI"):a.createNewTextBlock(n,r),i.splitList(n,u,r,l),o.normalizeLists(n.dom,u.parentNode),!0))},u=function(e){var t=r.getSelectedListItems(e);if(t.length){var i,o,a=n.createBookmark(e.selection.getRng(!0)),s=e.getBody();for(i=t.length;i--;)for(var u=t[i].parentNode;u&&u!==s;){for(o=t.length;o--;)if(t[o]===u){t.splice(i,1);break}u=u.parentNode}for(i=0;i<t.length&&(l(e,t[i])||0!==i);i++);return e.selection.setRng(n.resolveBookmark(a)),e.nodeChanged(),!0}};return{outdent:l,outdentSelection:u}}),a("8",["2","f","b","4","c","g","e","7"],function(e,t,n
,r,i,o,a,s){var l=function(e,t,n){var r=n["list-style-type"]?n["list-style-type"]:null;e.setStyle(t,"list-style-type",r)},u=function(t,n){e.each(n,function(e,n){t.setAttribute(n,e)})},c=function(t,n,r){u(n,r["list-attributes"]),e.each(t.select("li",n),function(e){u(e,r["list-item-attributes"])})},d=function(e,t,n){l(e,t,n),c(e,t,n)},f=function(e,t,n){var i,o,a=e.getBody();for(i=t[n?"startContainer":"endContainer"],o=t[n?"startOffset":"endOffset"],1===i.nodeType&&(i=i.childNodes[Math.min(o,i.childNodes.length-1)]||i);i.parentNode!==a;){if(r.isTextBlock(e,i))return i;if(/^(TD|TH)$/.test(i.parentNode.nodeName))return i;i=i.parentNode}return i},p=function(n,i){for(var o,a=[],s=n.getBody(),l=n.dom,u=f(n,i,!0),c=f(n,i,!1),d=[],p=u;p&&(d.push(p),p!==c);p=p.nextSibling);return e.each(d,function(e){if(r.isTextBlock(n,e))return a.push(e),void(o=null);if(l.isBlock(e)||r.isBr(e))r
eturn r.isBr(e)&&l.remove(e),void(o=null);var i=e.nextSibling;return t.isBookmarkNode(e)&&(r.isTextBlock(n,i)||!i&&e.parentNode===s)?void(o=null):(o||(o=l.create("p"),e.parentNode.insertBefore(o,e),a.push(o)),void o.appendChild(e))}),a},h=function(t,n,o){var a,s=t.selection.getRng(!0),l="LI",u=t.dom;o=o?o:{},"false"!==u.getContentEditable(t.selection.getNode())&&(n=n.toUpperCase(),"DL"===n&&(l="DT"),a=i.createBookmark(s),e.each(p(t,s),function(e){var i,a,s=function(e){var t=u.getStyle(e,"list-style-type"),n=o?o["list-style-type"]:"";return n=null===n?"":n,t===n};a=e.previousSibling,a&&r.isListNode(a)&&a.nodeName===n&&s(a)?(i=a,e=u.rename(e,l),a.appendChild(e)):(i=u.create(n),e.parentNode.insertBefore(i,e),i.appendChild(e),e=u.rename(e,l)),d(u,i,o),C(t.dom,i)}),t.selection.setRng(i.resolveBookmark(a)))},m=function(t){var l=i.createB
ookmark(t.selection.getRng(!0)),u=t.getBody(),c=n.getSelectedListItems(t),d=e.grep(c,function(e){return t.dom.isEmpty(e)});c=e.grep(c,function(e){return!t.dom.isEmpty(e)}),e.each(d,function(e){if(r.isEmpty(t.dom,e))return void s.outdent(t,e)}),e.each(c,function(e){var n,i;if(e.parentNode!==t.getBody()){for(n=e;n&&n!==u;n=n.parentNode)r.isListNode(n)&&(i=n);o.splitList(t,i,e),a.normalizeLists(t.dom,i.parentNode)}}),t.selection.setRng(i.resolveBookmark(l))},g=function(e,t){return e&&t&&r.isListNode(e)&&e.nodeName===t.nodeName},v=function(e,t,n){var r=e.getStyle(t,"list-style-type",!0),i=e.getStyle(n,"list-style-type",!0);return r===i},y=function(e,t){return e.className===t.className},b=function(e,t,n){return g(t,n)&&v(e,t,n)&&y(t,n)},C=function(e,t){var n,r;if(n=t.nextSibling,b(e,t,n)){for(;r=n.firstChild;)t.appendChild(r);e.remove(n)}if(n=t.previousSibling,b(e,t,n)){for(;r=n.lastChild;)t.insertBefore(r,t.firs
tChild);e.remove(n)}},x=function(e,t,n){var r=e.dom.getParent(e.selection.getStart(),"OL,UL,DL");if(n=n?n:{},r!==e.getBody())if(r)if(r.nodeName===t)m(e,t);else{var o=i.createBookmark(e.selection.getRng(!0));d(e.dom,r,n),C(e.dom,e.dom.rename(r,t)),e.selection.setRng(i.resolveBookmark(o))}else h(e,t,n)};return{toggleList:x,removeList:m,mergeWithAdjacentLists:C}}),a("5",["9","a","3","b","4","c","d","e","8"],function(e,t,n,r,i,o,a,s,l){var u=function(n,r,o){var a,s,l=r.startContainer,u=r.startOffset;if(3===l.nodeType&&(o?u<l.data.length:u>0))return l;for(a=n.schema.getNonEmptyElements(),1===l.nodeType&&(l=t.getNode(l,u)),s=new e(l,n.getBody()),o&&i.isBogusBr(n.dom,l)&&s.next();l=s[o?"next":"prev2"]();){if("LI"===l.nodeName&&!l.hasChildNodes())return l;if(a[l.nodeName])return l;if(3===l.nodeType&&
l.data.length>0)return l}},c=function(e,t,n){var r,o,a=t.parentNode;if(i.isChildOfBody(e,t)&&i.isChildOfBody(e,n)){if(i.isListNode(n.lastChild)&&(o=n.lastChild),a===n.lastChild&&i.isBr(a.previousSibling)&&e.remove(a.previousSibling),r=n.lastChild,r&&i.isBr(r)&&t.hasChildNodes()&&e.remove(r),i.isEmpty(e,n,!0)&&e.$(n).empty(),!i.isEmpty(e,t,!0))for(;r=t.firstChild;)n.appendChild(r);o&&n.appendChild(o),e.remove(t),i.isEmpty(e,a)&&a!==e.getRoot()&&e.remove(a)}},d=function(e,t){var n,r,s,d=e.dom,f=e.selection,p=d.getParent(f.getStart(),"LI");if(p){if(n=p.parentNode,n===e.getBody()&&i.isEmpty(d,n))return!0;if(r=a.normalizeRange(f.getRng(!0)),s=d.getParent(u(e,r,t),"LI"),s&&s!==p){var h=o.createBookmark(r);return t?c(d,s,p):c(d,p,s),e.selection.setRng(o.resolveBookmark(h)),!0}if(!s&&!t&&l.removeList(e,n.nodeName))return!0}return!1},f=function(e,t){v
ar n=e.dom,r=n.getParent(e.selection.getStart(),n.isBlock);if(r&&n.isEmpty(r)){var i=a.normalizeRange(e.selection.getRng(!0)),o=n.getParent(u(e,i,t),"LI");if(o)return e.undoManager.transact(function(){n.remove(r),l.mergeWithAdjacentLists(n,o.parentNode),e.selection.select(o,!0),e.selection.collapse(t)}),!0}return!1},p=function(e,t){return d(e,t)||f(e,t)},h=function(e){var t=e.dom.getParent(e.selection.getStart(),"LI,DT,DD");return!!(t||r.getSelectedListItems(e).length>0)&&(e.undoManager.transact(function(){e.execCommand("Delete"),s.normalizeLists(e.dom,e.getBody())}),!0)},m=function(e,t){return e.selection.isCollapsed()?p(e,t):h(e)},g=function(e){e.on("keydown",function(t){t.keyCode===n.BACKSPACE?m(e,!1)&&t.preventDefault():t.keyCode===n.DELETE&&m(e,!0)&&t.preventDefault()})};return{setup:g,backspaceDelete:m}}),a("6",["h","4","c","b"],function(e,t,n,r)
{var i=function(n,r){var i;if(t.isListNode(n)){for(;i=n.firstChild;)r.appendChild(i);e.remove(n)}},o=function(n){var r,o,a;return"DT"===n.nodeName?(e.rename(n,"DD"),!0):(r=n.previousSibling,r&&t.isListNode(r)?(r.appendChild(n),!0):r&&"LI"===r.nodeName&&t.isListNode(r.lastChild)?(r.lastChild.appendChild(n),i(n.lastChild,r.lastChild),!0):(r=n.nextSibling,r&&t.isListNode(r)?(r.insertBefore(n,r.firstChild),!0):(r=n.previousSibling,!(!r||"LI"!==r.nodeName)&&(o=e.create(n.parentNode.nodeName),a=e.getStyle(n.parentNode,"listStyleType"),a&&e.setStyle(o,"listStyleType",a),r.appendChild(o),o.appendChild(n),i(n.lastChild,o),!0))))},a=function(e){var t=r.getSelectedListItems(e);if(t.length){for(var i=n.createBookmark(e.selection.getRng(!0)),a=0;a<t.length&&(o(t[a])||0!==a);a++);return e.selection.setRng(n.resolveBookmark(i)),e.nodeChanged(),!0}};return{indentSelection:a}}),a(&q
uot;0",["1","2","3","4","5","6","7","8"],function(e,t,n,r,i,o,a,s){var l=function(e,t){return function(){var n=e.dom.getParent(e.selection.getStart(),"UL,OL,DL");return n&&n.nodeName===t}},u=function(e){e.on("BeforeExecCommand",function(t){var n,r=t.command.toLowerCase();if("indent"===r?o.indentSelection(e)&&(n=!0):"outdent"===r&&a.outdentSelection(e)&&(n=!0),n)return e.fire("ExecCommand",{command:t.command}),t.preventDefault(),!0}),e.addCommand("InsertUnorderedList",function(t,n){s.toggleList(e,"UL",n)}),e.addCommand("InsertOrderedList",function(t,n){s.toggleList(e,"OL",n)}),e.addCommand("InsertDefinitionList",function(t,n){s.toggleList(e,"DL",n)})},c=function(e){e.addQueryStateHandler("InsertUnorderedList",l(e,"UL")),e.addQueryStateHandle
r("InsertOrderedList",l(e,"OL")),e.addQueryStateHandler("InsertDefinitionList",l(e,"DL"))},d=function(e){e.on("keydown",function(t){9!==t.keyCode||n.metaKeyPressed(t)||e.dom.getParent(e.selection.getStart(),"LI,DT,DD")&&(t.preventDefault(),t.shiftKey?a.outdentSelection(e):o.indentSelection(e))})},f=function(e){var n=function(n){return function(){var i=this;e.on("NodeChange",function(e){var o=t.grep(e.parents,r.isListNode);i.active(o.length>0&&o[0].nodeName===n)})}},i=function(e,n){var r=e.settings.plugins?e.settings.plugins:"";return t.inArray(r.split(/[ ,]/),n)!==-1};i(e,"advlist")||(e.addButton("numlist",{title:"Numbered list",cmd:"InsertOrderedList",onPostRender:n("OL")}),e.addButton("bullist",{title:"Bullet list",cmd:"InsertUnorderedList",onPostRender:n("UL")})),e.addButton("indent",
{icon:"indent",title:"Increase indent",cmd:"Indent",onPostRender:function(t){var n=t.control;e.on("nodechange",function(){for(var t=e.selection.getSelectedBlocks(),i=!1,o=0,a=t.length;!i&&o<a;o++){var s=t[o].nodeName;i="LI"===s&&r.isFirstChild(t[o])||"UL"===s||"OL"===s||"DD"===s}n.disabled(i)})}})};return e.add("lists",function(e){return f(e),i.setup(e),e.on("init",function(){u(e),c(e),d(e)}),{backspaceDelete:function(t){i.backspaceDelete(e,t)}}}),function(){}}),r("0")()}();
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+!function(){var a={},b=function(b){for(var c=a[b],e=c.deps,f=c.defn,g=e.length,h=new Array(g),i=0;i<g;++i)h[i]=d(e[i]);var j=f.apply(null,h);if(void 0===j)throw"module ["+b+"] returned undefined";c.instance=j},c=function(b,c,d){if("string"!=typeof b)throw"module id must be a string";if(void 0===c)throw"no dependencies for "+b;if(void 0===d)throw"no definition function for "+b;a[b]={deps:c,defn:d,instance:void 0}},d=function(c){var d=a[c];if(void 0===d)throw"module ["+c+"] was undefined";return void 0===d.instance&&b(c),d.instance},e=function(a,b){for(var c=a.length,e=new Array(c),f=0;f<c;++f)e.push(d(a[f]));b.apply(null,b)},f={};f.bolt={module:{api:{define:c,require:e,demand:d}}};var g=c,h=function(a,b){g(a,[],function(){return b})};h("9",tinymce.util.Tools.resolve),g("1",[&q
uot;9"],function(a){return a("tinymce.PluginManager")}),g("2",["9"],function(a){return a("tinymce.util.Tools")}),g("3",["9"],function(a){return a("tinymce.util.VK")}),g("a",["9"],function(a){return a("tinymce.dom.DOMUtils")}),g("8",[],function(){var a=function(a){return a&&3===a.nodeType},b=function(a){return a&&/^(OL|UL|DL)$/.test(a.nodeName)},c=function(a){return a&&/^(LI|DT|DD)$/.test(a.nodeName)},d=function(a){return a&&"BR"===a.nodeName},e=function(a){return a.parentNode.firstChild===a},f=function(a){return a.parentNode.lastChild===a},g=function(a,b){return b&&!!a.schema.getTextBlockElements()[b.nodeName]},h=function(a,b){return!!d(b)&&!(!a.isBlock(b.nextSibling)||d(b.previousSibling))},i=function(a,b,c){var d=a.isEmpty(b);return!(c&&a.select("span[data-mce-type=bookmark]",b).length>0)&a
mp;&d},j=function(a,b){return a.isChildOf(b,a.getRoot())};return{isTextNode:a,isListNode:b,isListItemNode:c,isBr:d,isFirstChild:e,isLastChild:f,isTextBlock:g,isBogusBr:h,isEmpty:i,isChildOfBody:j}}),g("h",["9"],function(a){return a("tinymce.dom.RangeUtils")}),g("j",["h","8"],function(a,b){var c=function(c,d){var e=a.getNode(c,d);if(b.isListItemNode(c)&&b.isTextNode(e)){var f=d>=c.childNodes.length?e.data.length:0;return{container:e,offset:f}}return{container:c,offset:d}},d=function(a){var b=a.cloneRange(),d=c(a.startContainer,a.startOffset);b.setStart(d.container,d.offset);var e=c(a.endContainer,a.endOffset);return b.setEnd(e.container,e.offset),b};return{getNormalizedEndPoint:c,normalizeRange:d}}),g("b",["a","8","j"],function(a,b,c){var d=a.DOM,e=function(a){var b={},c=function(c){var e,f,g;f=a[c?"startContainer":"endContainer"],g=a[c?"startOff
set":"endOffset"],1===f.nodeType&&(e=d.create("span",{"data-mce-type":"bookmark"}),f.hasChildNodes()?(g=Math.min(g,f.childNodes.length-1),c?f.insertBefore(e,f.childNodes[g]):d.insertAfter(e,f.childNodes[g])):f.appendChild(e),f=e,g=0),b[c?"startContainer":"endContainer"]=f,b[c?"startOffset":"endOffset"]=g};return c(!0),a.collapsed||c(),b},f=function(a){function b(b){var c,e,f,g=function(a){for(var b=a.parentNode.firstChild,c=0;b;){if(b===a)return c;1===b.nodeType&&"bookmark"===b.getAttribute("data-mce-type")||c++,b=b.nextSibling}return-1};c=f=a[b?"startContainer":"endContainer"],e=a[b?"startOffset":"endOffset"],c&&(1===c.nodeType&&(e=g(c),c=c.parentNode,d.remove(f)),a[b?"startContainer":"endContainer"]=c,a[b?"startOffset":"endOffset"]=e)}b(!0),b();var e=d.createRng();ret
urn e.setStart(a.startContainer,a.startOffset),a.endContainer&&e.setEnd(a.endContainer,a.endOffset),c.normalizeRange(e)};return{createBookmark:e,resolveBookmark:f}}),g("c",["2","8"],function(a,b){var c=function(c){return a.grep(c.selection.getSelectedBlocks(),function(a){return b.isListItemNode(a)})};return{getSelectedListItems:c}}),g("4",["a","b","8","c"],function(a,b,c,d){var e=a.DOM,f=function(a,b){var d;if(c.isListNode(a)){for(;d=a.firstChild;)b.appendChild(d);e.remove(a)}},g=function(a){var b,d,g;return"DT"===a.nodeName?(e.rename(a,"DD"),!0):(b=a.previousSibling,b&&c.isListNode(b)?(b.appendChild(a),!0):b&&"LI"===b.nodeName&&c.isListNode(b.lastChild)?(b.lastChild.appendChild(a),f(a.lastChild,b.lastChild),!0):(b=a.nextSibling,b&&c.isListNode(b)?(b.insertBefore(a,b.firstChild),!0):(b=a.previousSibling,!(!b||"LI"!==b.nodeNam
e)&&(d=e.create(a.parentNode.nodeName),g=e.getStyle(a.parentNode,"listStyleType"),g&&e.setStyle(d,"listStyleType",g),b.appendChild(d),d.appendChild(a),f(a.lastChild,d),!0))))},h=function(a){var c=d.getSelectedListItems(a);if(c.length){for(var e=b.createBookmark(a.selection.getRng(!0)),f=0;f<c.length&&(g(c[f])||0!==f);f++);return a.selection.setRng(b.resolveBookmark(e)),a.nodeChanged(),!0}};return{indentSelection:h}}),g("d",["a","2","8"],function(a,b,c){var d=a.DOM,e=function(a,b){var e,f=b.parentNode;"LI"===f.nodeName&&f.firstChild===b&&(e=f.previousSibling,e&&"LI"===e.nodeName?(e.appendChild(b),c.isEmpty(a,f)&&d.remove(f)):d.setStyle(f,"listStyleType","none")),c.isListNode(f)&&(e=f.previousSibling,e&&"LI"===e.nodeName&&e.appendChild(b))},f=function(a,c){b.each(b.grep(a.select("ol,ul"
;,c)),function(b){e(a,b)})};return{normalizeList:e,normalizeLists:f}}),g("k",["9"],function(a){return a("tinymce.Env")}),g("f",["a","k"],function(a,b){var c=a.DOM,d=function(a,d,e){var f,g,h,i=c.createFragment(),j=a.schema.getBlockElements();if(a.settings.forced_root_block&&(e=e||a.settings.forced_root_block),e&&(g=c.create(e),g.tagName===a.settings.forced_root_block&&c.setAttribs(g,a.settings.forced_root_block_attrs),i.appendChild(g)),d)for(;f=d.firstChild;){var k=f.nodeName;h||"SPAN"===k&&"bookmark"===f.getAttribute("data-mce-type")||(h=!0),j[k]?(i.appendChild(f),g=null):e?(g||(g=c.create(e),i.appendChild(g)),g.appendChild(f)):i.appendChild(f)}return a.settings.forced_root_block?h||b.ie&&!(b.ie>10)||g.appendChild(c.create("br",{"data-mce-bogus":"1"})):i.appendChild(c.create("br")),i};return{createNewTextBlock:d
}}),g("e",["a","8","f","2"],function(a,b,c,d){var e=a.DOM,f=function(a,f,g,h){var i,j,k,l,m=function(a){d.each(k,function(b){a.parentNode.insertBefore(b,g.parentNode)}),e.remove(a)};for(k=e.select('span[data-mce-type="bookmark"]',f),h=h||c.createNewTextBlock(a,g),i=e.createRng(),i.setStartAfter(g),i.setEndAfter(f),j=i.extractContents(),l=j.firstChild;l;l=l.firstChild)if("LI"===l.nodeName&&a.dom.isEmpty(l)){e.remove(l);break}a.dom.isEmpty(j)||e.insertAfter(j,f),e.insertAfter(h,f),b.isEmpty(a.dom,g.parentNode)&&m(g.parentNode),e.remove(g),b.isEmpty(a.dom,f)&&e.remove(f)};return{splitList:f}}),g("5",["a","b","8","d","c","e","f"],function(a,b,c,d,e,f,g){var h=a.DOM,i=function(a,b){c.isEmpty(a,b)&&h.remove(b)},j=function(a,b){var e,j=b.parentNode,k=j.parentNode;return j===a.getBody()||("DD"===b.node
Name?(h.rename(b,"DT"),!0):c.isFirstChild(b)&&c.isLastChild(b)?("LI"===k.nodeName?(h.insertAfter(b,k),i(a.dom,k),h.remove(j)):c.isListNode(k)?h.remove(j,!0):(k.insertBefore(g.createNewTextBlock(a,b),j),h.remove(j)),!0):c.isFirstChild(b)?("LI"===k.nodeName?(h.insertAfter(b,k),b.appendChild(j),i(a.dom,k)):c.isListNode(k)?k.insertBefore(b,j):(k.insertBefore(g.createNewTextBlock(a,b),j),h.remove(b)),!0):c.isLastChild(b)?("LI"===k.nodeName?h.insertAfter(b,k):c.isListNode(k)?h.insertAfter(b,j):(h.insertAfter(g.createNewTextBlock(a,b),j),h.remove(b)),!0):("LI"===k.nodeName?(j=k,e=g.createNewTextBlock(a,b,"LI")):e=c.isListNode(k)?g.createNewTextBlock(a,b,"LI"):g.createNewTextBlock(a,b),f.splitList(a,j,b,e),d.normalizeLists(a.dom,j.parentNode),!0))},k=function(a){var c=e.getSelectedListItems(a);if(c.length){var d,f,g=b.createBookmark(a.selection.getRng(!0)),h=a.getBody();for(d=c.length;d--;)for(var i=c[d].parentNod
e;i&&i!==h;){for(f=c.length;f--;)if(c[f]===i){c.splice(d,1);break}i=i.parentNode}for(d=0;d<c.length&&(j(a,c[d])||0!==d);d++);return a.selection.setRng(b.resolveBookmark(g)),a.nodeChanged(),!0}};return{outdent:j,outdentSelection:k}}),g("g",["9"],function(a){return a("tinymce.dom.BookmarkManager")}),g("6",["g","2","5","b","8","d","c","e"],function(a,b,c,d,e,f,g,h){var i=function(a,b,c){var d=c["list-style-type"]?c["list-style-type"]:null;a.setStyle(b,"list-style-type",d)},j=function(a,c){b.each(c,function(b,c){a.setAttribute(c,b)})},k=function(a,c,d){j(c,d["list-attributes"]),b.each(a.select("li",c),function(a){j(a,d["list-item-attributes"])})},l=function(a,b,c){i(a,b,c),k(a,b,c)},m=function(a,b,c){var d,f,g=a.getBody();for(d=b[c?"startContainer":"endContainer"],f=b[c?&
quot;startOffset":"endOffset"],1===d.nodeType&&(d=d.childNodes[Math.min(f,d.childNodes.length-1)]||d);d.parentNode!==g;){if(e.isTextBlock(a,d))return d;if(/^(TD|TH)$/.test(d.parentNode.nodeName))return d;d=d.parentNode}return d},n=function(c,d){for(var f,g=[],h=c.getBody(),i=c.dom,j=m(c,d,!0),k=m(c,d,!1),l=[],n=j;n&&(l.push(n),n!==k);n=n.nextSibling);return b.each(l,function(b){if(e.isTextBlock(c,b))return g.push(b),void(f=null);if(i.isBlock(b)||e.isBr(b))return e.isBr(b)&&i.remove(b),void(f=null);var d=b.nextSibling;return a.isBookmarkNode(b)&&(e.isTextBlock(c,d)||!d&&b.parentNode===h)?void(f=null):(f||(f=i.create("p"),b.parentNode.insertBefore(f,b),g.push(f)),void f.appendChild(b))}),g},o=function(a,c,f){var g,h=a.selection.getRng(!0),i="LI",j=a.dom;f=f?f:{},"false"!==j.getContentEditable(a.selection.getNode())&&(c=c.toUpperCase(),"DL"===c&&(i="DT"),g=d.createBo
okmark(h),b.each(n(a,h),function(b){var d,g,h=function(a){var b=j.getStyle(a,"list-style-type"),c=f?f["list-style-type"]:"";return c=null===c?"":c,b===c};g=b.previousSibling,g&&e.isListNode(g)&&g.nodeName===c&&h(g)?(d=g,b=j.rename(b,i),g.appendChild(b)):(d=j.create(c),b.parentNode.insertBefore(d,b),d.appendChild(b),b=j.rename(b,i)),l(j,d,f),u(a.dom,d)}),a.selection.setRng(d.resolveBookmark(g)))},p=function(a){var i=d.createBookmark(a.selection.getRng(!0)),j=a.getBody(),k=g.getSelectedListItems(a),l=b.grep(k,function(b){return a.dom.isEmpty(b)});k=b.grep(k,function(b){return!a.dom.isEmpty(b)}),b.each(l,function(b){if(e.isEmpty(a.dom,b))return void c.outdent(a,b)}),b.each(k,function(b){var c,d;if(b.parentNode!==a.getBody()){for(c=b;c&&c!==j;c=c.parentNode)e.isListNode(c)&&(d=c);h.splitList(a,d,b),f.normalizeLists(a.dom,d.parentNode)}}),a.selection.setRng(d.resolveBookmark(i))},q=function(a,b){return a&
&b&&e.isListNode(a)&&a.nodeName===b.nodeName},r=function(a,b,c){var d=a.getStyle(b,"list-style-type",!0),e=a.getStyle(c,"list-style-type",!0);return d===e},s=function(a,b){return a.className===b.className},t=function(a,b,c){return q(b,c)&&r(a,b,c)&&s(b,c)},u=function(a,b){var c,d;if(c=b.nextSibling,t(a,b,c)){for(;d=c.firstChild;)b.appendChild(d);a.remove(c)}if(c=b.previousSibling,t(a,b,c)){for(;d=c.lastChild;)b.insertBefore(d,b.firstChild);a.remove(c)}},v=function(a,b,c){var e=a.dom.getParent(a.selection.getStart(),"OL,UL,DL");if(c=c?c:{},e!==a.getBody())if(e)if(e.nodeName===b)p(a,b);else{var f=d.createBookmark(a.selection.getRng(!0));l(a.dom,e,c),u(a.dom,a.dom.rename(e,b)),a.selection.setRng(d.resolveBookmark(f))}else o(a,b,c)};return{toggleList:v,removeList:p,mergeWithAdjacentLists:u}}),g("i",["9"],function(a){return a("tinymce.dom.TreeWalker")}),g("7",["h","i&q
uot;,"3","6","b","8","d","j","c"],function(a,b,c,d,e,f,g,h,i){var j=function(c,d,e){var g,h,i=d.startContainer,j=d.startOffset;if(3===i.nodeType&&(e?j<i.data.length:j>0))return i;for(g=c.schema.getNonEmptyElements(),1===i.nodeType&&(i=a.getNode(i,j)),h=new b(i,c.getBody()),e&&f.isBogusBr(c.dom,i)&&h.next();i=h[e?"next":"prev2"]();){if("LI"===i.nodeName&&!i.hasChildNodes())return i;if(g[i.nodeName])return i;if(3===i.nodeType&&i.data.length>0)return i}},k=function(a,b,c){var d,e,g=b.parentNode;if(f.isChildOfBody(a,b)&&f.isChildOfBody(a,c)){if(f.isListNode(c.lastChild)&&(e=c.lastChild),g===c.lastChild&&f.isBr(g.previousSibling)&&a.remove(g.previousSibling),d=c.lastChild,d&&f.isBr(d)&&b.hasChildNodes()&&a.remove(d),f.isEmpty(a,c,!0)&&a.$(c).empty(),!f.isEmpty(a,b,!0))fo
r(;d=b.firstChild;)c.appendChild(d);e&&c.appendChild(e),a.remove(b),f.isEmpty(a,g)&&g!==a.getRoot()&&a.remove(g)}},l=function(a,b){var c,g,i,l=a.dom,m=a.selection,n=l.getParent(m.getStart(),"LI");if(n){if(c=n.parentNode,c===a.getBody()&&f.isEmpty(l,c))return!0;if(g=h.normalizeRange(m.getRng(!0)),i=l.getParent(j(a,g,b),"LI"),i&&i!==n){var o=e.createBookmark(g);return b?k(l,i,n):k(l,n,i),a.selection.setRng(e.resolveBookmark(o)),!0}if(!i&&!b&&d.removeList(a,c.nodeName))return!0}return!1},m=function(a,b){var c=a.dom,e=c.getParent(a.selection.getStart(),c.isBlock);if(e&&c.isEmpty(e)){var f=h.normalizeRange(a.selection.getRng(!0)),g=c.getParent(j(a,f,b),"LI");if(g)return a.undoManager.transact(function(){c.remove(e),d.mergeWithAdjacentLists(c,g.parentNode),a.selection.select(g,!0),a.selection.collapse(b)}),!0}return!1},n=function(a,b){return l(a,b)||m(a,b)},o=function(a){var b=a.dom.getParent(a.s
election.getStart(),"LI,DT,DD");return!!(b||i.getSelectedListItems(a).length>0)&&(a.undoManager.transact(function(){a.execCommand("Delete"),g.normalizeLists(a.dom,a.getBody())}),!0)},p=function(a,b){return a.selection.isCollapsed()?n(a,b):o(a)},q=function(a){a.on("keydown",function(b){b.keyCode===c.BACKSPACE?p(a,!1)&&b.preventDefault():b.keyCode===c.DELETE&&p(a,!0)&&b.preventDefault()})};return{setup:q,backspaceDelete:p}}),g("0",["1","2","3","4","5","6","7","8"],function(a,b,c,d,e,f,g,h){var i=function(a,b){return function(){var c=a.dom.getParent(a.selection.getStart(),"UL,OL,DL");return c&&c.nodeName===b}},j=function(a){a.on("BeforeExecCommand",function(b){var c,f=b.command.toLowerCase();if("indent"===f?d.indentSelection(a)&&(c=!0):"outdent"===f&&e.outdentSelection(a
)&&(c=!0),c)return a.fire("ExecCommand",{command:b.command}),b.preventDefault(),!0}),a.addCommand("InsertUnorderedList",function(b,c){f.toggleList(a,"UL",c)}),a.addCommand("InsertOrderedList",function(b,c){f.toggleList(a,"OL",c)}),a.addCommand("InsertDefinitionList",function(b,c){f.toggleList(a,"DL",c)})},k=function(a){a.addQueryStateHandler("InsertUnorderedList",i(a,"UL")),a.addQueryStateHandler("InsertOrderedList",i(a,"OL")),a.addQueryStateHandler("InsertDefinitionList",i(a,"DL"))},l=function(a){a.on("keydown",function(b){9!==b.keyCode||c.metaKeyPressed(b)||a.dom.getParent(a.selection.getStart(),"LI,DT,DD")&&(b.preventDefault(),b.shiftKey?e.outdentSelection(a):d.indentSelection(a))})},m=function(a){var c=function(c){return function(){var d=this;a.on("NodeChange",function(a){var e=b.grep(a.parents,h.isListNod
e);d.active(e.length>0&&e[0].nodeName===c)})}},d=function(a,c){var d=a.settings.plugins?a.settings.plugins:"";return b.inArray(d.split(/[ ,]/),c)!==-1};d(a,"advlist")||(a.addButton("numlist",{title:"Numbered list",cmd:"InsertOrderedList",onPostRender:c("OL")}),a.addButton("bullist",{title:"Bullet list",cmd:"InsertUnorderedList",onPostRender:c("UL")})),a.addButton("indent",{icon:"indent",title:"Increase indent",cmd:"Indent",onPostRender:function(b){var c=b.control;a.on("nodechange",function(){for(var b=a.selection.getSelectedBlocks(),d=!1,e=0,f=b.length;!d&&e<f;e++){var g=b[e].nodeName;d="LI"===g&&h.isFirstChild(b[e])||"UL"===g||"OL"===g||"DD"===g}c.disabled(d)})}})};return a.add("lists",function(a){return m(a),g.setup(a),a.on("init",function(){j(a
),k(a),l(a)}),{backspaceDelete:function(b){g.backspaceDelete(a,b)}}}),function(){}}),d("0")()}();
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginsmediamoxieplayerswf"></a>
<div class="binary"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/src/wp-includes/js/tinymce/plugins/media/moxieplayer.swf</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginsmediapluginjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/media/plugin.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/media/plugin.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/media/plugin.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -81,1341 +81,1708 @@
</span><span class="cx" style="display: block; padding: 0 10px"> define(id, [], function () { return ref; });
</span><span class="cx" style="display: block; padding: 0 10px"> };
</span><span class="cx" style="display: block; padding: 0 10px"> /*jsc
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-["tinymce.media.Plugin","global!tinymce.PluginManager","tinymce.media.ui.Dialog","tinymce.media.core.Sanitize","tinymce.media.core.UpdateHtml","tinymce.media.core.Nodes","global!tinymce.util.Delay","tinymce.media.core.HtmlToData","global!tinymce.html.Writer","global!tinymce.html.SaxParser","global!tinymce.html.Schema","global!tinymce.dom.DOMUtils.DOM","tinymce.media.core.Size","tinymce.media.core.Service","global!tinymce.util.Tools","global!tinymce.Env","tinymce.media.ui.SizeManager","tinymce.media.core.VideoScript","global!tinymce.html.Node","tinymce.media.core.DataToHtml","global!tinymce.util.Promise","tinymce.media.core.Mime","tinymce.media.core.UrlPatterns"]
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+["tinymce.plugins.media.Plugin","tinymce.core.html.Node","tinymce.core.PluginManager","tinymce.core.util.Tools","tinymce.plugins.media.core.Nodes","tinymce.plugins.media.core.Sanitize","tinymce.plugins.media.core.UpdateHtml","tinymce.plugins.media.ui.Dialog","global!tinymce.util.Tools.resolve","tinymce.core.html.Writer","tinymce.core.html.SaxParser","tinymce.core.html.Schema","tinymce.plugins.media.core.VideoScript","tinymce.core.Env","tinymce.core.dom.DOMUtils","tinymce.plugins.media.core.Size","tinymce.core.util.Delay","tinymce.plugins.media.core.HtmlToData","tinymce.plugins.media.core.Service","tinymce.plugins.media.ui.SizeManager","tinymce.plugins.media.core.DataToHtml","ti
nymce.core.util.Promise","tinymce.plugins.media.core.Mime","tinymce.plugins.media.core.UrlPatterns"]
</ins><span class="cx" style="display: block; padding: 0 10px"> jsc*/
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-defineGlobal("global!tinymce.PluginManager", tinymce.PluginManager);
-defineGlobal("global!tinymce.util.Delay", tinymce.util.Delay);
-defineGlobal("global!tinymce.util.Tools", tinymce.util.Tools);
-defineGlobal("global!tinymce.html.SaxParser", tinymce.html.SaxParser);
-defineGlobal("global!tinymce.html.Schema", tinymce.html.Schema);
-defineGlobal("global!tinymce.dom.DOMUtils.DOM", tinymce.dom.DOMUtils.DOM);
-define('tinymce.media.core.VideoScript', [
-], function () {
- var getVideoScriptMatch = function (prefixes, src) {
- // var prefixes = editor.settings.media_scripts;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+defineGlobal("global!tinymce.util.Tools.resolve", tinymce.util.Tools.resolve);
+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (prefixes) {
- for (var i = 0; i < prefixes.length; i++) {
- if (src.indexOf(prefixes[i].filter) !== -1) {
- return prefixes[i];
- }
- }
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.html.Node',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.html.Node');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- getVideoScriptMatch: getVideoScriptMatch
- };
-});
-define('tinymce.media.core.Size', [
-], function () {
- var trimPx = function (value) {
- return value.replace(/px$/, '');
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var addPx = function (value) {
- return /^[0-9.]+$/.test(value) ? (value + 'px') : value;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.PluginManager',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.PluginManager');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getSize = function (name) {
- return function (elm) {
- return elm ? trimPx(elm.style[name]) : '';
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var setSize = function (name) {
- return function (elm, value) {
- if (elm) {
- elm.style[name] = addPx(value);
- }
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.Tools',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.util.Tools');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- getMaxWidth: getSize('maxWidth'),
- getMaxHeight: getSize('maxHeight'),
- setMaxWidth: setSize('maxWidth'),
- setMaxHeight: setSize('maxHeight')
- };
-});
-define('tinymce.media.core.HtmlToData', [
- 'global!tinymce.util.Tools',
- 'global!tinymce.html.SaxParser',
- 'global!tinymce.html.Schema',
- 'global!tinymce.dom.DOMUtils.DOM',
- 'tinymce.media.core.VideoScript',
- 'tinymce.media.core.Size'
-], function (Tools, SaxParser, Schema, DOM, VideoScript, Size) {
- var getEphoxEmbedIri = function (elm) {
- return DOM.getAttrib(elm, 'data-ephox-embed-iri');
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isEphoxEmbed = function (html) {
- var fragment = DOM.createFragment(html);
- return getEphoxEmbedIri(fragment.firstChild) !== '';
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.html.Writer',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.html.Writer');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var htmlToDataSax = function (prefixes, html) {
- var data = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- new SaxParser({
- validate: false,
- allow_conditional_comments: true,
- special: 'script,noscript',
- start: function (name, attrs) {
- if (!data.source1 && name === "param") {
- data.source1 = attrs.map.movie;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.html.SaxParser',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.html.SaxParser');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name === "iframe" || name === "object" || name === "embed" || name === "video" || name === "audio") {
- if (!data.type) {
- data.type = name;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- data = Tools.extend(attrs.map, data);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.html.Schema',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.html.Schema');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name === "script") {
- var videoScript = VideoScript.getVideoScriptMatch(prefixes, attrs.map.src);
- if (!videoScript) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Sanitize.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- data = {
- type: "script",
- source1: attrs.map.src,
- width: videoScript.width,
- height: videoScript.height
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.media.core.Sanitize',
+ [
+ 'tinymce.core.util.Tools',
+ 'tinymce.core.html.Writer',
+ 'tinymce.core.html.SaxParser',
+ 'tinymce.core.html.Schema'
+ ],
+ function (Tools, Writer, SaxParser, Schema) {
+ var sanitize = function (editor, html) {
+ if (editor.settings.media_filter_html === false) {
+ return html;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name === "source") {
- if (!data.source1) {
- data.source1 = attrs.map.src;
- } else if (!data.source2) {
- data.source2 = attrs.map.src;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var writer = new Writer();
+ var blocked;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name === "img" && !data.poster) {
- data.poster = attrs.map.src;
- }
- }
- }).parse(html);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ new SaxParser({
+ validate: false,
+ allow_conditional_comments: false,
+ special: 'script,noscript',
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- data.source1 = data.source1 || data.src || data.data;
- data.source2 = data.source2 || '';
- data.poster = data.poster || '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ comment: function (text) {
+ writer.comment(text);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return data;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ cdata: function (text) {
+ writer.cdata(text);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var ephoxEmbedHtmlToData = function (html) {
- var fragment = DOM.createFragment(html);
- var div = fragment.firstChild;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ text: function (text, raw) {
+ writer.text(text, raw);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- type: 'ephox-embed-iri',
- source1: getEphoxEmbedIri(div),
- source2: '',
- poster: '',
- width: Size.getMaxWidth(div),
- height: Size.getMaxHeight(div)
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ start: function (name, attrs, empty) {
+ blocked = true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var htmlToData = function (prefixes, html) {
- return isEphoxEmbed(html) ? ephoxEmbedHtmlToData(html) : htmlToDataSax(prefixes, html);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name === 'script' || name === 'noscript') {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- htmlToData: htmlToData
- };
-});
-defineGlobal("global!tinymce.html.Writer", tinymce.html.Writer);
-define('tinymce.media.core.UpdateHtml', [
- 'global!tinymce.html.Writer',
- 'global!tinymce.html.SaxParser',
- 'global!tinymce.html.Schema',
- 'global!tinymce.dom.DOMUtils.DOM',
- 'tinymce.media.core.Size'
-], function (Writer, SaxParser, Schema, DOM, Size) {
- var setAttributes = function (attrs, updatedAttrs) {
- var name;
- var i;
- var value;
- var attr;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (var i = 0; i < attrs.length; i++) {
+ if (attrs[i].name.indexOf('on') === 0) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (name in updatedAttrs) {
- value = "" + updatedAttrs[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (attrs[i].name === 'style') {
+ attrs[i].value = editor.dom.serializeStyle(editor.dom.parseStyle(attrs[i].value), name);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (attrs.map[name]) {
- i = attrs.length;
- while (i--) {
- attr = attrs[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ writer.start(name, attrs, empty);
+ blocked = false;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (attr.name === name) {
- if (value) {
- attrs.map[name] = value;
- attr.value = value;
- } else {
- delete attrs.map[name];
- attrs.splice(i, 1);
- }
- }
- }
- } else if (value) {
- attrs.push({
- name: name,
- value: value
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ end: function (name) {
+ if (blocked) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- attrs.map[name] = value;
- }
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ writer.end(name);
+ }
+ }, new Schema({})).parse(html);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var normalizeHtml = function (html) {
- var writer = new Writer();
- var parser = new SaxParser(writer);
- parser.parse(html);
- return writer.getContent();
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return writer.getContent();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var updateHtmlSax = function (html, data, updateAll) {
- var writer = new Writer();
- var sourceCount = 0;
- var hasImage;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ sanitize: sanitize
+ };
+ }
+);
+/**
+ * VideoScript.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- new SaxParser({
- validate: false,
- allow_conditional_comments: true,
- special: 'script,noscript',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.media.core.VideoScript',
+ [
+ ],
+ function () {
+ var getVideoScriptMatch = function (prefixes, src) {
+ // var prefixes = editor.settings.media_scripts;
+ if (prefixes) {
+ for (var i = 0; i < prefixes.length; i++) {
+ if (src.indexOf(prefixes[i].filter) !== -1) {
+ return prefixes[i];
+ }
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- comment: function (text) {
- writer.comment(text);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ getVideoScriptMatch: getVideoScriptMatch
+ };
+ }
+);
+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- cdata: function (text) {
- writer.cdata(text);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.Env',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.Env');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- text: function (text, raw) {
- writer.text(text, raw);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Nodes.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- start: function (name, attrs, empty) {
- switch (name) {
- case "video":
- case "object":
- case "embed":
- case "img":
- case "iframe":
- setAttributes(attrs, {
- width: data.width,
- height: data.height
- });
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.media.core.Nodes',
+ [
+ 'tinymce.plugins.media.core.Sanitize',
+ 'tinymce.plugins.media.core.VideoScript',
+ 'tinymce.core.html.Node',
+ 'tinymce.core.Env'
+ ],
+ function (Sanitize, VideoScript, Node, Env) {
+ var createPlaceholderNode = function (editor, node) {
+ var placeHolder;
+ var name = node.name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (updateAll) {
- switch (name) {
- case "video":
- setAttributes(attrs, {
- poster: data.poster,
- src: ""
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ placeHolder = new Node('img', 1);
+ placeHolder.shortEnded = true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (data.source2) {
- setAttributes(attrs, {
- src: ""
- });
- }
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ retainAttributesAndInnerHtml(editor, node, placeHolder);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case "iframe":
- setAttributes(attrs, {
- src: data.source1
- });
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ placeHolder.attr({
+ width: node.attr('width') || "300",
+ height: node.attr('height') || (name === "audio" ? "30" : "150"),
+ style: node.attr('style'),
+ src: Env.transparentSrc,
+ "data-mce-object": name,
+ "class": "mce-object mce-object-" + name
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case "source":
- sourceCount++;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return placeHolder;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (sourceCount <= 2) {
- setAttributes(attrs, {
- src: data["source" + sourceCount],
- type: data["source" + sourceCount + "mime"]
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createPreviewIframeNode = function (editor, node) {
+ var previewWrapper;
+ var previewNode;
+ var shimNode;
+ var name = node.name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!data["source" + sourceCount]) {
- return;
- }
- }
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ previewWrapper = new Node('span', 1);
+ previewWrapper.attr({
+ contentEditable: 'false',
+ style: node.attr('style'),
+ "data-mce-object": name,
+ "class": "mce-preview-object mce-object-" + name
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case "img":
- if (!data.poster) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ retainAttributesAndInnerHtml(editor, node, previewWrapper);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- hasImage = true;
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ previewNode = new Node(name, 1);
+ previewNode.attr({
+ src: node.attr('src'),
+ allowfullscreen: node.attr('allowfullscreen'),
+ width: node.attr('width') || "300",
+ height: node.attr('height') || (name === "audio" ? "30" : "150"),
+ frameborder: '0'
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- writer.start(name, attrs, empty);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ shimNode = new Node('span', 1);
+ shimNode.attr('class', 'mce-shim');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- end: function (name) {
- if (name === "video" && updateAll) {
- for (var index = 1; index <= 2; index++) {
- if (data["source" + index]) {
- var attrs = [];
- attrs.map = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ previewWrapper.append(previewNode);
+ previewWrapper.append(shimNode);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (sourceCount < index) {
- setAttributes(attrs, {
- src: data["source" + index],
- type: data["source" + index + "mime"]
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return previewWrapper;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- writer.start("source", attrs, true);
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var retainAttributesAndInnerHtml = function (editor, sourceNode, targetNode) {
+ var attrName;
+ var attrValue;
+ var attribs;
+ var ai;
+ var innerHtml;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (data.poster && name === "object" && updateAll && !hasImage) {
- var imgAttrs = [];
- imgAttrs.map = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Prefix all attributes except width, height and style since we
+ // will add these to the placeholder
+ attribs = sourceNode.attributes;
+ ai = attribs.length;
+ while (ai--) {
+ attrName = attribs[ai].name;
+ attrValue = attribs[ai].value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- setAttributes(imgAttrs, {
- src: data.poster,
- width: data.width,
- height: data.height
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (attrName !== "width" && attrName !== "height" && attrName !== "style") {
+ if (attrName === "data" || attrName === "src") {
+ attrValue = editor.convertURL(attrValue, attrName);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- writer.start("img", imgAttrs, true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ targetNode.attr('data-mce-p-' + attrName, attrValue);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- writer.end(name);
- }
- }, new Schema({})).parse(html);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Place the inner HTML contents inside an escaped attribute
+ // This enables us to copy/paste the fake object
+ innerHtml = sourceNode.firstChild && sourceNode.firstChild.value;
+ if (innerHtml) {
+ targetNode.attr("data-mce-html", escape(Sanitize.sanitize(editor, innerHtml)));
+ targetNode.firstChild = null;
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return writer.getContent();
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isWithinEphoxEmbed = function (node) {
+ while ((node = node.parent)) {
+ if (node.attr('data-ephox-embed-iri')) {
+ return true;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isEphoxEmbed = function (html) {
- var fragment = DOM.createFragment(html);
- return DOM.getAttrib(fragment.firstChild, 'data-ephox-embed-iri') !== '';
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var updateEphoxEmbed = function (html, data) {
- var fragment = DOM.createFragment(html);
- var div = fragment.firstChild;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var placeHolderConverter = function (editor) {
+ return function (nodes) {
+ var i = nodes.length;
+ var node;
+ var videoScript;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Size.setMaxWidth(div, data.width);
- Size.setMaxHeight(div, data.height);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i];
+ if (!node.parent) {
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return normalizeHtml(div.outerHTML);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.parent.attr('data-mce-object')) {
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var updateHtml = function (html, data, updateAll) {
- return isEphoxEmbed(html) ? updateEphoxEmbed(html, data) : updateHtmlSax(html, data, updateAll);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.name === 'script') {
+ videoScript = VideoScript.getVideoScriptMatch(editor.settings.media_scripts, node.attr('src'));
+ if (!videoScript) {
+ continue;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- updateHtml: updateHtml
- };
-});
-define('tinymce.media.core.Mime', [
-], function () {
- var guess = function (url) {
- var mimes = {
- 'mp3': 'audio/mpeg',
- 'wav': 'audio/wav',
- 'mp4': 'video/mp4',
- 'webm': 'video/webm',
- 'ogg': 'video/ogg',
- 'swf': 'application/x-shockwave-flash'
- };
- var fileEnd = url.toLowerCase().split('.').pop();
- var mime = mimes[fileEnd];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (videoScript) {
+ if (videoScript.width) {
+ node.attr('width', videoScript.width.toString());
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return mime ? mime : '';
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (videoScript.height) {
+ node.attr('height', videoScript.height.toString());
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- guess: guess
- };
-});
-define('tinymce.media.core.UrlPatterns', [
-], function () {
- var urlPatterns = [
- {
- regex: /youtu\.be\/([\w\-.]+)/,
- type: 'iframe', w: 560, h: 314,
- url: '//www.youtube.com/embed/$1',
- allowFullscreen: true
- },
- {
- regex: /youtube\.com(.+)v=([^&]+)/,
- type: 'iframe', w: 560, h: 314,
- url: '//www.youtube.com/embed/$2',
- allowFullscreen: true
- },
- {
- regex: /youtube.com\/embed\/([a-z0-9\-_]+(?:\?.+)?)/i,
- type: 'iframe', w: 560, h: 314,
- url: '//www.youtube.com/embed/$1',
- allowFullscreen: true
- },
- {
- regex: /vimeo\.com\/([0-9]+)/,
- type: 'iframe', w: 425, h: 350,
- url: '//player.vimeo.com/video/$1?title=0&byline=0&portrait=0&color=8dc7dc',
- allowfullscreen: true
- },
- {
- regex: /vimeo\.com\/(.*)\/([0-9]+)/,
- type: "iframe", w: 425, h: 350,
- url: "//player.vimeo.com/video/$2?title=0&byline=0",
- allowfullscreen: true
- },
- {
- regex: /maps\.google\.([a-z]{2,3})\/maps\/(.+)msid=(.+)/,
- type: 'iframe', w: 425, h: 350,
- url: '//maps.google.com/maps/ms?msid=$2&output=embed"',
- allowFullscreen: false
- },
- {
- regex: /dailymotion\.com\/video\/([^_]+)/,
- type: 'iframe', w: 480, h: 270,
- url: '//www.dailymotion.com/embed/video/$1',
- allowFullscreen: true
- }
- ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.name === 'iframe' && editor.settings.media_live_embeds !== false && Env.ceFalse) {
+ if (!isWithinEphoxEmbed(node)) {
+ node.replace(createPreviewIframeNode(editor, node));
+ }
+ } else {
+ if (!isWithinEphoxEmbed(node)) {
+ node.replace(createPlaceholderNode(editor, node));
+ }
+ }
+ }
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- urlPatterns: urlPatterns
- };
-});
-define('tinymce.media.core.DataToHtml', [
- 'tinymce.media.core.Mime',
- 'tinymce.media.core.HtmlToData',
- 'tinymce.media.core.UrlPatterns',
- 'tinymce.media.core.VideoScript',
- 'tinymce.media.core.UpdateHtml',
- 'global!tinymce.util.Tools'
-], function (Mime, HtmlToData, UrlPatterns, VideoScript, UpdateHtml, Tools) {
- var dataToHtml = function (editor, dataIn) {
- var html = '';
- var data = Tools.extend({}, dataIn);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ createPreviewIframeNode: createPreviewIframeNode,
+ createPlaceholderNode: createPlaceholderNode,
+ placeHolderConverter: placeHolderConverter
+ };
+ }
+);
+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!data.source1) {
- Tools.extend(data, HtmlToData.htmlToData(editor.settings.media_scripts, data.embed));
- if (!data.source1) {
- return '';
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.DOMUtils',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.dom.DOMUtils');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!data.source2) {
- data.source2 = '';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Size.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!data.poster) {
- data.poster = '';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.media.core.Size',
+ [
+ ],
+ function () {
+ var trimPx = function (value) {
+ return value.replace(/px$/, '');
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- data.source1 = editor.convertURL(data.source1, "source");
- data.source2 = editor.convertURL(data.source2, "source");
- data.source1mime = Mime.guess(data.source1);
- data.source2mime = Mime.guess(data.source2);
- data.poster = editor.convertURL(data.poster, "poster");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var addPx = function (value) {
+ return /^[0-9.]+$/.test(value) ? (value + 'px') : value;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(UrlPatterns.urlPatterns, function (pattern) {
- var i;
- var url;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getSize = function (name) {
+ return function (elm) {
+ return elm ? trimPx(elm.style[name]) : '';
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var match = pattern.regex.exec(data.source1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var setSize = function (name) {
+ return function (elm, value) {
+ if (elm) {
+ elm.style[name] = addPx(value);
+ }
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (match) {
- url = pattern.url;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ getMaxWidth: getSize('maxWidth'),
+ getMaxHeight: getSize('maxHeight'),
+ setMaxWidth: setSize('maxWidth'),
+ setMaxHeight: setSize('maxHeight')
+ };
+ }
+);
+/**
+ * UpdateHtml.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0; match[i]; i++) {
- /*jshint loopfunc:true*/
- /*eslint no-loop-func:0 */
- url = url.replace('$' + i, function () {
- return match[i];
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.media.core.UpdateHtml',
+ [
+ 'tinymce.core.html.Writer',
+ 'tinymce.core.html.SaxParser',
+ 'tinymce.core.html.Schema',
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.plugins.media.core.Size'
+ ],
+ function (Writer, SaxParser, Schema, DOMUtils, Size) {
+ var DOM = DOMUtils.DOM;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- data.source1 = url;
- data.type = pattern.type;
- data.allowFullscreen = pattern.allowFullscreen;
- data.width = data.width || pattern.w;
- data.height = data.height || pattern.h;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var setAttributes = function (attrs, updatedAttrs) {
+ var name;
+ var i;
+ var value;
+ var attr;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (data.embed) {
- html = UpdateHtml.updateHtml(data.embed, data, true);
- } else {
- var videoScript = VideoScript.getVideoScriptMatch(editor.settings.media_scripts, data.source1);
- if (videoScript) {
- data.type = 'script';
- data.width = videoScript.width;
- data.height = videoScript.height;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (name in updatedAttrs) {
+ value = "" + updatedAttrs[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- data.width = data.width || 300;
- data.height = data.height || 150;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (attrs.map[name]) {
+ i = attrs.length;
+ while (i--) {
+ attr = attrs[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(data, function (value, key) {
- data[key] = editor.dom.encode(value);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (attr.name === name) {
+ if (value) {
+ attrs.map[name] = value;
+ attr.value = value;
+ } else {
+ delete attrs.map[name];
+ attrs.splice(i, 1);
+ }
+ }
+ }
+ } else if (value) {
+ attrs.push({
+ name: name,
+ value: value
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (data.type === "iframe") {
- var allowFullscreen = data.allowFullscreen ? ' allowFullscreen="1"' : '';
- html +=
- '<iframe src="' + data.source1 +
- '" width="' + data.width +
- '" height="' + data.height +
- '"' + allowFullscreen + '></iframe>';
- } else if (data.source1mime === "application/x-shockwave-flash") {
- html +=
- '<object data="' + data.source1 +
- '" width="' + data.width +
- '" height="' + data.height +
- '" type="application/x-shockwave-flash">';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ attrs.map[name] = value;
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (data.poster) {
- html += '<img src="' + data.poster + '" width="' + data.width + '" height="' + data.height + '" />';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var normalizeHtml = function (html) {
+ var writer = new Writer();
+ var parser = new SaxParser(writer);
+ parser.parse(html);
+ return writer.getContent();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- html += '</object>';
- } else if (data.source1mime.indexOf('audio') !== -1) {
- if (editor.settings.audio_template_callback) {
- html = editor.settings.audio_template_callback(data);
- } else {
- html += (
- '<audio controls="controls" src="' + data.source1 + '">' +
- (
- data.source2 ?
- '\n<source src="' + data.source2 + '"' +
- (data.source2mime ? ' type="' + data.source2mime + '"' : '') +
- ' />\n' : '') +
- '</audio>'
- );
- }
- } else if (data.type === "script") {
- html += '<script src="' + data.source1 + '"></script>';
- } else {
- if (editor.settings.video_template_callback) {
- html = editor.settings.video_template_callback(data);
- } else {
- html = (
- '<video width="' + data.width +
- '" height="' + data.height + '"' +
- (data.poster ? ' poster="' + data.poster + '"' : '') + ' controls="controls">\n' +
- '<source src="' + data.source1 + '"' +
- (data.source1mime ? ' type="' + data.source1mime + '"' : '') + ' />\n' +
- (data.source2 ? '<source src="' + data.source2 + '"' +
- (data.source2mime ? ' type="' + data.source2mime + '"' : '') + ' />\n' : '') +
- '</video>'
- );
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var updateHtmlSax = function (html, data, updateAll) {
+ var writer = new Writer();
+ var sourceCount = 0;
+ var hasImage;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return html;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ new SaxParser({
+ validate: false,
+ allow_conditional_comments: true,
+ special: 'script,noscript',
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- dataToHtml: dataToHtml
- };
-});
-defineGlobal("global!tinymce.util.Promise", tinymce.util.Promise);
-define('tinymce.media.core.Service', [
- 'tinymce.media.core.DataToHtml',
- 'global!tinymce.util.Promise'
-], function (DataToHtml, Promise) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ comment: function (text) {
+ writer.comment(text);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var embedPromise = function (data, dataToHtml, handler) {
- var cache = {};
- return new Promise(function (res, rej) {
- var wrappedResolve = function (response) {
- if (response.html) {
- cache[data.source1] = response;
- }
- return res({
- url: data.source1,
- html: response.html ? response.html : dataToHtml(data)
- });
- };
- if (cache[data.source1]) {
- wrappedResolve(cache[data.source1]);
- } else {
- handler({url: data.source1}, wrappedResolve, rej);
- }
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ cdata: function (text) {
+ writer.cdata(text);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var defaultPromise = function (data, dataToHtml) {
- return new Promise(function (res) {
- res({html: dataToHtml(data), url: data.source1});
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ text: function (text, raw) {
+ writer.text(text, raw);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var loadedData = function (editor) {
- return function (data) {
- return DataToHtml.dataToHtml(editor, data);
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ start: function (name, attrs, empty) {
+ switch (name) {
+ case "video":
+ case "object":
+ case "embed":
+ case "img":
+ case "iframe":
+ if (data.height !== undefined && data.width !== undefined) {
+ setAttributes(attrs, {
+ width: data.width,
+ height: data.height
+ });
+ }
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getEmbedHtml = function (editor, data) {
- var embedHandler = editor.settings.media_url_resolver;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (updateAll) {
+ switch (name) {
+ case "video":
+ setAttributes(attrs, {
+ poster: data.poster,
+ src: ""
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return embedHandler ? embedPromise(data, loadedData(editor), embedHandler) : defaultPromise(data, loadedData(editor));
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (data.source2) {
+ setAttributes(attrs, {
+ src: ""
+ });
+ }
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- getEmbedHtml: getEmbedHtml
- };
-});
-defineGlobal("global!tinymce.Env", tinymce.Env);
-define('tinymce.media.ui.SizeManager', [
-], function () {
- var doSyncSize = function (widthCtrl, heightCtrl) {
- widthCtrl.state.set('oldVal', widthCtrl.value());
- heightCtrl.state.set('oldVal', heightCtrl.value());
- };
- var doSizeControls = function (win, f) {
- var widthCtrl = win.find('#width')[0];
- var heightCtrl = win.find('#height')[0];
- var constrained = win.find('#constrain')[0];
- if (widthCtrl && heightCtrl && constrained) {
- f(widthCtrl, heightCtrl, constrained.checked());
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case "iframe":
+ setAttributes(attrs, {
+ src: data.source1
+ });
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var doUpdateSize = function (widthCtrl, heightCtrl, isContrained) {
- var oldWidth = widthCtrl.state.get('oldVal');
- var oldHeight = heightCtrl.state.get('oldVal');
- var newWidth = widthCtrl.value();
- var newHeight = heightCtrl.value();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case "source":
+ sourceCount++;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isContrained && oldWidth && oldHeight && newWidth && newHeight) {
- if (newWidth !== oldWidth) {
- newHeight = Math.round((newWidth / oldWidth) * newHeight);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (sourceCount <= 2) {
+ setAttributes(attrs, {
+ src: data["source" + sourceCount],
+ type: data["source" + sourceCount + "mime"]
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isNaN(newHeight)) {
- heightCtrl.value(newHeight);
- }
- } else {
- newWidth = Math.round((newHeight / oldHeight) * newWidth);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!data["source" + sourceCount]) {
+ return;
+ }
+ }
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isNaN(newWidth)) {
- widthCtrl.value(newWidth);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case "img":
+ if (!data.poster) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- doSyncSize(widthCtrl, heightCtrl);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ hasImage = true;
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var syncSize = function (win) {
- doSizeControls(win, doSyncSize);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ writer.start(name, attrs, empty);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var updateSize = function (win) {
- doSizeControls(win, doUpdateSize);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ end: function (name) {
+ if (name === "video" && updateAll) {
+ for (var index = 1; index <= 2; index++) {
+ if (data["source" + index]) {
+ var attrs = [];
+ attrs.map = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var createUi = function (onChange) {
- var recalcSize = function () {
- onChange(function (win) {
- updateSize(win);
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (sourceCount < index) {
+ setAttributes(attrs, {
+ src: data["source" + index],
+ type: data["source" + index + "mime"]
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- type: 'container',
- label: 'Dimensions',
- layout: 'flex',
- align: 'center',
- spacing: 5,
- items: [
- {
- name: 'width', type: 'textbox', maxLength: 5, size: 5,
- onchange: recalcSize, ariaLabel: 'Width'
- },
- {type: 'label', text: 'x'},
- {
- name: 'height', type: 'textbox', maxLength: 5, size: 5,
- onchange: recalcSize, ariaLabel: 'Height'
- },
- {name: 'constrain', type: 'checkbox', checked: true, text: 'Constrain proportions'}
- ]
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ writer.start("source", attrs, true);
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- createUi: createUi,
- syncSize: syncSize,
- updateSize: updateSize
- };
-});
-define('tinymce.media.ui.Dialog', [
- 'global!tinymce.util.Delay',
- 'tinymce.media.core.HtmlToData',
- 'tinymce.media.core.UpdateHtml',
- 'tinymce.media.core.Service',
- 'tinymce.media.core.Size',
- 'global!tinymce.util.Tools',
- 'global!tinymce.Env',
- 'tinymce.media.ui.SizeManager'
-], function (Delay, HtmlToData, UpdateHtml, Service, Size, Tools, Env, SizeManager) {
- var embedChange = (Env.ie && Env.ie <= 8) ? 'onChange' : 'onInput';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (data.poster && name === "object" && updateAll && !hasImage) {
+ var imgAttrs = [];
+ imgAttrs.map = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var handleError = function (editor) {
- return function (error) {
- var errorMessage = error && error.msg ?
- 'Media embed handler error: ' + error.msg :
- 'Media embed handler threw unknown error.';
- editor.notificationManager.open({type: 'error', text: errorMessage});
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ setAttributes(imgAttrs, {
+ src: data.poster,
+ width: data.width,
+ height: data.height
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getData = function (editor) {
- var element = editor.selection.getNode();
- var dataEmbed = element.getAttribute('data-ephox-embed-iri');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ writer.start("img", imgAttrs, true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (dataEmbed) {
- return {
- source1: dataEmbed,
- 'data-ephox-embed-iri': dataEmbed,
- width: Size.getMaxWidth(element),
- height: Size.getMaxHeight(element)
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ writer.end(name);
+ }
+ }, new Schema({})).parse(html);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return element.getAttribute('data-mce-object') ?
- HtmlToData.htmlToData(editor.settings.media_scripts, editor.serializer.serialize(element, {selection: true})) :
- {};
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return writer.getContent();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getSource = function (editor) {
- var elm = editor.selection.getNode();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isEphoxEmbed = function (html) {
+ var fragment = DOM.createFragment(html);
+ return DOM.getAttrib(fragment.firstChild, 'data-ephox-embed-iri') !== '';
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elm.getAttribute('data-mce-object') || elm.getAttribute('data-ephox-embed-iri')) {
- return editor.selection.getContent();
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var updateEphoxEmbed = function (html, data) {
+ var fragment = DOM.createFragment(html);
+ var div = fragment.firstChild;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var addEmbedHtml = function (win, editor) {
- return function (response) {
- var html = response.html;
- var embed = win.find('#embed')[0];
- var data = Tools.extend(HtmlToData.htmlToData(editor.settings.media_scripts, html), {source1: response.url});
- win.fromJSON(data);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Size.setMaxWidth(div, data.width);
+ Size.setMaxHeight(div, data.height);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (embed) {
- embed.value(html);
- SizeManager.updateSize(win);
- }
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return normalizeHtml(div.outerHTML);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var selectPlaceholder = function (editor, beforeObjects) {
- var i;
- var y;
- var afterObjects = editor.dom.select('img[data-mce-object]');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var updateHtml = function (html, data, updateAll) {
+ return isEphoxEmbed(html) ? updateEphoxEmbed(html, data) : updateHtmlSax(html, data, updateAll);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Find new image placeholder so we can select it
- for (i = 0; i < beforeObjects.length; i++) {
- for (y = afterObjects.length - 1; y >= 0; y--) {
- if (beforeObjects[i] === afterObjects[y]) {
- afterObjects.splice(y, 1);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ updateHtml: updateHtml
+ };
+ }
+);
+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.selection.select(afterObjects[0]);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.Delay',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.util.Delay');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var handleInsert = function (editor, html) {
- var beforeObjects = editor.dom.select('img[data-mce-object]');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * HtmlToData.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.insertContent(html);
- selectPlaceholder(editor, beforeObjects);
- editor.nodeChanged();
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.media.core.HtmlToData',
+ [
+ 'tinymce.core.util.Tools',
+ 'tinymce.core.html.SaxParser',
+ 'tinymce.core.html.Schema',
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.plugins.media.core.VideoScript',
+ 'tinymce.plugins.media.core.Size'
+ ],
+ function (Tools, SaxParser, Schema, DOMUtils, VideoScript, Size) {
+ var DOM = DOMUtils.DOM;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var submitForm = function (win, editor) {
- var data = win.toJSON();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getEphoxEmbedIri = function (elm) {
+ return DOM.getAttrib(elm, 'data-ephox-embed-iri');
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- data.embed = UpdateHtml.updateHtml(data.embed, data);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isEphoxEmbed = function (html) {
+ var fragment = DOM.createFragment(html);
+ return getEphoxEmbedIri(fragment.firstChild) !== '';
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (data.embed) {
- handleInsert(editor, data.embed);
- } else {
- Service.getEmbedHtml(editor, data)
- .then(function (response) {
- handleInsert(editor, response.html);
- })["catch"](handleError(editor));
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var htmlToDataSax = function (prefixes, html) {
+ var data = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var populateMeta = function (win, meta) {
- Tools.each(meta, function (value, key) {
- win.find('#' + key).value(value);
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ new SaxParser({
+ validate: false,
+ allow_conditional_comments: true,
+ special: 'script,noscript',
+ start: function (name, attrs) {
+ if (!data.source1 && name === "param") {
+ data.source1 = attrs.map.movie;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var showDialog = function (editor) {
- var win;
- var data;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name === "iframe" || name === "object" || name === "embed" || name === "video" || name === "audio") {
+ if (!data.type) {
+ data.type = name;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var generalFormItems = [
- {
- name: 'source1',
- type: 'filepicker',
- filetype: 'media',
- size: 40,
- autofocus: true,
- label: 'Source',
- onpaste: function () {
- setTimeout(function () {
- Service.getEmbedHtml(editor, win.toJSON())
- .then(
- addEmbedHtml(win, editor)
- )["catch"](handleError(editor));
- }, 1);
- },
- onchange: function (e) {
- Service.getEmbedHtml(editor, win.toJSON())
- .then(
- addEmbedHtml(win, editor)
- )["catch"](handleError(editor));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ data = Tools.extend(attrs.map, data);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- populateMeta(win, e.meta);
- },
- onbeforecall: function (e) {
- e.meta = win.toJSON();
- }
- }
- ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name === "script") {
+ var videoScript = VideoScript.getVideoScriptMatch(prefixes, attrs.map.src);
+ if (!videoScript) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var advancedFormItems = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ data = {
+ type: "script",
+ source1: attrs.map.src,
+ width: videoScript.width,
+ height: videoScript.height
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var reserialise = function (update) {
- update(win);
- data = win.toJSON();
- win.find('#embed').value(UpdateHtml.updateHtml(data.embed, data));
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name === "source") {
+ if (!data.source1) {
+ data.source1 = attrs.map.src;
+ } else if (!data.source2) {
+ data.source2 = attrs.map.src;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.settings.media_alt_source !== false) {
- advancedFormItems.push({name: 'source2', type: 'filepicker', filetype: 'media', size: 40, label: 'Alternative source'});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name === "img" && !data.poster) {
+ data.poster = attrs.map.src;
+ }
+ }
+ }).parse(html);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.settings.media_poster !== false) {
- advancedFormItems.push({name: 'poster', type: 'filepicker', filetype: 'image', size: 40, label: 'Poster'});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ data.source1 = data.source1 || data.src || data.data;
+ data.source2 = data.source2 || '';
+ data.poster = data.poster || '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.settings.media_dimensions !== false) {
- var control = SizeManager.createUi(reserialise);
- generalFormItems.push(control);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return data;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- data = getData(editor);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var ephoxEmbedHtmlToData = function (html) {
+ var fragment = DOM.createFragment(html);
+ var div = fragment.firstChild;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var embedTextBox = {
- id: 'mcemediasource',
- type: 'textbox',
- flex: 1,
- name: 'embed',
- value: getSource(editor),
- multiline: true,
- rows: 5,
- label: 'Source'
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ type: 'ephox-embed-iri',
+ source1: getEphoxEmbedIri(div),
+ source2: '',
+ poster: '',
+ width: Size.getMaxWidth(div),
+ height: Size.getMaxHeight(div)
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var updateValueOnChange = function () {
- data = Tools.extend({}, HtmlToData.htmlToData(editor.settings.media_scripts, this.value()));
- this.parent().parent().fromJSON(data);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var htmlToData = function (prefixes, html) {
+ return isEphoxEmbed(html) ? ephoxEmbedHtmlToData(html) : htmlToDataSax(prefixes, html);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- embedTextBox[embedChange] = updateValueOnChange;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ htmlToData: htmlToData
+ };
+ }
+);
+/**
+ * Mime.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- win = editor.windowManager.open({
- title: 'Insert/edit media',
- data: data,
- bodyType: 'tabpanel',
- body: [
- {
- title: 'General',
- type: "form",
- items: generalFormItems
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.media.core.Mime',
+ [
+ ],
+ function () {
+ var guess = function (url) {
+ var mimes = {
+ 'mp3': 'audio/mpeg',
+ 'wav': 'audio/wav',
+ 'mp4': 'video/mp4',
+ 'webm': 'video/webm',
+ 'ogg': 'video/ogg',
+ 'swf': 'application/x-shockwave-flash'
+ };
+ var fileEnd = url.toLowerCase().split('.').pop();
+ var mime = mimes[fileEnd];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- {
- title: 'Embed',
- type: "container",
- layout: 'flex',
- direction: 'column',
- align: 'stretch',
- padding: 10,
- spacing: 10,
- items: [
- {
- type: 'label',
- text: 'Paste your embed code below:',
- forId: 'mcemediasource'
- },
- embedTextBox
- ]
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return mime ? mime : '';
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- {
- title: 'Advanced',
- type: "form",
- items: advancedFormItems
- }
- ],
- onSubmit: function () {
- SizeManager.updateSize(win);
- submitForm(win, editor);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ guess: guess
+ };
+ }
+);
+/**
+ * UrlPatterns.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- SizeManager.syncSize(win);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.media.core.UrlPatterns',
+ [
+ ],
+ function () {
+ var urlPatterns = [
+ {
+ regex: /youtu\.be\/([\w\-.]+)/,
+ type: 'iframe', w: 560, h: 314,
+ url: '//www.youtube.com/embed/$1',
+ allowFullscreen: true
+ },
+ {
+ regex: /youtube\.com(.+)v=([^&]+)/,
+ type: 'iframe', w: 560, h: 314,
+ url: '//www.youtube.com/embed/$2',
+ allowFullscreen: true
+ },
+ {
+ regex: /youtube.com\/embed\/([a-z0-9\-_]+(?:\?.+)?)/i,
+ type: 'iframe', w: 560, h: 314,
+ url: '//www.youtube.com/embed/$1',
+ allowFullscreen: true
+ },
+ {
+ regex: /vimeo\.com\/([0-9]+)/,
+ type: 'iframe', w: 425, h: 350,
+ url: '//player.vimeo.com/video/$1?title=0&byline=0&portrait=0&color=8dc7dc',
+ allowfullscreen: true
+ },
+ {
+ regex: /vimeo\.com\/(.*)\/([0-9]+)/,
+ type: "iframe", w: 425, h: 350,
+ url: "//player.vimeo.com/video/$2?title=0&byline=0",
+ allowfullscreen: true
+ },
+ {
+ regex: /maps\.google\.([a-z]{2,3})\/maps\/(.+)msid=(.+)/,
+ type: 'iframe', w: 425, h: 350,
+ url: '//maps.google.com/maps/ms?msid=$2&output=embed"',
+ allowFullscreen: false
+ },
+ {
+ regex: /dailymotion\.com\/video\/([^_]+)/,
+ type: 'iframe', w: 480, h: 270,
+ url: '//www.dailymotion.com/embed/video/$1',
+ allowFullscreen: true
+ }
+ ];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- showDialog: showDialog
- };
-});
-define('tinymce.media.core.Sanitize', [
- 'global!tinymce.util.Tools',
- 'global!tinymce.html.Writer',
- 'global!tinymce.html.SaxParser',
- 'global!tinymce.html.Schema'
-], function (Tools, Writer, SaxParser, Schema) {
- var sanitize = function (editor, html) {
- if (editor.settings.media_filter_html === false) {
- return html;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ urlPatterns: urlPatterns
+ };
+ }
+);
+/**
+ * DataToHtml.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var writer = new Writer();
- var blocked;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.media.core.DataToHtml',
+ [
+ 'tinymce.plugins.media.core.Mime',
+ 'tinymce.plugins.media.core.HtmlToData',
+ 'tinymce.plugins.media.core.UrlPatterns',
+ 'tinymce.plugins.media.core.VideoScript',
+ 'tinymce.plugins.media.core.UpdateHtml',
+ 'tinymce.core.util.Tools'
+ ],
+ function (Mime, HtmlToData, UrlPatterns, VideoScript, UpdateHtml, Tools) {
+ var dataToHtml = function (editor, dataIn) {
+ var html = '';
+ var data = Tools.extend({}, dataIn);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- new SaxParser({
- validate: false,
- allow_conditional_comments: false,
- special: 'script,noscript',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!data.source1) {
+ Tools.extend(data, HtmlToData.htmlToData(editor.settings.media_scripts, data.embed));
+ if (!data.source1) {
+ return '';
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- comment: function (text) {
- writer.comment(text);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!data.source2) {
+ data.source2 = '';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- cdata: function (text) {
- writer.cdata(text);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!data.poster) {
+ data.poster = '';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- text: function (text, raw) {
- writer.text(text, raw);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ data.source1 = editor.convertURL(data.source1, "source");
+ data.source2 = editor.convertURL(data.source2, "source");
+ data.source1mime = Mime.guess(data.source1);
+ data.source2mime = Mime.guess(data.source2);
+ data.poster = editor.convertURL(data.poster, "poster");
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- start: function (name, attrs, empty) {
- blocked = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(UrlPatterns.urlPatterns, function (pattern) {
+ var i;
+ var url;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name === 'script' || name === 'noscript') {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var match = pattern.regex.exec(data.source1);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var i = 0; i < attrs.length; i++) {
- if (attrs[i].name.indexOf('on') === 0) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (match) {
+ url = pattern.url;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (attrs[i].name === 'style') {
- attrs[i].value = editor.dom.serializeStyle(editor.dom.parseStyle(attrs[i].value), name);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0; match[i]; i++) {
+ /*jshint loopfunc:true*/
+ /*eslint no-loop-func:0 */
+ url = url.replace('$' + i, function () {
+ return match[i];
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- writer.start(name, attrs, empty);
- blocked = false;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ data.source1 = url;
+ data.type = pattern.type;
+ data.allowFullscreen = pattern.allowFullscreen;
+ data.width = data.width || pattern.w;
+ data.height = data.height || pattern.h;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- end: function (name) {
- if (blocked) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (data.embed) {
+ html = UpdateHtml.updateHtml(data.embed, data, true);
+ } else {
+ var videoScript = VideoScript.getVideoScriptMatch(editor.settings.media_scripts, data.source1);
+ if (videoScript) {
+ data.type = 'script';
+ data.width = videoScript.width;
+ data.height = videoScript.height;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- writer.end(name);
- }
- }, new Schema({})).parse(html);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ data.width = data.width || 300;
+ data.height = data.height || 150;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return writer.getContent();
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(data, function (value, key) {
+ data[key] = editor.dom.encode(value);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- sanitize: sanitize
- };
-});
-defineGlobal("global!tinymce.html.Node", tinymce.html.Node);
-define('tinymce.media.core.Nodes', [
- 'tinymce.media.core.Sanitize',
- 'tinymce.media.core.VideoScript',
- 'global!tinymce.html.Node',
- 'global!tinymce.Env'
-], function (Sanitize, VideoScript, Node, Env) {
- var createPlaceholderNode = function (editor, node) {
- var placeHolder;
- var name = node.name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (data.type === "iframe") {
+ var allowFullscreen = data.allowFullscreen ? ' allowFullscreen="1"' : '';
+ html +=
+ '<iframe src="' + data.source1 +
+ '" width="' + data.width +
+ '" height="' + data.height +
+ '"' + allowFullscreen + '></iframe>';
+ } else if (data.source1mime === "application/x-shockwave-flash") {
+ html +=
+ '<object data="' + data.source1 +
+ '" width="' + data.width +
+ '" height="' + data.height +
+ '" type="application/x-shockwave-flash">';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- placeHolder = new Node('img', 1);
- placeHolder.shortEnded = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (data.poster) {
+ html += '<img src="' + data.poster + '" width="' + data.width + '" height="' + data.height + '" />';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- retainAttributesAndInnerHtml(editor, node, placeHolder);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ html += '</object>';
+ } else if (data.source1mime.indexOf('audio') !== -1) {
+ if (editor.settings.audio_template_callback) {
+ html = editor.settings.audio_template_callback(data);
+ } else {
+ html += (
+ '<audio controls="controls" src="' + data.source1 + '">' +
+ (
+ data.source2 ?
+ '\n<source src="' + data.source2 + '"' +
+ (data.source2mime ? ' type="' + data.source2mime + '"' : '') +
+ ' />\n' : '') +
+ '</audio>'
+ );
+ }
+ } else if (data.type === "script") {
+ html += '<script src="' + data.source1 + '"></script>';
+ } else {
+ if (editor.settings.video_template_callback) {
+ html = editor.settings.video_template_callback(data);
+ } else {
+ html = (
+ '<video width="' + data.width +
+ '" height="' + data.height + '"' +
+ (data.poster ? ' poster="' + data.poster + '"' : '') + ' controls="controls">\n' +
+ '<source src="' + data.source1 + '"' +
+ (data.source1mime ? ' type="' + data.source1mime + '"' : '') + ' />\n' +
+ (data.source2 ? '<source src="' + data.source2 + '"' +
+ (data.source2mime ? ' type="' + data.source2mime + '"' : '') + ' />\n' : '') +
+ '</video>'
+ );
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- placeHolder.attr({
- width: node.attr('width') || "300",
- height: node.attr('height') || (name === "audio" ? "30" : "150"),
- style: node.attr('style'),
- src: Env.transparentSrc,
- "data-mce-object": name,
- "class": "mce-object mce-object-" + name
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return html;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return placeHolder;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ dataToHtml: dataToHtml
+ };
+ }
+);
+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var createPreviewIframeNode = function (editor, node) {
- var previewWrapper;
- var previewNode;
- var shimNode;
- var name = node.name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.Promise',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.util.Promise');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- previewWrapper = new Node('span', 1);
- previewWrapper.attr({
- contentEditable: 'false',
- style: node.attr('style'),
- "data-mce-object": name,
- "class": "mce-preview-object mce-object-" + name
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Service.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- retainAttributesAndInnerHtml(editor, node, previewWrapper);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.media.core.Service',
+ [
+ 'tinymce.plugins.media.core.DataToHtml',
+ 'tinymce.core.util.Promise'
+ ],
+ function (DataToHtml, Promise) {
+ var embedPromise = function (data, dataToHtml, handler) {
+ var cache = {};
+ return new Promise(function (res, rej) {
+ var wrappedResolve = function (response) {
+ if (response.html) {
+ cache[data.source1] = response;
+ }
+ return res({
+ url: data.source1,
+ html: response.html ? response.html : dataToHtml(data)
+ });
+ };
+ if (cache[data.source1]) {
+ wrappedResolve(cache[data.source1]);
+ } else {
+ handler({ url: data.source1 }, wrappedResolve, rej);
+ }
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- previewNode = new Node(name, 1);
- previewNode.attr({
- src: node.attr('src'),
- allowfullscreen: node.attr('allowfullscreen'),
- width: node.attr('width') || "300",
- height: node.attr('height') || (name === "audio" ? "30" : "150"),
- frameborder: '0'
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var defaultPromise = function (data, dataToHtml) {
+ return new Promise(function (res) {
+ res({ html: dataToHtml(data), url: data.source1 });
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- shimNode = new Node('span', 1);
- shimNode.attr('class', 'mce-shim');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var loadedData = function (editor) {
+ return function (data) {
+ return DataToHtml.dataToHtml(editor, data);
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- previewWrapper.append(previewNode);
- previewWrapper.append(shimNode);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getEmbedHtml = function (editor, data) {
+ var embedHandler = editor.settings.media_url_resolver;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return previewWrapper;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return embedHandler ? embedPromise(data, loadedData(editor), embedHandler) : defaultPromise(data, loadedData(editor));
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var retainAttributesAndInnerHtml = function (editor, sourceNode, targetNode) {
- var attrName;
- var attrValue;
- var attribs;
- var ai;
- var innerHtml;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ getEmbedHtml: getEmbedHtml
+ };
+ }
+);
+/**
+ * SizeManager.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Prefix all attributes except width, height and style since we
- // will add these to the placeholder
- attribs = sourceNode.attributes;
- ai = attribs.length;
- while (ai--) {
- attrName = attribs[ai].name;
- attrValue = attribs[ai].value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.media.ui.SizeManager',
+ [
+ ],
+ function () {
+ var doSyncSize = function (widthCtrl, heightCtrl) {
+ widthCtrl.state.set('oldVal', widthCtrl.value());
+ heightCtrl.state.set('oldVal', heightCtrl.value());
+ };
+ var doSizeControls = function (win, f) {
+ var widthCtrl = win.find('#width')[0];
+ var heightCtrl = win.find('#height')[0];
+ var constrained = win.find('#constrain')[0];
+ if (widthCtrl && heightCtrl && constrained) {
+ f(widthCtrl, heightCtrl, constrained.checked());
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (attrName !== "width" && attrName !== "height" && attrName !== "style") {
- if (attrName === "data" || attrName === "src") {
- attrValue = editor.convertURL(attrValue, attrName);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var doUpdateSize = function (widthCtrl, heightCtrl, isContrained) {
+ var oldWidth = widthCtrl.state.get('oldVal');
+ var oldHeight = heightCtrl.state.get('oldVal');
+ var newWidth = widthCtrl.value();
+ var newHeight = heightCtrl.value();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- targetNode.attr('data-mce-p-' + attrName, attrValue);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isContrained && oldWidth && oldHeight && newWidth && newHeight) {
+ if (newWidth !== oldWidth) {
+ newHeight = Math.round((newWidth / oldWidth) * newHeight);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Place the inner HTML contents inside an escaped attribute
- // This enables us to copy/paste the fake object
- innerHtml = sourceNode.firstChild && sourceNode.firstChild.value;
- if (innerHtml) {
- targetNode.attr("data-mce-html", escape(Sanitize.sanitize(editor, innerHtml)));
- targetNode.firstChild = null;
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isNaN(newHeight)) {
+ heightCtrl.value(newHeight);
+ }
+ } else {
+ newWidth = Math.round((newHeight / oldHeight) * newWidth);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isWithinEphoxEmbed = function (node) {
- while ((node = node.parent)) {
- if (node.attr('data-ephox-embed-iri')) {
- return true;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isNaN(newWidth)) {
+ widthCtrl.value(newWidth);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ doSyncSize(widthCtrl, heightCtrl);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var placeHolderConverter = function (editor) {
- return function (nodes) {
- var i = nodes.length;
- var node;
- var videoScript;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var syncSize = function (win) {
+ doSizeControls(win, doSyncSize);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i];
- if (!node.parent) {
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var updateSize = function (win) {
+ doSizeControls(win, doUpdateSize);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.parent.attr('data-mce-object')) {
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createUi = function (onChange) {
+ var recalcSize = function () {
+ onChange(function (win) {
+ updateSize(win);
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.name === 'script') {
- videoScript = VideoScript.getVideoScriptMatch(editor.settings.media_scripts, node.attr('src'));
- if (!videoScript) {
- continue;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ type: 'container',
+ label: 'Dimensions',
+ layout: 'flex',
+ align: 'center',
+ spacing: 5,
+ items: [
+ {
+ name: 'width', type: 'textbox', maxLength: 5, size: 5,
+ onchange: recalcSize, ariaLabel: 'Width'
+ },
+ { type: 'label', text: 'x' },
+ {
+ name: 'height', type: 'textbox', maxLength: 5, size: 5,
+ onchange: recalcSize, ariaLabel: 'Height'
+ },
+ { name: 'constrain', type: 'checkbox', checked: true, text: 'Constrain proportions' }
+ ]
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (videoScript) {
- if (videoScript.width) {
- node.attr('width', videoScript.width.toString());
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ createUi: createUi,
+ syncSize: syncSize,
+ updateSize: updateSize
+ };
+ }
+);
+/**
+ * Dialog.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (videoScript.height) {
- node.attr('height', videoScript.height.toString());
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.media.ui.Dialog',
+ [
+ 'tinymce.core.util.Delay',
+ 'tinymce.plugins.media.core.HtmlToData',
+ 'tinymce.plugins.media.core.UpdateHtml',
+ 'tinymce.plugins.media.core.Service',
+ 'tinymce.plugins.media.core.Size',
+ 'tinymce.core.util.Tools',
+ 'tinymce.core.Env',
+ 'tinymce.plugins.media.ui.SizeManager'
+ ],
+ function (Delay, HtmlToData, UpdateHtml, Service, Size, Tools, Env, SizeManager) {
+ var embedChange = (Env.ie && Env.ie <= 8) ? 'onChange' : 'onInput';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.name === 'iframe' && editor.settings.media_live_embeds !== false && Env.ceFalse) {
- if (!isWithinEphoxEmbed(node)) {
- node.replace(createPreviewIframeNode(editor, node));
- }
- } else {
- if (!isWithinEphoxEmbed(node)) {
- node.replace(createPlaceholderNode(editor, node));
- }
- }
- }
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var handleError = function (editor) {
+ return function (error) {
+ var errorMessage = error && error.msg ?
+ 'Media embed handler error: ' + error.msg :
+ 'Media embed handler threw unknown error.';
+ editor.notificationManager.open({ type: 'error', text: errorMessage });
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- createPreviewIframeNode: createPreviewIframeNode,
- createPlaceholderNode: createPlaceholderNode,
- placeHolderConverter: placeHolderConverter
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getData = function (editor) {
+ var element = editor.selection.getNode();
+ var dataEmbed = element.getAttribute('data-ephox-embed-iri');
+
+ if (dataEmbed) {
+ return {
+ source1: dataEmbed,
+ 'data-ephox-embed-iri': dataEmbed,
+ width: Size.getMaxWidth(element),
+ height: Size.getMaxHeight(element)
+ };
+ }
+
+ return element.getAttribute('data-mce-object') ?
+ HtmlToData.htmlToData(editor.settings.media_scripts, editor.serializer.serialize(element, { selection: true })) :
+ {};
+ };
+
+ var getSource = function (editor) {
+ var elm = editor.selection.getNode();
+
+ if (elm.getAttribute('data-mce-object') || elm.getAttribute('data-ephox-embed-iri')) {
+ return editor.selection.getContent();
+ }
+ };
+
+ var addEmbedHtml = function (win, editor) {
+ return function (response) {
+ var html = response.html;
+ var embed = win.find('#embed')[0];
+ var data = Tools.extend(HtmlToData.htmlToData(editor.settings.media_scripts, html), { source1: response.url });
+ win.fromJSON(data);
+
+ if (embed) {
+ embed.value(html);
+ SizeManager.updateSize(win);
+ }
+ };
+ };
+
+ var selectPlaceholder = function (editor, beforeObjects) {
+ var i;
+ var y;
+ var afterObjects = editor.dom.select('img[data-mce-object]');
+
+ // Find new image placeholder so we can select it
+ for (i = 0; i < beforeObjects.length; i++) {
+ for (y = afterObjects.length - 1; y >= 0; y--) {
+ if (beforeObjects[i] === afterObjects[y]) {
+ afterObjects.splice(y, 1);
+ }
+ }
+ }
+
+ editor.selection.select(afterObjects[0]);
+ };
+
+ var handleInsert = function (editor, html) {
+ var beforeObjects = editor.dom.select('img[data-mce-object]');
+
+ editor.insertContent(html);
+ selectPlaceholder(editor, beforeObjects);
+ editor.nodeChanged();
+ };
+
+ var submitForm = function (win, editor) {
+ var data = win.toJSON();
+
+ data.embed = UpdateHtml.updateHtml(data.embed, data);
+
+ if (data.embed) {
+ handleInsert(editor, data.embed);
+ } else {
+ Service.getEmbedHtml(editor, data)
+ .then(function (response) {
+ handleInsert(editor, response.html);
+ })["catch"](handleError(editor));
+ }
+ };
+
+ var populateMeta = function (win, meta) {
+ Tools.each(meta, function (value, key) {
+ win.find('#' + key).value(value);
+ });
+ };
+
+ var showDialog = function (editor) {
+ var win;
+ var data;
+
+ var generalFormItems = [
+ {
+ name: 'source1',
+ type: 'filepicker',
+ filetype: 'media',
+ size: 40,
+ autofocus: true,
+ label: 'Source',
+ onpaste: function () {
+ setTimeout(function () {
+ Service.getEmbedHtml(editor, win.toJSON())
+ .then(
+ addEmbedHtml(win, editor)
+ )["catch"](handleError(editor));
+ }, 1);
+ },
+ onchange: function (e) {
+ Service.getEmbedHtml(editor, win.toJSON())
+ .then(
+ addEmbedHtml(win, editor)
+ )["catch"](handleError(editor));
+
+ populateMeta(win, e.meta);
+ },
+ onbeforecall: function (e) {
+ e.meta = win.toJSON();
+ }
+ }
+ ];
+
+ var advancedFormItems = [];
+
+ var reserialise = function (update) {
+ update(win);
+ data = win.toJSON();
+ win.find('#embed').value(UpdateHtml.updateHtml(data.embed, data));
+ };
+
+ if (editor.settings.media_alt_source !== false) {
+ advancedFormItems.push({ name: 'source2', type: 'filepicker', filetype: 'media', size: 40, label: 'Alternative source' });
+ }
+
+ if (editor.settings.media_poster !== false) {
+ advancedFormItems.push({ name: 'poster', type: 'filepicker', filetype: 'image', size: 40, label: 'Poster' });
+ }
+
+ if (editor.settings.media_dimensions !== false) {
+ var control = SizeManager.createUi(reserialise);
+ generalFormItems.push(control);
+ }
+
+ data = getData(editor);
+
+ var embedTextBox = {
+ id: 'mcemediasource',
+ type: 'textbox',
+ flex: 1,
+ name: 'embed',
+ value: getSource(editor),
+ multiline: true,
+ rows: 5,
+ label: 'Source'
+ };
+
+ var updateValueOnChange = function () {
+ data = Tools.extend({}, HtmlToData.htmlToData(editor.settings.media_scripts, this.value()));
+ this.parent().parent().fromJSON(data);
+ };
+
+ embedTextBox[embedChange] = updateValueOnChange;
+
+ win = editor.windowManager.open({
+ title: 'Insert/edit media',
+ data: data,
+ bodyType: 'tabpanel',
+ body: [
+ {
+ title: 'General',
+ type: "form",
+ items: generalFormItems
+ },
+
+ {
+ title: 'Embed',
+ type: "container",
+ layout: 'flex',
+ direction: 'column',
+ align: 'stretch',
+ padding: 10,
+ spacing: 10,
+ items: [
+ {
+ type: 'label',
+ text: 'Paste your embed code below:',
+ forId: 'mcemediasource'
+ },
+ embedTextBox
+ ]
+ },
+
+ {
+ title: 'Advanced',
+ type: "form",
+ items: advancedFormItems
+ }
+ ],
+ onSubmit: function () {
+ SizeManager.updateSize(win);
+ submitForm(win, editor);
+ }
+ });
+
+ SizeManager.syncSize(win);
+ };
+
+ return {
+ showDialog: showDialog
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * plugin.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Plugin.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/*jshint maxlen:255 */
-/*eslint max-len:0 */
-/*global tinymce:true */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.media.Plugin',
+ [
+ 'tinymce.core.html.Node',
+ 'tinymce.core.PluginManager',
+ 'tinymce.core.util.Tools',
+ 'tinymce.plugins.media.core.Nodes',
+ 'tinymce.plugins.media.core.Sanitize',
+ 'tinymce.plugins.media.core.UpdateHtml',
+ 'tinymce.plugins.media.ui.Dialog'
+ ],
+ function (Node, PluginManager, Tools, Nodes, Sanitize, UpdateHtml, Dialog) {
+ var Plugin = function (editor) {
+ editor.on('ResolveName', function (e) {
+ var name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce.media.Plugin', [
- 'global!tinymce.PluginManager',
- 'tinymce.media.ui.Dialog',
- 'tinymce.media.core.Sanitize',
- 'tinymce.media.core.UpdateHtml',
- 'tinymce.media.core.Nodes'
-], function (PluginManager, Dialog, Sanitize, UpdateHtml, Nodes) {
- var Plugin = function (editor) {
- editor.on('ResolveName', function (e) {
- var name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.target.nodeType === 1 && (name = e.target.getAttribute("data-mce-object"))) {
+ e.name = name;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.target.nodeType === 1 && (name = e.target.getAttribute("data-mce-object"))) {
- e.name = name;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('preInit', function () {
+ // Make sure that any messy HTML is retained inside these
+ var specialElements = editor.schema.getSpecialElements();
+ Tools.each('video audio iframe object'.split(' '), function (name) {
+ specialElements[name] = new RegExp('<\/' + name + '[^>]*>', 'gi');
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('preInit', function () {
- // Make sure that any messy HTML is retained inside these
- var specialElements = editor.schema.getSpecialElements();
- tinymce.each('video audio iframe object'.split(' '), function (name) {
- specialElements[name] = new RegExp('<\/' + name + '[^>]*>', 'gi');
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Allow elements
+ //editor.schema.addValidElements(
+ // 'object[id|style|width|height|classid|codebase|*],embed[id|style|width|height|type|src|*],video[*],audio[*]'
+ //);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Allow elements
- //editor.schema.addValidElements('object[id|style|width|height|classid|codebase|*],embed[id|style|width|height|type|src|*],video[*],audio[*]');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set allowFullscreen attribs as boolean
+ var boolAttrs = editor.schema.getBoolAttrs();
+ Tools.each('webkitallowfullscreen mozallowfullscreen allowfullscreen'.split(' '), function (name) {
+ boolAttrs[name] = {};
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set allowFullscreen attribs as boolean
- var boolAttrs = editor.schema.getBoolAttrs();
- tinymce.each('webkitallowfullscreen mozallowfullscreen allowfullscreen'.split(' '), function (name) {
- boolAttrs[name] = {};
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Converts iframe, video etc into placeholder images
+ editor.parser.addNodeFilter('iframe,video,audio,object,embed,script',
+ Nodes.placeHolderConverter(editor));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Converts iframe, video etc into placeholder images
- editor.parser.addNodeFilter('iframe,video,audio,object,embed,script',
- Nodes.placeHolderConverter(editor));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Replaces placeholder images with real elements for video, object, iframe etc
+ editor.serializer.addAttributeFilter('data-mce-object', function (nodes, name) {
+ var i = nodes.length;
+ var node;
+ var realElm;
+ var ai;
+ var attribs;
+ var innerHtml;
+ var innerNode;
+ var realElmName;
+ var className;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Replaces placeholder images with real elements for video, object, iframe etc
- editor.serializer.addAttributeFilter('data-mce-object', function (nodes, name) {
- var i = nodes.length;
- var node;
- var realElm;
- var ai;
- var attribs;
- var innerHtml;
- var innerNode;
- var realElmName;
- var className;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i];
+ if (!node.parent) {
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i];
- if (!node.parent) {
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ realElmName = node.attr(name);
+ realElm = new Node(realElmName, 1);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- realElmName = node.attr(name);
- realElm = new tinymce.html.Node(realElmName, 1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add width/height to everything but audio
+ if (realElmName !== "audio" && realElmName !== "script") {
+ className = node.attr('class');
+ if (className && className.indexOf('mce-preview-object') !== -1) {
+ realElm.attr({
+ width: node.firstChild.attr('width'),
+ height: node.firstChild.attr('height')
+ });
+ } else {
+ realElm.attr({
+ width: node.attr('width'),
+ height: node.attr('height')
+ });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add width/height to everything but audio
- if (realElmName !== "audio" && realElmName !== "script") {
- className = node.attr('class');
- if (className && className.indexOf('mce-preview-object') !== -1) {
- realElm.attr({
- width: node.firstChild.attr('width'),
- height: node.firstChild.attr('height')
- });
- } else {
- realElm.attr({
- width: node.attr('width'),
- height: node.attr('height')
- });
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ realElm.attr({
+ style: node.attr('style')
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- realElm.attr({
- style: node.attr('style')
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Unprefix all placeholder attributes
+ attribs = node.attributes;
+ ai = attribs.length;
+ while (ai--) {
+ var attrName = attribs[ai].name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Unprefix all placeholder attributes
- attribs = node.attributes;
- ai = attribs.length;
- while (ai--) {
- var attrName = attribs[ai].name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (attrName.indexOf('data-mce-p-') === 0) {
+ realElm.attr(attrName.substr(11), attribs[ai].value);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (attrName.indexOf('data-mce-p-') === 0) {
- realElm.attr(attrName.substr(11), attribs[ai].value);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (realElmName === "script") {
+ realElm.attr('type', 'text/javascript');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (realElmName === "script") {
- realElm.attr('type', 'text/javascript');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Inject innerhtml
+ innerHtml = node.attr('data-mce-html');
+ if (innerHtml) {
+ innerNode = new Node('#text', 3);
+ innerNode.raw = true;
+ innerNode.value = Sanitize.sanitize(editor, unescape(innerHtml));
+ realElm.append(innerNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Inject innerhtml
- innerHtml = node.attr('data-mce-html');
- if (innerHtml) {
- innerNode = new tinymce.html.Node('#text', 3);
- innerNode.raw = true;
- innerNode.value = Sanitize.sanitize(editor, unescape(innerHtml));
- realElm.append(innerNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node.replace(realElm);
+ }
+ });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node.replace(realElm);
- }
- });
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('click keyup', function () {
+ var selectedNode = editor.selection.getNode();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('click keyup', function () {
- var selectedNode = editor.selection.getNode();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (selectedNode && editor.dom.hasClass(selectedNode, 'mce-preview-object')) {
+ if (editor.dom.getAttrib(selectedNode, 'data-mce-selected')) {
+ selectedNode.setAttribute('data-mce-selected', '2');
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (selectedNode && editor.dom.hasClass(selectedNode, 'mce-preview-object')) {
- if (editor.dom.getAttrib(selectedNode, 'data-mce-selected')) {
- selectedNode.setAttribute('data-mce-selected', '2');
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('ObjectSelected', function (e) {
+ var objectType = e.target.getAttribute('data-mce-object');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('ObjectSelected', function (e) {
- var objectType = e.target.getAttribute('data-mce-object');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (objectType === "audio" || objectType === "script") {
+ e.preventDefault();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (objectType === "audio" || objectType === "script") {
- e.preventDefault();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('objectResized', function (e) {
+ var target = e.target;
+ var html;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('objectResized', function (e) {
- var target = e.target;
- var html;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (target.getAttribute('data-mce-object')) {
+ html = target.getAttribute('data-mce-html');
+ if (html) {
+ html = unescape(html);
+ target.setAttribute('data-mce-html', escape(
+ UpdateHtml.updateHtml(html, {
+ width: e.width,
+ height: e.height
+ })
+ ));
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (target.getAttribute('data-mce-object')) {
- html = target.getAttribute('data-mce-html');
- if (html) {
- html = unescape(html);
- target.setAttribute('data-mce-html', escape(
- UpdateHtml.updateHtml(html, {
- width: e.width,
- height: e.height
- })
- ));
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.showDialog = function () {
+ Dialog.showDialog(editor);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.showDialog = function () {
- Dialog.showDialog(editor);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addButton('media', {
+ tooltip: 'Insert/edit media',
+ onclick: this.showDialog,
+ stateSelector: ['img[data-mce-object]', 'span[data-mce-object]', 'div[data-ephox-embed-iri]']
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addButton('media', {
- tooltip: 'Insert/edit media',
- onclick: this.showDialog,
- stateSelector: ['img[data-mce-object]', 'span[data-mce-object]', 'div[data-ephox-embed-iri]']
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addMenuItem('media', {
+ icon: 'media',
+ text: 'Media',
+ onclick: this.showDialog,
+ context: 'insert',
+ prependToContext: true
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addMenuItem('media', {
- icon: 'media',
- text: 'Media',
- onclick: this.showDialog,
- context: 'insert',
- prependToContext: true
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('setContent', function () {
+ // TODO: This shouldn't be needed there should be a way to mark bogus
+ // elements so they are never removed except external save
+ editor.$('span.mce-preview-object').each(function (index, elm) {
+ var $elm = editor.$(elm);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('setContent', function () {
- // TODO: This shouldn't be needed there should be a way to mark bogus
- // elements so they are never removed except external save
- editor.$('span.mce-preview-object').each(function (index, elm) {
- var $elm = editor.$(elm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ($elm.find('span.mce-shim', elm).length === 0) {
+ $elm.append('<span class="mce-shim"></span>');
+ }
+ });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ($elm.find('span.mce-shim', elm).length === 0) {
- $elm.append('<span class="mce-shim"></span>');
- }
- });
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addCommand('mceMedia', this.showDialog);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addCommand('mceMedia', this.showDialog);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ PluginManager.add('media', Plugin);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- PluginManager.add('media', Plugin);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function () { };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function () {};
-});
</del><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-dem('tinymce.media.Plugin')();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+dem('tinymce.plugins.media.Plugin')();
</ins><span class="cx" style="display: block; padding: 0 10px"> })();
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginsmediapluginminjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/media/plugin.min.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/media/plugin.min.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/media/plugin.min.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1 +1 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-!function(){var e={},t=function(t){for(var n=e[t],i=n.deps,o=n.defn,a=i.length,s=new Array(a),l=0;l<a;++l)s[l]=r(i[l]);var u=o.apply(null,s);if(void 0===u)throw"module ["+t+"] returned undefined";n.instance=u},n=function(t,n,r){if("string"!=typeof t)throw"module id must be a string";if(void 0===n)throw"no dependencies for "+t;if(void 0===r)throw"no definition function for "+t;e[t]={deps:n,defn:r,instance:void 0}},r=function(n){var r=e[n];if(void 0===r)throw"module ["+n+"] was undefined";return void 0===r.instance&&t(n),r.instance},i=function(e,t){for(var n=e.length,i=new Array(n),o=0;o<n;++o)i.push(r(e[o]));t.apply(null,t)},o={};o.bolt={module:{api:{define:n,require:i,demand:r}}};var a=n,s=function(e,t){a(e,[],function(){return t})};s("1",tinymce.PluginManager),s("6",tinymce.
util.Delay),s("e",tinymce.util.Tools),s("9",tinymce.html.SaxParser),s("a",tinymce.html.Schema),s("b",tinymce.dom.DOMUtils.DOM),a("h",[],function(){var e=function(e,t){if(e)for(var n=0;n<e.length;n++)if(t.indexOf(e[n].filter)!==-1)return e[n]};return{getVideoScriptMatch:e}}),a("c",[],function(){var e=function(e){return e.replace(/px$/,"")},t=function(e){return/^[0-9.]+$/.test(e)?e+"px":e},n=function(t){return function(n){return n?e(n.style[t]):""}},r=function(e){return function(n,r){n&&(n.style[e]=t(r))}};return{getMaxWidth:n("maxWidth"),getMaxHeight:n("maxHeight"),setMaxWidth:r("maxWidth"),setMaxHeight:r("maxHeight")}}),a("7",["e","9","a","b","h","c"],function(e,t,n,r,i,o){var a=function(e){return r.getAttrib(e,"data-ephox-embed-iri")},s=function(e){var t=r.createFr
agment(e);return""!==a(t.firstChild)},l=function(n,r){var o={};return new t({validate:!1,allow_conditional_comments:!0,special:"script,noscript",start:function(t,r){if(o.source1||"param"!==t||(o.source1=r.map.movie),"iframe"!==t&&"object"!==t&&"embed"!==t&&"video"!==t&&"audio"!==t||(o.type||(o.type=t),o=e.extend(r.map,o)),"script"===t){var a=i.getVideoScriptMatch(n,r.map.src);if(!a)return;o={type:"script",source1:r.map.src,width:a.width,height:a.height}}"source"===t&&(o.source1?o.source2||(o.source2=r.map.src):o.source1=r.map.src),"img"!==t||o.poster||(o.poster=r.map.src)}}).parse(r),o.source1=o.source1||o.src||o.data,o.source2=o.source2||"",o.poster=o.poster||"",o},u=function(e){var t=r.createFragment(e),n=t.firstChild;return{type:"ephox-embed-iri",source1:a(n),source2:"",poster:"
",width:o.getMaxWidth(n),height:o.getMaxHeight(n)}},c=function(e,t){return s(t)?u(t):l(e,t)};return{htmlToData:c}}),s("8",tinymce.html.Writer),a("4",["8","9","a","b","c"],function(e,t,n,r,i){var o=function(e,t){var n,r,i,o;for(n in t)if(i=""+t[n],e.map[n])for(r=e.length;r--;)o=e[r],o.name===n&&(i?(e.map[n]=i,o.value=i):(delete e.map[n],e.splice(r,1)));else i&&(e.push({name:n,value:i}),e.map[n]=i)},a=function(n){var r=new e,i=new t(r);return i.parse(n),r.getContent()},s=function(r,i,a){var s,l=new e,u=0;return new t({validate:!1,allow_conditional_comments:!0,special:"script,noscript",comment:function(e){l.comment(e)},cdata:function(e){l.cdata(e)},text:function(e,t){l.text(e,t)},start:function(e,t,n){switch(e){case"video":case"object":case"embed":case"img":case"iframe":o(t,{width:i.width,height:i.height})}if(a)switch(e){case&q
uot;video":o(t,{poster:i.poster,src:""}),i.source2&&o(t,{src:""});break;case"iframe":o(t,{src:i.source1});break;case"source":if(u++,u<=2&&(o(t,{src:i["source"+u],type:i["source"+u+"mime"]}),!i["source"+u]))return;break;case"img":if(!i.poster)return;s=!0}l.start(e,t,n)},end:function(e){if("video"===e&&a)for(var t=1;t<=2;t++)if(i["source"+t]){var n=[];n.map={},u<t&&(o(n,{src:i["source"+t],type:i["source"+t+"mime"]}),l.start("source",n,!0))}if(i.poster&&"object"===e&&a&&!s){var r=[];r.map={},o(r,{src:i.poster,width:i.width,height:i.height}),l.start("img",r,!0)}l.end(e)}},new n({})).parse(r),l.getContent()},l=function(e){var t=r.createFragment(e);return""!==r.getAttrib(t.firstChild,"data-ephox-embed-iri")},u=function(e,t){var n=r.c
reateFragment(e),o=n.firstChild;return i.setMaxWidth(o,t.width),i.setMaxHeight(o,t.height),a(o.outerHTML)},c=function(e,t,n){return l(e)?u(e,t):s(e,t,n)};return{updateHtml:c}}),a("l",[],function(){var e=function(e){var t={mp3:"audio/mpeg",wav:"audio/wav",mp4:"video/mp4",webm:"video/webm",ogg:"video/ogg",swf:"application/x-shockwave-flash"},n=e.toLowerCase().split(".").pop(),r=t[n];return r?r:""};return{guess:e}}),a("m",[],function(){var e=[{regex:/youtu\.be\/([\w\-.]+)/,type:"iframe",w:560,h:314,url:"//www.youtube.com/embed/$1",allowFullscreen:!0},{regex:/youtube\.com(.+)v=([^&]+)/,type:"iframe",w:560,h:314,url:"//www.youtube.com/embed/$2",allowFullscreen:!0},{regex:/youtube.com\/embed\/([a-z0-9\-_]+(?:\?.+)?)/i,type:"iframe",w:560,h:314,url:"//www.youtube.com/embed/$1",allowFullscreen:!0},{regex:/vimeo\.com\/([0-9]+)/,ty
pe:"iframe",w:425,h:350,url:"//player.vimeo.com/video/$1?title=0&byline=0&portrait=0&color=8dc7dc",allowfullscreen:!0},{regex:/vimeo\.com\/(.*)\/([0-9]+)/,type:"iframe",w:425,h:350,url:"//player.vimeo.com/video/$2?title=0&byline=0",allowfullscreen:!0},{regex:/maps\.google\.([a-z]{2,3})\/maps\/(.+)msid=(.+)/,type:"iframe",w:425,h:350,url:'//maps.google.com/maps/ms?msid=$2&output=embed"',allowFullscreen:!1},{regex:/dailymotion\.com\/video\/([^_]+)/,type:"iframe",w:480,h:270,url:"//www.dailymotion.com/embed/video/$1",allowFullscreen:!0}];return{urlPatterns:e}}),a("j",["l","7","m","h","4","e"],function(e,t,n,r,i,o){var a=function(a,s){var l="",u=o.extend({},s);if(!u.source1&&(o.extend(u,t.htmlToData(a.settings.media_scripts,u.embed)),!u.source1))return"";if(u.source2||(u.source2=""),
u.poster||(u.poster=""),u.source1=a.convertURL(u.source1,"source"),u.source2=a.convertURL(u.source2,"source"),u.source1mime=e.guess(u.source1),u.source2mime=e.guess(u.source2),u.poster=a.convertURL(u.poster,"poster"),o.each(n.urlPatterns,function(e){var t,n,r=e.regex.exec(u.source1);if(r){for(n=e.url,t=0;r[t];t++)n=n.replace("$"+t,function(){return r[t]});u.source1=n,u.type=e.type,u.allowFullscreen=e.allowFullscreen,u.width=u.width||e.w,u.height=u.height||e.h}}),u.embed)l=i.updateHtml(u.embed,u,!0);else{var c=r.getVideoScriptMatch(a.settings.media_scripts,u.source1);if(c&&(u.type="script",u.width=c.width,u.height=c.height),u.width=u.width||300,u.height=u.height||150,o.each(u,function(e,t){u[t]=a.dom.encode(e)}),"iframe"===u.type){var d=u.allowFullscreen?' allowFullscreen="1"':"";l+='<iframe src="'+u.source1+'" width="'+u.width+'" height="'+u.height+'"'+d
+"></iframe>"}else"application/x-shockwave-flash"===u.source1mime?(l+='<object data="'+u.source1+'" width="'+u.width+'" height="'+u.height+'" type="application/x-shockwave-flash">',u.poster&&(l+='<img src="'+u.poster+'" width="'+u.width+'" height="'+u.height+'" />'),l+="</object>"):u.source1mime.indexOf("audio")!==-1?a.settings.audio_template_callback?l=a.settings.audio_template_callback(u):l+='<audio controls="controls" src="'+u.source1+'">'+(u.source2?'\n<source src="'+u.source2+'"'+(u.source2mime?' type="'+u.source2mime+'"':"")+" />\n":"")+"</audio>":"script"===u.type?l+='<script src="'+u.source1+'"></script>':l=a.settings.video_template_callback?a.settings.video_template_callback(u):'<video width="'+u
.width+'" height="'+u.height+'"'+(u.poster?' poster="'+u.poster+'"':"")+' controls="controls">\n<source src="'+u.source1+'"'+(u.source1mime?' type="'+u.source1mime+'"':"")+" />\n"+(u.source2?'<source src="'+u.source2+'"'+(u.source2mime?' type="'+u.source2mime+'"':"")+" />\n":"")+"</video>"}return l};return{dataToHtml:a}}),s("k",tinymce.util.Promise),a("d",["j","k"],function(e,t){var n=function(e,n,r){var i={};return new t(function(t,o){var a=function(r){return r.html&&(i[e.source1]=r),t({url:e.source1,html:r.html?r.html:n(e)})};i[e.source1]?a(i[e.source1]):r({url:e.source1},a,o)})},r=function(e,n){return new t(function(t){t({html:n(e),url:e.source1})})},i=function(t){return function(n){return e.dataToHtml(t,n)}},o=function(e,t){var o=e.settings.media_url_resolver;return o?
n(t,i(e),o):r(t,i(e))};return{getEmbedHtml:o}}),s("f",tinymce.Env),a("g",[],function(){var e=function(e,t){e.state.set("oldVal",e.value()),t.state.set("oldVal",t.value())},t=function(e,t){var n=e.find("#width")[0],r=e.find("#height")[0],i=e.find("#constrain")[0];n&&r&&i&&t(n,r,i.checked())},n=function(t,n,r){var i=t.state.get("oldVal"),o=n.state.get("oldVal"),a=t.value(),s=n.value();r&&i&&o&&a&&s&&(a!==i?(s=Math.round(a/i*s),isNaN(s)||n.value(s)):(a=Math.round(s/o*a),isNaN(a)||t.value(a))),e(t,n)},r=function(n){t(n,e)},i=function(e){t(e,n)},o=function(e){var t=function(){e(function(e){i(e)})};return{type:"container",label:"Dimensions",layout:"flex",align:"center",spacing:5,items:[{name:"width",type:"textbox",maxLength:5,size:5,onchange:t,ariaLabel:"Width"},{type:
"label",text:"x"},{name:"height",type:"textbox",maxLength:5,size:5,onchange:t,ariaLabel:"Height"},{name:"constrain",type:"checkbox",checked:!0,text:"Constrain proportions"}]}};return{createUi:o,syncSize:r,updateSize:i}}),a("2",["6","7","4","d","c","e","f","g"],function(e,t,n,r,i,o,a,s){var l=a.ie&&a.ie<=8?"onChange":"onInput",u=function(e){return function(t){var n=t&&t.msg?"Media embed handler error: "+t.msg:"Media embed handler threw unknown error.";e.notificationManager.open({type:"error",text:n})}},c=function(e){var n=e.selection.getNode(),r=n.getAttribute("data-ephox-embed-iri");return r?{source1:r,"data-ephox-embed-iri":r,width:i.getMaxWidth(n),height:i.getMaxHeight(n)}:n.getAttribute("data-mce-object")?t.htmlToDa
ta(e.settings.media_scripts,e.serializer.serialize(n,{selection:!0})):{}},d=function(e){var t=e.selection.getNode();if(t.getAttribute("data-mce-object")||t.getAttribute("data-ephox-embed-iri"))return e.selection.getContent()},f=function(e,n){return function(r){var i=r.html,a=e.find("#embed")[0],l=o.extend(t.htmlToData(n.settings.media_scripts,i),{source1:r.url});e.fromJSON(l),a&&(a.value(i),s.updateSize(e))}},p=function(e,t){var n,r,i=e.dom.select("img[data-mce-object]");for(n=0;n<t.length;n++)for(r=i.length-1;r>=0;r--)t[n]===i[r]&&i.splice(r,1);e.selection.select(i[0])},h=function(e,t){var n=e.dom.select("img[data-mce-object]");e.insertContent(t),p(e,n),e.nodeChanged()},m=function(e,t){var i=e.toJSON();i.embed=n.updateHtml(i.embed,i),i.embed?h(t,i.embed):r.getEmbedHtml(t,i).then(function(e){h(t,e.html)})["catch"](u(t))},g=function(e,t){o.each(t,function(t,n){e.find("#"+n).value(t)})},v=funct
ion(e){var i,a,p=[{name:"source1",type:"filepicker",filetype:"media",size:40,autofocus:!0,label:"Source",onpaste:function(){setTimeout(function(){r.getEmbedHtml(e,i.toJSON()).then(f(i,e))["catch"](u(e))},1)},onchange:function(t){r.getEmbedHtml(e,i.toJSON()).then(f(i,e))["catch"](u(e)),g(i,t.meta)},onbeforecall:function(e){e.meta=i.toJSON()}}],h=[],v=function(e){e(i),a=i.toJSON(),i.find("#embed").value(n.updateHtml(a.embed,a))};if(e.settings.media_alt_source!==!1&&h.push({name:"source2",type:"filepicker",filetype:"media",size:40,label:"Alternative source"}),e.settings.media_poster!==!1&&h.push({name:"poster",type:"filepicker",filetype:"image",size:40,label:"Poster"}),e.settings.media_dimensions!==!1){var y=s.createUi(v);p.push(y)}a=c(e);var b={id:"mcemediasource",type:"textbox",flex:1,name:"embed
",value:d(e),multiline:!0,rows:5,label:"Source"},C=function(){a=o.extend({},t.htmlToData(e.settings.media_scripts,this.value())),this.parent().parent().fromJSON(a)};b[l]=C,i=e.windowManager.open({title:"Insert/edit media",data:a,bodyType:"tabpanel",body:[{title:"General",type:"form",items:p},{title:"Embed",type:"container",layout:"flex",direction:"column",align:"stretch",padding:10,spacing:10,items:[{type:"label",text:"Paste your embed code below:",forId:"mcemediasource"},b]},{title:"Advanced",type:"form",items:h}],onSubmit:function(){s.updateSize(i),m(i,e)}}),s.syncSize(i)};return{showDialog:v}}),a("3",["e","8","9","a"],function(e,t,n,r){var i=function(e,i){if(e.settings.media_filter_html===!1)return i;var o,a=new t;return new n({validate:!1,allow_conditional_comments:!1,special:&
quot;script,noscript",comment:function(e){a.comment(e)},cdata:function(e){a.cdata(e)},text:function(e,t){a.text(e,t)},start:function(t,n,r){if(o=!0,"script"!==t&&"noscript"!==t){for(var i=0;i<n.length;i++){if(0===n[i].name.indexOf("on"))return;"style"===n[i].name&&(n[i].value=e.dom.serializeStyle(e.dom.parseStyle(n[i].value),t))}a.start(t,n,r),o=!1}},end:function(e){o||a.end(e)}},new r({})).parse(i),a.getContent()};return{sanitize:i}}),s("i",tinymce.html.Node),a("5",["3","h","i","f"],function(e,t,n,r){var i=function(e,t){var i,o=t.name;return i=new n("img",1),i.shortEnded=!0,a(e,t,i),i.attr({width:t.attr("width")||"300",height:t.attr("height")||("audio"===o?"30":"150"),style:t.attr("style"),src:r.transparentSrc,"data-mce-object":o,"class":"mce-object mce-obj
ect-"+o}),i},o=function(e,t){var r,i,o,s=t.name;return r=new n("span",1),r.attr({contentEditable:"false",style:t.attr("style"),"data-mce-object":s,"class":"mce-preview-object mce-object-"+s}),a(e,t,r),i=new n(s,1),i.attr({src:t.attr("src"),allowfullscreen:t.attr("allowfullscreen"),width:t.attr("width")||"300",height:t.attr("height")||("audio"===s?"30":"150"),frameborder:"0"}),o=new n("span",1),o.attr("class","mce-shim"),r.append(i),r.append(o),r},a=function(t,n,r){var i,o,a,s,l;for(a=n.attributes,s=a.length;s--;)i=a[s].name,o=a[s].value,"width"!==i&&"height"!==i&&"style"!==i&&("data"!==i&&"src"!==i||(o=t.convertURL(o,i)),r.attr("data-mce-p-"+i,o));l=n.firstChild&&n.firstChild.value,l&&(r.attr(&q
uot;data-mce-html",escape(e.sanitize(t,l))),r.firstChild=null)},s=function(e){for(;e=e.parent;)if(e.attr("data-ephox-embed-iri"))return!0;return!1},l=function(e){return function(n){for(var a,l,u=n.length;u--;)a=n[u],a.parent&&(a.parent.attr("data-mce-object")||("script"!==a.name||(l=t.getVideoScriptMatch(e.settings.media_scripts,a.attr("src"))))&&(l&&(l.width&&a.attr("width",l.width.toString()),l.height&&a.attr("height",l.height.toString())),"iframe"===a.name&&e.settings.media_live_embeds!==!1&&r.ceFalse?s(a)||a.replace(o(e,a)):s(a)||a.replace(i(e,a))))}};return{createPreviewIframeNode:o,createPlaceholderNode:i,placeHolderConverter:l}}),a("0",["1","2","3","4","5"],function(e,t,n,r,i){var o=function(e){e.on("ResolveName",function(e){var t;1===e.target.nodeType&&(t=e.target.getAt
tribute("data-mce-object"))&&(e.name=t)}),e.on("preInit",function(){var t=e.schema.getSpecialElements();tinymce.each("video audio iframe object".split(" "),function(e){t[e]=new RegExp("</"+e+"[^>]*>","gi")});var r=e.schema.getBoolAttrs();tinymce.each("webkitallowfullscreen mozallowfullscreen allowfullscreen".split(" "),function(e){r[e]={}}),e.parser.addNodeFilter("iframe,video,audio,object,embed,script",i.placeHolderConverter(e)),e.serializer.addAttributeFilter("data-mce-object",function(t,r){for(var i,o,a,s,l,u,c,d,f=t.length;f--;)if(i=t[f],i.parent){for(c=i.attr(r),o=new tinymce.html.Node(c,1),"audio"!==c&&"script"!==c&&(d=i.attr("class"),d&&d.indexOf("mce-preview-object")!==-1?o.attr({width:i.firstChild.attr("width"),height:i.firstChild.attr("height")}):o.attr({width:i.att
r("width"),height:i.attr("height")})),o.attr({style:i.attr("style")}),s=i.attributes,a=s.length;a--;){var p=s[a].name;0===p.indexOf("data-mce-p-")&&o.attr(p.substr(11),s[a].value)}"script"===c&&o.attr("type","text/javascript"),l=i.attr("data-mce-html"),l&&(u=new tinymce.html.Node("#text",3),u.raw=!0,u.value=n.sanitize(e,unescape(l)),o.append(u)),i.replace(o)}})}),e.on("click keyup",function(){var t=e.selection.getNode();t&&e.dom.hasClass(t,"mce-preview-object")&&e.dom.getAttrib(t,"data-mce-selected")&&t.setAttribute("data-mce-selected","2")}),e.on("ObjectSelected",function(e){var t=e.target.getAttribute("data-mce-object");"audio"!==t&&"script"!==t||e.preventDefault()}),e.on("objectResized",function(e){var t,n=e.target;n.getAttribute("da
ta-mce-object")&&(t=n.getAttribute("data-mce-html"),t&&(t=unescape(t),n.setAttribute("data-mce-html",escape(r.updateHtml(t,{width:e.width,height:e.height})))))}),this.showDialog=function(){t.showDialog(e)},e.addButton("media",{tooltip:"Insert/edit media",onclick:this.showDialog,stateSelector:["img[data-mce-object]","span[data-mce-object]","div[data-ephox-embed-iri]"]}),e.addMenuItem("media",{icon:"media",text:"Media",onclick:this.showDialog,context:"insert",prependToContext:!0}),e.on("setContent",function(){e.$("span.mce-preview-object").each(function(t,n){var r=e.$(n);0===r.find("span.mce-shim",n).length&&r.append('<span class="mce-shim"></span>')})}),e.addCommand("mceMedia",this.showDialog)};return e.add("media",o),function(){}}),r("0")()}();
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+!function(){var a={},b=function(b){for(var c=a[b],e=c.deps,f=c.defn,g=e.length,h=new Array(g),i=0;i<g;++i)h[i]=d(e[i]);var j=f.apply(null,h);if(void 0===j)throw"module ["+b+"] returned undefined";c.instance=j},c=function(b,c,d){if("string"!=typeof b)throw"module id must be a string";if(void 0===c)throw"no dependencies for "+b;if(void 0===d)throw"no definition function for "+b;a[b]={deps:c,defn:d,instance:void 0}},d=function(c){var d=a[c];if(void 0===d)throw"module ["+c+"] was undefined";return void 0===d.instance&&b(c),d.instance},e=function(a,b){for(var c=a.length,e=new Array(c),f=0;f<c;++f)e.push(d(a[f]));b.apply(null,b)},f={};f.bolt={module:{api:{define:c,require:e,demand:d}}};var g=c,h=function(a,b){g(a,[],function(){return b})};h("8",tinymce.util.Tools.resolve),g("1",[&q
uot;8"],function(a){return a("tinymce.html.Node")}),g("2",["8"],function(a){return a("tinymce.PluginManager")}),g("3",["8"],function(a){return a("tinymce.util.Tools")}),g("9",["8"],function(a){return a("tinymce.html.Writer")}),g("a",["8"],function(a){return a("tinymce.html.SaxParser")}),g("b",["8"],function(a){return a("tinymce.html.Schema")}),g("5",["3","9","a","b"],function(a,b,c,d){var e=function(a,e){if(a.settings.media_filter_html===!1)return e;var f,g=new b;return new c({validate:!1,allow_conditional_comments:!1,special:"script,noscript",comment:function(a){g.comment(a)},cdata:function(a){g.cdata(a)},text:function(a,b){g.text(a,b)},start:function(b,c,d){if(f=!0,"script"!==b&&"noscript"!==b){for(var e=0;e<c.length;e++){if(0===
c[e].name.indexOf("on"))return;"style"===c[e].name&&(c[e].value=a.dom.serializeStyle(a.dom.parseStyle(c[e].value),b))}g.start(b,c,d),f=!1}},end:function(a){f||g.end(a)}},new d({})).parse(e),g.getContent()};return{sanitize:e}}),g("c",[],function(){var a=function(a,b){if(a)for(var c=0;c<a.length;c++)if(b.indexOf(a[c].filter)!==-1)return a[c]};return{getVideoScriptMatch:a}}),g("d",["8"],function(a){return a("tinymce.Env")}),g("4",["5","c","1","d"],function(a,b,c,d){var e=function(a,b){var e,f=b.name;return e=new c("img",1),e.shortEnded=!0,g(a,b,e),e.attr({width:b.attr("width")||"300",height:b.attr("height")||("audio"===f?"30":"150"),style:b.attr("style"),src:d.transparentSrc,"data-mce-object":f,"class":"mce-object mce-object-"+f}),e},f=function(a,b){var d,e,f
,h=b.name;return d=new c("span",1),d.attr({contentEditable:"false",style:b.attr("style"),"data-mce-object":h,"class":"mce-preview-object mce-object-"+h}),g(a,b,d),e=new c(h,1),e.attr({src:b.attr("src"),allowfullscreen:b.attr("allowfullscreen"),width:b.attr("width")||"300",height:b.attr("height")||("audio"===h?"30":"150"),frameborder:"0"}),f=new c("span",1),f.attr("class","mce-shim"),d.append(e),d.append(f),d},g=function(b,c,d){var e,f,g,h,i;for(g=c.attributes,h=g.length;h--;)e=g[h].name,f=g[h].value,"width"!==e&&"height"!==e&&"style"!==e&&("data"!==e&&"src"!==e||(f=b.convertURL(f,e)),d.attr("data-mce-p-"+e,f));i=c.firstChild&&c.firstChild.value,i&&(d.attr("data-mce-html",escape(a.sanitize(b
,i))),d.firstChild=null)},h=function(a){for(;a=a.parent;)if(a.attr("data-ephox-embed-iri"))return!0;return!1},i=function(a){return function(c){for(var g,i,j=c.length;j--;)g=c[j],g.parent&&(g.parent.attr("data-mce-object")||("script"!==g.name||(i=b.getVideoScriptMatch(a.settings.media_scripts,g.attr("src"))))&&(i&&(i.width&&g.attr("width",i.width.toString()),i.height&&g.attr("height",i.height.toString())),"iframe"===g.name&&a.settings.media_live_embeds!==!1&&d.ceFalse?h(g)||g.replace(f(a,g)):h(g)||g.replace(e(a,g))))}};return{createPreviewIframeNode:f,createPlaceholderNode:e,placeHolderConverter:i}}),g("e",["8"],function(a){return a("tinymce.dom.DOMUtils")}),g("f",[],function(){var a=function(a){return a.replace(/px$/,"")},b=function(a){return/^[0-9.]+$/.test(a)?a+"px":a},c=function(b){return function
(c){return c?a(c.style[b]):""}},d=function(a){return function(c,d){c&&(c.style[a]=b(d))}};return{getMaxWidth:c("maxWidth"),getMaxHeight:c("maxHeight"),setMaxWidth:d("maxWidth"),setMaxHeight:d("maxHeight")}}),g("6",["9","a","b","e","f"],function(a,b,c,d,e){var f=d.DOM,g=function(a,b){var c,d,e,f;for(c in b)if(e=""+b[c],a.map[c])for(d=a.length;d--;)f=a[d],f.name===c&&(e?(a.map[c]=e,f.value=e):(delete a.map[c],a.splice(d,1)));else e&&(a.push({name:c,value:e}),a.map[c]=e)},h=function(c){var d=new a,e=new b(d);return e.parse(c),d.getContent()},i=function(d,e,f){var h,i=new a,j=0;return new b({validate:!1,allow_conditional_comments:!0,special:"script,noscript",comment:function(a){i.comment(a)},cdata:function(a){i.cdata(a)},text:function(a,b){i.text(a,b)},start:function(a,b,c){switch(a){case"video":case"object":case&qu
ot;embed":case"img":case"iframe":void 0!==e.height&&void 0!==e.width&&g(b,{width:e.width,height:e.height})}if(f)switch(a){case"video":g(b,{poster:e.poster,src:""}),e.source2&&g(b,{src:""});break;case"iframe":g(b,{src:e.source1});break;case"source":if(j++,j<=2&&(g(b,{src:e["source"+j],type:e["source"+j+"mime"]}),!e["source"+j]))return;break;case"img":if(!e.poster)return;h=!0}i.start(a,b,c)},end:function(a){if("video"===a&&f)for(var b=1;b<=2;b++)if(e["source"+b]){var c=[];c.map={},j<b&&(g(c,{src:e["source"+b],type:e["source"+b+"mime"]}),i.start("source",c,!0))}if(e.poster&&"object"===a&&f&&!h){var d=[];d.map={},g(d,{src:e.poster,width:e.width,height:e.height}),i.start("img",d,!0)}i.end(a)}},new c({})).pa
rse(d),i.getContent()},j=function(a){var b=f.createFragment(a);return""!==f.getAttrib(b.firstChild,"data-ephox-embed-iri")},k=function(a,b){var c=f.createFragment(a),d=c.firstChild;return e.setMaxWidth(d,b.width),e.setMaxHeight(d,b.height),h(d.outerHTML)},l=function(a,b,c){return j(a)?k(a,b):i(a,b,c)};return{updateHtml:l}}),g("g",["8"],function(a){return a("tinymce.util.Delay")}),g("h",["3","a","b","e","c","f"],function(a,b,c,d,e,f){var g=d.DOM,h=function(a){return g.getAttrib(a,"data-ephox-embed-iri")},i=function(a){var b=g.createFragment(a);return""!==h(b.firstChild)},j=function(c,d){var f={};return new b({validate:!1,allow_conditional_comments:!0,special:"script,noscript",start:function(b,d){if(f.source1||"param"!==b||(f.source1=d.map.movie),"iframe"!==b&&"object"!==b&&"embed"!
==b&&"video"!==b&&"audio"!==b||(f.type||(f.type=b),f=a.extend(d.map,f)),"script"===b){var g=e.getVideoScriptMatch(c,d.map.src);if(!g)return;f={type:"script",source1:d.map.src,width:g.width,height:g.height}}"source"===b&&(f.source1?f.source2||(f.source2=d.map.src):f.source1=d.map.src),"img"!==b||f.poster||(f.poster=d.map.src)}}).parse(d),f.source1=f.source1||f.src||f.data,f.source2=f.source2||"",f.poster=f.poster||"",f},k=function(a){var b=g.createFragment(a),c=b.firstChild;return{type:"ephox-embed-iri",source1:h(c),source2:"",poster:"",width:f.getMaxWidth(c),height:f.getMaxHeight(c)}},l=function(a,b){return i(b)?k(b):j(a,b)};return{htmlToData:l}}),g("m",[],function(){var a=function(a){var b={mp3:"audio/mpeg",wav:"audio/wav",mp4:"video/mp4",webm:"video/webm",ogg:"video/ogg",swf:"applicati
on/x-shockwave-flash"},c=a.toLowerCase().split(".").pop(),d=b[c];return d?d:""};return{guess:a}}),g("n",[],function(){var a=[{regex:/youtu\.be\/([\w\-.]+)/,type:"iframe",w:560,h:314,url:"//www.youtube.com/embed/$1",allowFullscreen:!0},{regex:/youtube\.com(.+)v=([^&]+)/,type:"iframe",w:560,h:314,url:"//www.youtube.com/embed/$2",allowFullscreen:!0},{regex:/youtube.com\/embed\/([a-z0-9\-_]+(?:\?.+)?)/i,type:"iframe",w:560,h:314,url:"//www.youtube.com/embed/$1",allowFullscreen:!0},{regex:/vimeo\.com\/([0-9]+)/,type:"iframe",w:425,h:350,url:"//player.vimeo.com/video/$1?title=0&byline=0&portrait=0&color=8dc7dc",allowfullscreen:!0},{regex:/vimeo\.com\/(.*)\/([0-9]+)/,type:"iframe",w:425,h:350,url:"//player.vimeo.com/video/$2?title=0&byline=0",allowfullscreen:!0},{regex:/maps\.google\.([a-z]{2,3})\/maps\/(.+)msid=(.+)/,type:"ifra
me",w:425,h:350,url:'//maps.google.com/maps/ms?msid=$2&output=embed"',allowFullscreen:!1},{regex:/dailymotion\.com\/video\/([^_]+)/,type:"iframe",w:480,h:270,url:"//www.dailymotion.com/embed/video/$1",allowFullscreen:!0}];return{urlPatterns:a}}),g("k",["m","h","n","c","6","3"],function(a,b,c,d,e,f){var g=function(g,h){var i="",j=f.extend({},h);if(!j.source1&&(f.extend(j,b.htmlToData(g.settings.media_scripts,j.embed)),!j.source1))return"";if(j.source2||(j.source2=""),j.poster||(j.poster=""),j.source1=g.convertURL(j.source1,"source"),j.source2=g.convertURL(j.source2,"source"),j.source1mime=a.guess(j.source1),j.source2mime=a.guess(j.source2),j.poster=g.convertURL(j.poster,"poster"),f.each(c.urlPatterns,function(a){var b,c,d=a.regex.exec(j.source1);if(d){for(c=a.url,b=0;d[b];b++)c=c.replace("$"+b,f
unction(){return d[b]});j.source1=c,j.type=a.type,j.allowFullscreen=a.allowFullscreen,j.width=j.width||a.w,j.height=j.height||a.h}}),j.embed)i=e.updateHtml(j.embed,j,!0);else{var k=d.getVideoScriptMatch(g.settings.media_scripts,j.source1);if(k&&(j.type="script",j.width=k.width,j.height=k.height),j.width=j.width||300,j.height=j.height||150,f.each(j,function(a,b){j[b]=g.dom.encode(a)}),"iframe"===j.type){var l=j.allowFullscreen?' allowFullscreen="1"':"";i+='<iframe src="'+j.source1+'" width="'+j.width+'" height="'+j.height+'"'+l+"></iframe>"}else"application/x-shockwave-flash"===j.source1mime?(i+='<object data="'+j.source1+'" width="'+j.width+'" height="'+j.height+'" type="application/x-shockwave-flash">',j.poster&&(i+='<img src="'+j.poster+'" width="'+j.width+'" height="'+j.height+'" />'
),i+="</object>"):j.source1mime.indexOf("audio")!==-1?g.settings.audio_template_callback?i=g.settings.audio_template_callback(j):i+='<audio controls="controls" src="'+j.source1+'">'+(j.source2?'\n<source src="'+j.source2+'"'+(j.source2mime?' type="'+j.source2mime+'"':"")+" />\n":"")+"</audio>":"script"===j.type?i+='<script src="'+j.source1+'"></script>':i=g.settings.video_template_callback?g.settings.video_template_callback(j):'<video width="'+j.width+'" height="'+j.height+'"'+(j.poster?' poster="'+j.poster+'"':"")+' controls="controls">\n<source src="'+j.source1+'"'+(j.source1mime?' type="'+j.source1mime+'"':"")+" />\n"+(j.source2?'<source src="'+j.source2+'"'+(j.source2mime?' type="'+j.source2mime+'"':&qu
ot;")+" />\n":"")+"</video>"}return i};return{dataToHtml:g}}),g("l",["8"],function(a){return a("tinymce.util.Promise")}),g("i",["k","l"],function(a,b){var c=function(a,c,d){var e={};return new b(function(b,f){var g=function(d){return d.html&&(e[a.source1]=d),b({url:a.source1,html:d.html?d.html:c(a)})};e[a.source1]?g(e[a.source1]):d({url:a.source1},g,f)})},d=function(a,c){return new b(function(b){b({html:c(a),url:a.source1})})},e=function(b){return function(c){return a.dataToHtml(b,c)}},f=function(a,b){var f=a.settings.media_url_resolver;return f?c(b,e(a),f):d(b,e(a))};return{getEmbedHtml:f}}),g("j",[],function(){var a=function(a,b){a.state.set("oldVal",a.value()),b.state.set("oldVal",b.value())},b=function(a,b){var c=a.find("#width")[0],d=a.find("#height")[0],e=a.find("#constrain")[0];c&&d&&e&&
amp;b(c,d,e.checked())},c=function(b,c,d){var e=b.state.get("oldVal"),f=c.state.get("oldVal"),g=b.value(),h=c.value();d&&e&&f&&g&&h&&(g!==e?(h=Math.round(g/e*h),isNaN(h)||c.value(h)):(g=Math.round(h/f*g),isNaN(g)||b.value(g))),a(b,c)},d=function(c){b(c,a)},e=function(a){b(a,c)},f=function(a){var b=function(){a(function(a){e(a)})};return{type:"container",label:"Dimensions",layout:"flex",align:"center",spacing:5,items:[{name:"width",type:"textbox",maxLength:5,size:5,onchange:b,ariaLabel:"Width"},{type:"label",text:"x"},{name:"height",type:"textbox",maxLength:5,size:5,onchange:b,ariaLabel:"Height"},{name:"constrain",type:"checkbox",checked:!0,text:"Constrain proportions"}]}};return{createUi:f,syncSize:d,updateSize:e}}),g("7",["g","h","6",&q
uot;i","f","3","d","j"],function(a,b,c,d,e,f,g,h){var i=g.ie&&g.ie<=8?"onChange":"onInput",j=function(a){return function(b){var c=b&&b.msg?"Media embed handler error: "+b.msg:"Media embed handler threw unknown error.";a.notificationManager.open({type:"error",text:c})}},k=function(a){var c=a.selection.getNode(),d=c.getAttribute("data-ephox-embed-iri");return d?{source1:d,"data-ephox-embed-iri":d,width:e.getMaxWidth(c),height:e.getMaxHeight(c)}:c.getAttribute("data-mce-object")?b.htmlToData(a.settings.media_scripts,a.serializer.serialize(c,{selection:!0})):{}},l=function(a){var b=a.selection.getNode();if(b.getAttribute("data-mce-object")||b.getAttribute("data-ephox-embed-iri"))return a.selection.getContent()},m=function(a,c){return function(d){var e=d.html,g=a.find("#embed")[0],i=f.extend(b.htmlToData(c.settings.m
edia_scripts,e),{source1:d.url});a.fromJSON(i),g&&(g.value(e),h.updateSize(a))}},n=function(a,b){var c,d,e=a.dom.select("img[data-mce-object]");for(c=0;c<b.length;c++)for(d=e.length-1;d>=0;d--)b[c]===e[d]&&e.splice(d,1);a.selection.select(e[0])},o=function(a,b){var c=a.dom.select("img[data-mce-object]");a.insertContent(b),n(a,c),a.nodeChanged()},p=function(a,b){var e=a.toJSON();e.embed=c.updateHtml(e.embed,e),e.embed?o(b,e.embed):d.getEmbedHtml(b,e).then(function(a){o(b,a.html)})["catch"](j(b))},q=function(a,b){f.each(b,function(b,c){a.find("#"+c).value(b)})},r=function(a){var e,g,n=[{name:"source1",type:"filepicker",filetype:"media",size:40,autofocus:!0,label:"Source",onpaste:function(){setTimeout(function(){d.getEmbedHtml(a,e.toJSON()).then(m(e,a))["catch"](j(a))},1)},onchange:function(b){d.getEmbedHtml(a,e.toJSON()).then(m(e,a))["catch"](j(a)),q(e,b.meta)},onb
eforecall:function(a){a.meta=e.toJSON()}}],o=[],r=function(a){a(e),g=e.toJSON(),e.find("#embed").value(c.updateHtml(g.embed,g))};if(a.settings.media_alt_source!==!1&&o.push({name:"source2",type:"filepicker",filetype:"media",size:40,label:"Alternative source"}),a.settings.media_poster!==!1&&o.push({name:"poster",type:"filepicker",filetype:"image",size:40,label:"Poster"}),a.settings.media_dimensions!==!1){var s=h.createUi(r);n.push(s)}g=k(a);var t={id:"mcemediasource",type:"textbox",flex:1,name:"embed",value:l(a),multiline:!0,rows:5,label:"Source"},u=function(){g=f.extend({},b.htmlToData(a.settings.media_scripts,this.value())),this.parent().parent().fromJSON(g)};t[i]=u,e=a.windowManager.open({title:"Insert/edit media",data:g,bodyType:"tabpanel",body:[{title:"General",type:"form",items:n},{title:"E
mbed",type:"container",layout:"flex",direction:"column",align:"stretch",padding:10,spacing:10,items:[{type:"label",text:"Paste your embed code below:",forId:"mcemediasource"},t]},{title:"Advanced",type:"form",items:o}],onSubmit:function(){h.updateSize(e),p(e,a)}}),h.syncSize(e)};return{showDialog:r}}),g("0",["1","2","3","4","5","6","7"],function(a,b,c,d,e,f,g){var h=function(b){b.on("ResolveName",function(a){var b;1===a.target.nodeType&&(b=a.target.getAttribute("data-mce-object"))&&(a.name=b)}),b.on("preInit",function(){var f=b.schema.getSpecialElements();c.each("video audio iframe object".split(" "),function(a){f[a]=new RegExp("</"+a+"[^>]*>","gi")});var g=b.schema.getBoolAttrs();c.each("webkitallowful
lscreen mozallowfullscreen allowfullscreen".split(" "),function(a){g[a]={}}),b.parser.addNodeFilter("iframe,video,audio,object,embed,script",d.placeHolderConverter(b)),b.serializer.addAttributeFilter("data-mce-object",function(c,d){for(var f,g,h,i,j,k,l,m,n=c.length;n--;)if(f=c[n],f.parent){for(l=f.attr(d),g=new a(l,1),"audio"!==l&&"script"!==l&&(m=f.attr("class"),m&&m.indexOf("mce-preview-object")!==-1?g.attr({width:f.firstChild.attr("width"),height:f.firstChild.attr("height")}):g.attr({width:f.attr("width"),height:f.attr("height")})),g.attr({style:f.attr("style")}),i=f.attributes,h=i.length;h--;){var o=i[h].name;0===o.indexOf("data-mce-p-")&&g.attr(o.substr(11),i[h].value)}"script"===l&&g.attr("type","text/javascript"),j=f.attr("data-mce-html"),j&&(k=new a("
;#text",3),k.raw=!0,k.value=e.sanitize(b,unescape(j)),g.append(k)),f.replace(g)}})}),b.on("click keyup",function(){var a=b.selection.getNode();a&&b.dom.hasClass(a,"mce-preview-object")&&b.dom.getAttrib(a,"data-mce-selected")&&a.setAttribute("data-mce-selected","2")}),b.on("ObjectSelected",function(a){var b=a.target.getAttribute("data-mce-object");"audio"!==b&&"script"!==b||a.preventDefault()}),b.on("objectResized",function(a){var b,c=a.target;c.getAttribute("data-mce-object")&&(b=c.getAttribute("data-mce-html"),b&&(b=unescape(b),c.setAttribute("data-mce-html",escape(f.updateHtml(b,{width:a.width,height:a.height})))))}),this.showDialog=function(){g.showDialog(b)},b.addButton("media",{tooltip:"Insert/edit media",onclick:this.showDialog,stateSelector:["img[data-mce-object]",&q
uot;span[data-mce-object]","div[data-ephox-embed-iri]"]}),b.addMenuItem("media",{icon:"media",text:"Media",onclick:this.showDialog,context:"insert",prependToContext:!0}),b.on("setContent",function(){b.$("span.mce-preview-object").each(function(a,c){var d=b.$(c);0===d.find("span.mce-shim",c).length&&d.append('<span class="mce-shim"></span>')})}),b.addCommand("mceMedia",this.showDialog)};return b.add("media",h),function(){}}),d("0")()}();
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginspastepluginjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/paste/plugin.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/paste/plugin.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/paste/plugin.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,109 +1,294 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Compiled inline version. (Library mode)
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+(function () {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/*jshint smarttabs:true, undef:true, latedef:true, curly:true, bitwise:true, camelcase:true */
-/*globals $code */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+var defs = {}; // id -> {dependencies, definition, instance (possibly undefined)}
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-(function(exports, undefined) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+// Used when there is no 'main' module.
+// The name is probably (hopefully) unique so minification removes for releases.
+var register_3795 = function (id) {
+ var module = dem(id);
+ var fragments = id.split('.');
+ var target = Function('return this;')();
+ for (var i = 0; i < fragments.length - 1; ++i) {
+ if (target[fragments[i]] === undefined)
+ target[fragments[i]] = {};
+ target = target[fragments[i]];
+ }
+ target[fragments[fragments.length - 1]] = module;
+};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var modules = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+var instantiate = function (id) {
+ var actual = defs[id];
+ var dependencies = actual.deps;
+ var definition = actual.defn;
+ var len = dependencies.length;
+ var instances = new Array(len);
+ for (var i = 0; i < len; ++i)
+ instances[i] = dem(dependencies[i]);
+ var defResult = definition.apply(null, instances);
+ if (defResult === undefined)
+ throw 'module [' + id + '] returned undefined';
+ actual.instance = defResult;
+};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function require(ids, callback) {
- var module, defs = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+var def = function (id, dependencies, definition) {
+ if (typeof id !== 'string')
+ throw 'module id must be a string';
+ else if (dependencies === undefined)
+ throw 'no dependencies for ' + id;
+ else if (definition === undefined)
+ throw 'no definition function for ' + id;
+ defs[id] = {
+ deps: dependencies,
+ defn: definition,
+ instance: undefined
+ };
+};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var i = 0; i < ids.length; ++i) {
- module = modules[ids[i]] || resolve(ids[i]);
- if (!module) {
- throw 'module definition dependecy not found: ' + ids[i];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+var dem = function (id) {
+ var actual = defs[id];
+ if (actual === undefined)
+ throw 'module [' + id + '] was undefined';
+ else if (actual.instance === undefined)
+ instantiate(id);
+ return actual.instance;
+};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- defs.push(module);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+var req = function (ids, callback) {
+ var len = ids.length;
+ var instances = new Array(len);
+ for (var i = 0; i < len; ++i)
+ instances.push(dem(ids[i]));
+ callback.apply(null, callback);
+};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- callback.apply(null, defs);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+var ephox = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function define(id, dependencies, definition) {
- if (typeof id !== 'string') {
- throw 'invalid module definition, module id must be defined and be a string';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ephox.bolt = {
+ module: {
+ api: {
+ define: def,
+ require: req,
+ demand: dem
+ }
+ }
+};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (dependencies === undefined) {
- throw 'invalid module definition, dependencies must be specified';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+var define = def;
+var require = req;
+var demand = dem;
+// this helps with minificiation when using a lot of global references
+var defineGlobal = function (id, ref) {
+ define(id, [], function () { return ref; });
+};
+/*jsc
+["tinymce.plugins.paste.Plugin","tinymce.core.PluginManager","tinymce.plugins.paste.core.Clipboard","tinymce.plugins.paste.core.CutCopy","tinymce.plugins.paste.core.Quirks","tinymce.plugins.paste.core.WordFilter","global!tinymce.util.Tools.resolve","tinymce.core.dom.RangeUtils","tinymce.core.Env","tinymce.core.util.Delay","tinymce.core.util.Tools","tinymce.core.util.VK","tinymce.plugins.paste.core.InternalHtml","tinymce.plugins.paste.core.Utils","tinymce.plugins.paste.core.Newlines","tinymce.plugins.paste.core.SmartPaste","tinymce.core.html.DomParser","tinymce.core.html.Schema","tinymce.core.html.Serializer","tinymce.core.html.Node","tinymce.core.html.Entities"]
+jsc*/
+defineGlobal("global!tinymce.util.Tools.resolve", tinymce.util.Tools.resolve);
+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (definition === undefined) {
- throw 'invalid module definition, definition function must be specified';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.PluginManager',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.PluginManager');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- require(dependencies, function() {
- modules[id] = definition.apply(null, arguments);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function defined(id) {
- return !!modules[id];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.RangeUtils',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.dom.RangeUtils');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function resolve(id) {
- var target = exports;
- var fragments = id.split(/[.\/]/);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var fi = 0; fi < fragments.length; ++fi) {
- if (!target[fragments[fi]]) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.Env',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.Env');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- target = target[fragments[fi]];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return target;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.Delay',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.util.Delay');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function expose(ids) {
- var i, target, id, fragments, privateModules;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0; i < ids.length; i++) {
- target = exports;
- id = ids[i];
- fragments = id.split(/[.\/]/);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.Tools',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.util.Tools');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var fi = 0; fi < fragments.length - 1; ++fi) {
- if (target[fragments[fi]] === undefined) {
- target[fragments[fi]] = {};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- target = target[fragments[fi]];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.VK',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.util.VK');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- target[fragments[fragments.length - 1]] = modules[id];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * InternalHtml.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Expose private modules for unit tests
- if (exports.AMDLC_TESTS) {
- privateModules = exports.privateModules || {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.paste.core.InternalHtml',
+ [
+ ],
+ function () {
+ var internalMimeType = 'x-tinymce/html';
+ var internalMark = '<!-- ' + internalMimeType + ' -->';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (id in modules) {
- privateModules[id] = modules[id];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var mark = function (html) {
+ return internalMark + html;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0; i < ids.length; i++) {
- delete privateModules[ids[i]];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var unmark = function (html) {
+ return html.replace(internalMark, '');
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- exports.privateModules = privateModules;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isMarked = function (html) {
+ return html.indexOf(internalMark) !== -1;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/plugins/paste/classes/Utils.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ mark: mark,
+ unmark: unmark,
+ isMarked: isMarked,
+ internalHtmlMime: function () {
+ return internalMimeType;
+ }
+ };
+ }
+);
+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.html.DomParser',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.html.DomParser');
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.core.html.Schema',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.html.Schema');
+ }
+);
+
+/**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Utils.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -114,139 +299,384 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.pasteplugin.Utils
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/pasteplugin/Utils", [
- "tinymce/util/Tools",
- "tinymce/html/DomParser",
- "tinymce/html/Schema"
-], function(Tools, DomParser, Schema) {
- function filter(content, items) {
- Tools.each(items, function(v) {
- if (v.constructor == RegExp) {
- content = content.replace(v, '');
- } else {
- content = content.replace(v[0], v[1]);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.paste.core.Utils',
+ [
+ 'tinymce.core.util.Tools',
+ 'tinymce.core.html.DomParser',
+ 'tinymce.core.html.Schema'
+ ],
+ function (Tools, DomParser, Schema) {
+ function filter(content, items) {
+ Tools.each(items, function (v) {
+ if (v.constructor == RegExp) {
+ content = content.replace(v, '');
+ } else {
+ content = content.replace(v[0], v[1]);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return content;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return content;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Gets the innerText of the specified element. It will handle edge cases
- * and works better than textContent on Gecko.
- *
- * @param {String} html HTML string to get text from.
- * @return {String} String of text with line feeds.
- */
- function innerText(html) {
- var schema = new Schema(), domParser = new DomParser({}, schema), text = '';
- var shortEndedElements = schema.getShortEndedElements();
- var ignoreElements = Tools.makeMap('script noscript style textarea video audio iframe object', ' ');
- var blockElements = schema.getBlockElements();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Gets the innerText of the specified element. It will handle edge cases
+ * and works better than textContent on Gecko.
+ *
+ * @param {String} html HTML string to get text from.
+ * @return {String} String of text with line feeds.
+ */
+ function innerText(html) {
+ var schema = new Schema(), domParser = new DomParser({}, schema), text = '';
+ var shortEndedElements = schema.getShortEndedElements();
+ var ignoreElements = Tools.makeMap('script noscript style textarea video audio iframe object', ' ');
+ var blockElements = schema.getBlockElements();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function walk(node) {
- var name = node.name, currentNode = node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function walk(node) {
+ var name = node.name, currentNode = node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name === 'br') {
- text += '\n';
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name === 'br') {
+ text += '\n';
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // img/input/hr
- if (shortEndedElements[name]) {
- text += ' ';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // img/input/hr
+ if (shortEndedElements[name]) {
+ text += ' ';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Ingore script, video contents
- if (ignoreElements[name]) {
- text += ' ';
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Ingore script, video contents
+ if (ignoreElements[name]) {
+ text += ' ';
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.type == 3) {
- text += node.value;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.type == 3) {
+ text += node.value;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Walk all children
- if (!node.shortEnded) {
- if ((node = node.firstChild)) {
- do {
- walk(node);
- } while ((node = node.next));
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Walk all children
+ if (!node.shortEnded) {
+ if ((node = node.firstChild)) {
+ do {
+ walk(node);
+ } while ((node = node.next));
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add \n or \n\n for blocks or P
- if (blockElements[name] && currentNode.next) {
- text += '\n';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add \n or \n\n for blocks or P
+ if (blockElements[name] && currentNode.next) {
+ text += '\n';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name == 'p') {
- text += '\n';
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name == 'p') {
+ text += '\n';
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- html = filter(html, [
- /<!\[[^\]]+\]>/g // Conditional comments
- ]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ html = filter(html, [
+ /<!\[[^\]]+\]>/g // Conditional comments
+ ]);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- walk(domParser.parse(html));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ walk(domParser.parse(html));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return text;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return text;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Trims the specified HTML by removing all WebKit fragments, all elements wrapping the body trailing BR elements etc.
- *
- * @param {String} html Html string to trim contents on.
- * @return {String} Html contents that got trimmed.
- */
- function trimHtml(html) {
- function trimSpaces(all, s1, s2) {
- // WebKit meant to preserve multiple spaces but instead inserted around all inline tags,
- // including the spans with inline styles created on paste
- if (!s1 && !s2) {
- return ' ';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Trims the specified HTML by removing all WebKit fragments, all elements wrapping the body trailing BR elements etc.
+ *
+ * @param {String} html Html string to trim contents on.
+ * @return {String} Html contents that got trimmed.
+ */
+ function trimHtml(html) {
+ function trimSpaces(all, s1, s2) {
+ // WebKit meant to preserve multiple spaces but instead inserted around all inline tags,
+ // including the spans with inline styles created on paste
+ if (!s1 && !s2) {
+ return ' ';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return '\u00a0';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return '\u00a0';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- html = filter(html, [
- /^[\s\S]*<body[^>]*>\s*|\s*<\/body[^>]*>[\s\S]*$/g, // Remove anything but the contents within the BODY element
- /<!--StartFragment-->|<!--EndFragment-->/g, // Inner fragments (tables from excel on mac)
- [/( ?)<span class="Apple-converted-space">\u00a0<\/span>( ?)/g, trimSpaces],
- /<br class="Apple-interchange-newline">/g,
- /<br>$/i // Trailing BR elements
- ]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ html = filter(html, [
+ /^[\s\S]*<body[^>]*>\s*|\s*<\/body[^>]*>[\s\S]*$/ig, // Remove anything but the contents within the BODY element
+ /<!--StartFragment-->|<!--EndFragment-->/g, // Inner fragments (tables from excel on mac)
+ [/( ?)<span class="Apple-converted-space">\u00a0<\/span>( ?)/g, trimSpaces],
+ /<br class="Apple-interchange-newline">/g,
+ /<br>$/i // Trailing BR elements
+ ]);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return html;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return html;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // TODO: Should be in some global class
- function createIdGenerator(prefix) {
- var count = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // TODO: Should be in some global class
+ function createIdGenerator(prefix) {
+ var count = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function() {
- return prefix + (count++);
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function () {
+ return prefix + (count++);
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- filter: filter,
- innerText: innerText,
- trimHtml: trimHtml,
- createIdGenerator: createIdGenerator
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isMsEdge = function () {
+ return navigator.userAgent.indexOf(' Edge/') !== -1;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/plugins/paste/classes/SmartPaste.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ filter: filter,
+ innerText: innerText,
+ trimHtml: trimHtml,
+ createIdGenerator: createIdGenerator,
+ isMsEdge: isMsEdge
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * CutCopy.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.plugins.paste.core.CutCopy',
+ [
+ 'tinymce.core.Env',
+ 'tinymce.plugins.paste.core.InternalHtml',
+ 'tinymce.plugins.paste.core.Utils'
+ ],
+ function (Env, InternalHtml, Utils) {
+ var noop = function () {
+ };
+
+ var hasWorkingClipboardApi = function (clipboardData) {
+ // iOS supports the clipboardData API but it doesn't do anything for cut operations
+ // Edge 15 has a broken HTML Clipboard API see https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/11780845/
+ return Env.iOS === false && clipboardData !== undefined && typeof clipboardData.setData === 'function' && Utils.isMsEdge() !== true;
+ };
+
+ var setHtml5Clipboard = function (clipboardData, html, text) {
+ if (hasWorkingClipboardApi(clipboardData)) {
+ try {
+ clipboardData.clearData();
+ clipboardData.setData('text/html', html);
+ clipboardData.setData('text/plain', text);
+ clipboardData.setData(InternalHtml.internalHtmlMime(), html);
+ return true;
+ } catch (e) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ };
+
+ var setClipboardData = function (evt, data, fallback, done) {
+ if (setHtml5Clipboard(evt.clipboardData, data.html, data.text)) {
+ evt.preventDefault();
+ done();
+ } else {
+ fallback(data.html, done);
+ }
+ };
+
+ var fallback = function (editor) {
+ return function (html, done) {
+ var markedHtml = InternalHtml.mark(html);
+ var outer = editor.dom.create('div', { contenteditable: "false" });
+ var inner = editor.dom.create('div', { contenteditable: "true" }, markedHtml);
+ editor.dom.setStyles(outer, {
+ position: 'fixed',
+ left: '-3000px',
+ width: '1000px',
+ overflow: 'hidden'
+ });
+ outer.appendChild(inner);
+ editor.dom.add(editor.getBody(), outer);
+
+ var range = editor.selection.getRng();
+ inner.focus();
+
+ var offscreenRange = editor.dom.createRng();
+ offscreenRange.selectNodeContents(inner);
+ editor.selection.setRng(offscreenRange);
+
+ setTimeout(function () {
+ outer.parentNode.removeChild(outer);
+ editor.selection.setRng(range);
+ done();
+ }, 0);
+ };
+ };
+
+ var getData = function (editor) {
+ return {
+ html: editor.selection.getContent(),
+ text: editor.selection.getContent({ format: 'text' })
+ };
+ };
+
+ var cut = function (editor) {
+ return function (evt) {
+ if (editor.selection.isCollapsed() === false) {
+ setClipboardData(evt, getData(editor), fallback(editor), function () {
+ editor.execCommand('Delete');
+ });
+ }
+ };
+ };
+
+ var copy = function (editor) {
+ return function (evt) {
+ if (editor.selection.isCollapsed() === false) {
+ setClipboardData(evt, getData(editor), fallback(editor), noop);
+ }
+ };
+ };
+
+ var register = function (editor) {
+ editor.on('cut', cut(editor));
+ editor.on('copy', copy(editor));
+ };
+
+ return {
+ register: register
+ };
+ }
+);
+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.core.html.Entities',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.html.Entities');
+ }
+);
+
+/**
+ * Newlines.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+/**
+ * Newlines class contains utilities to convert newlines (\n or \r\n) tp BRs or to a combination of the specified block element and BRs
+ *
+ * @class tinymce.Newlines
+ * @private
+ */
+define(
+ 'tinymce.plugins.paste.core.Newlines',
+ [
+ 'tinymce.core.html.Entities'
+ ],
+ function (Entities) {
+
+ var isPlainText = function (text) {
+ // so basically any tag that is not one of the "p, div, br", or is one of them, but is followed
+ // by some additional characters qualifies the text as not a plain text (having some HTML tags)
+ return !/<(?:(?!\/?(?:div|p|br))[^>]*|(?:div|p|br)\s+\w[^>]+)>/.test(text);
+ };
+
+
+ var toBRs = function (text) {
+ return text.replace(/\r?\n/g, '<br>');
+ };
+
+
+ var openContainer = function (rootTag, rootAttrs) {
+ var key, attrs = [];
+ var tag = '<' + rootTag;
+
+ if (typeof rootAttrs === 'object') {
+ for (key in rootAttrs) {
+ if (rootAttrs.hasOwnProperty(key)) {
+ attrs.push(key + '="' + Entities.encodeAllRaw(rootAttrs[key]) + '"');
+ }
+ }
+
+ if (attrs.length) {
+ tag += ' ' + attrs.join(' ');
+ }
+ }
+ return tag + '>';
+ };
+
+
+ var toBlockElements = function (text, rootTag, rootAttrs) {
+ var pieces = text.split(/\r?\n/);
+ var i = 0, len = pieces.length;
+ var stack = [];
+ var blocks = [];
+ var tagOpen = openContainer(rootTag, rootAttrs);
+ var tagClose = '</' + rootTag + '>';
+ var isLast, newlineFollows, isSingleNewline;
+
+ // if single-line text then nothing to do
+ if (pieces.length === 1) {
+ return text;
+ }
+
+ for (; i < len; i++) {
+ isLast = i === len - 1;
+ newlineFollows = !isLast && !pieces[i + 1];
+ isSingleNewline = !pieces[i] && !stack.length;
+
+ stack.push(pieces[i] ? pieces[i] : ' ');
+
+ if (isLast || newlineFollows || isSingleNewline) {
+ blocks.push(stack.join('<br>'));
+ stack = [];
+ }
+
+ if (newlineFollows) {
+ i++; // extra progress for extra newline
+ }
+ }
+
+ return blocks.length === 1 ? blocks[0] : tagOpen + blocks.join(tagClose + tagOpen) + tagClose;
+ };
+
+
+ var convert = function (text, rootTag, rootAttrs) {
+ return rootTag ? toBlockElements(text, rootTag, rootAttrs) : toBRs(text);
+ };
+
+
+ return {
+ isPlainText: isPlainText,
+ convert: convert,
+ toBRs: toBRs,
+ toBlockElements: toBlockElements
+ };
+ }
+);
+/**
</ins><span class="cx" style="display: block; padding: 0 10px"> * SmartPaste.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -260,86 +690,88 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.pasteplugin.SmartPaste
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/pasteplugin/SmartPaste", [
- "tinymce/util/Tools"
-], function (Tools) {
- var isAbsoluteUrl = function (url) {
- return /^https?:\/\/[\w\?\-\/+=.&%@~#]+$/i.test(url);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.paste.core.SmartPaste',
+ [
+ 'tinymce.core.util.Tools'
+ ],
+ function (Tools) {
+ var isAbsoluteUrl = function (url) {
+ return /^https?:\/\/[\w\?\-\/+=.&%@~#]+$/i.test(url);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isImageUrl = function (url) {
- return isAbsoluteUrl(url) && /.(gif|jpe?g|png)$/.test(url);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isImageUrl = function (url) {
+ return isAbsoluteUrl(url) && /.(gif|jpe?g|png)$/.test(url);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var createImage = function (editor, url, pasteHtml) {
- editor.undoManager.extra(function () {
- pasteHtml(editor, url);
- }, function () {
- editor.insertContent('<img src="' + url + '">');
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createImage = function (editor, url, pasteHtml) {
+ editor.undoManager.extra(function () {
+ pasteHtml(editor, url);
+ }, function () {
+ editor.insertContent('<img src="' + url + '">');
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var createLink = function (editor, url, pasteHtml) {
- editor.undoManager.extra(function () {
- pasteHtml(editor, url);
- }, function () {
- editor.execCommand('mceInsertLink', false, url);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createLink = function (editor, url, pasteHtml) {
+ editor.undoManager.extra(function () {
+ pasteHtml(editor, url);
+ }, function () {
+ editor.execCommand('mceInsertLink', false, url);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var linkSelection = function (editor, html, pasteHtml) {
- return editor.selection.isCollapsed() === false && isAbsoluteUrl(html) ? createLink(editor, html, pasteHtml) : false;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var linkSelection = function (editor, html, pasteHtml) {
+ return editor.selection.isCollapsed() === false && isAbsoluteUrl(html) ? createLink(editor, html, pasteHtml) : false;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var insertImage = function (editor, html, pasteHtml) {
- return isImageUrl(html) ? createImage(editor, html, pasteHtml) : false;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var insertImage = function (editor, html, pasteHtml) {
+ return isImageUrl(html) ? createImage(editor, html, pasteHtml) : false;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var pasteHtml = function (editor, html) {
- editor.insertContent(html, {
- merge: editor.settings.paste_merge_formats !== false,
- paste: true
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var pasteHtml = function (editor, html) {
+ editor.insertContent(html, {
+ merge: editor.settings.paste_merge_formats !== false,
+ paste: true
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var smartInsertContent = function (editor, html) {
- Tools.each([
- linkSelection,
- insertImage,
- pasteHtml
- ], function (action) {
- return action(editor, html, pasteHtml) !== true;
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var smartInsertContent = function (editor, html) {
+ Tools.each([
+ linkSelection,
+ insertImage,
+ pasteHtml
+ ], function (action) {
+ return action(editor, html, pasteHtml) !== true;
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var insertContent = function (editor, html) {
- if (editor.settings.smart_paste === false) {
- pasteHtml(editor, html);
- } else {
- smartInsertContent(editor, html);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var insertContent = function (editor, html) {
+ if (editor.settings.smart_paste === false) {
+ pasteHtml(editor, html);
+ } else {
+ smartInsertContent(editor, html);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- isImageUrl: isImageUrl,
- isAbsoluteUrl: isAbsoluteUrl,
- insertContent: insertContent
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ isImageUrl: isImageUrl,
+ isAbsoluteUrl: isAbsoluteUrl,
+ insertContent: insertContent
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/plugins/paste/classes/Clipboard.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Clipboard.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -364,692 +796,727 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.pasteplugin.Clipboard
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/pasteplugin/Clipboard", [
- "tinymce/Env",
- "tinymce/dom/RangeUtils",
- "tinymce/util/VK",
- "tinymce/pasteplugin/Utils",
- "tinymce/pasteplugin/SmartPaste",
- "tinymce/util/Delay"
-], function(Env, RangeUtils, VK, Utils, SmartPaste, Delay) {
- return function(editor) {
- var self = this, pasteBinElm, lastRng, keyboardPasteTimeStamp = 0, draggingInternally = false;
- var pasteBinDefaultContent = '%MCEPASTEBIN%', keyboardPastePlainTextState;
- var mceInternalUrlPrefix = 'data:text/mce-internal,';
- var uniqueId = Utils.createIdGenerator("mceclip");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.paste.core.Clipboard',
+ [
+ 'tinymce.core.dom.RangeUtils',
+ 'tinymce.core.Env',
+ 'tinymce.core.util.Delay',
+ 'tinymce.core.util.Tools',
+ 'tinymce.core.util.VK',
+ 'tinymce.plugins.paste.core.CutCopy',
+ 'tinymce.plugins.paste.core.InternalHtml',
+ 'tinymce.plugins.paste.core.Newlines',
+ 'tinymce.plugins.paste.core.SmartPaste',
+ 'tinymce.plugins.paste.core.Utils'
+ ],
+ function (RangeUtils, Env, Delay, Tools, VK, CutCopy, InternalHtml, Newlines, SmartPaste, Utils) {
+ return function (editor) {
+ var self = this, pasteBinElm, lastRng, keyboardPasteTimeStamp = 0, draggingInternally = false;
+ var pasteBinDefaultContent = '%MCEPASTEBIN%', keyboardPastePlainTextState;
+ var mceInternalUrlPrefix = 'data:text/mce-internal,';
+ var uniqueId = Utils.createIdGenerator("mceclip");
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Pastes the specified HTML. This means that the HTML is filtered and then
- * inserted at the current selection in the editor. It will also fire paste events
- * for custom user filtering.
- *
- * @param {String} html HTML code to paste into the current selection.
- */
- function pasteHtml(html) {
- var args, dom = editor.dom;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Pastes the specified HTML. This means that the HTML is filtered and then
+ * inserted at the current selection in the editor. It will also fire paste events
+ * for custom user filtering.
+ *
+ * @param {String} html HTML code to paste into the current selection.
+ * @param {Boolean?} internalFlag Optional true/false flag if the contents is internal or external.
+ */
+ function pasteHtml(html, internalFlag) {
+ var args, dom = editor.dom, internal;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args = editor.fire('BeforePastePreProcess', {content: html}); // Internal event used by Quirks
- args = editor.fire('PastePreProcess', args);
- html = args.content;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ internal = internalFlag || InternalHtml.isMarked(html);
+ html = InternalHtml.unmark(html);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!args.isDefaultPrevented()) {
- // User has bound PastePostProcess events then we need to pass it through a DOM node
- // This is not ideal but we don't want to let the browser mess up the HTML for example
- // some browsers add to P tags etc
- if (editor.hasEventListeners('PastePostProcess') && !args.isDefaultPrevented()) {
- // We need to attach the element to the DOM so Sizzle selectors work on the contents
- var tempBody = dom.add(editor.getBody(), 'div', {style: 'display:none'}, html);
- args = editor.fire('PastePostProcess', {node: tempBody});
- dom.remove(tempBody);
- html = args.node.innerHTML;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args = editor.fire('BeforePastePreProcess', { content: html, internal: internal }); // Internal event used by Quirks
+ args = editor.fire('PastePreProcess', args);
+ html = args.content;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!args.isDefaultPrevented()) {
- SmartPaste.insertContent(editor, html);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!args.isDefaultPrevented()) {
+ // User has bound PastePostProcess events then we need to pass it through a DOM node
+ // This is not ideal but we don't want to let the browser mess up the HTML for example
+ // some browsers add to P tags etc
+ if (editor.hasEventListeners('PastePostProcess') && !args.isDefaultPrevented()) {
+ // We need to attach the element to the DOM so Sizzle selectors work on the contents
+ var tempBody = dom.add(editor.getBody(), 'div', { style: 'display:none' }, html);
+ args = editor.fire('PastePostProcess', { node: tempBody, internal: internal });
+ dom.remove(tempBody);
+ html = args.node.innerHTML;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Pastes the specified text. This means that the plain text is processed
- * and converted into BR and P elements. It will fire paste events for custom filtering.
- *
- * @param {String} text Text to paste as the current selection location.
- */
- function pasteText(text) {
- text = editor.dom.encode(text).replace(/\r\n/g, '\n');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!args.isDefaultPrevented()) {
+ SmartPaste.insertContent(editor, html);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var startBlock = editor.dom.getParent(editor.selection.getStart(), editor.dom.isBlock);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Pastes the specified text. This means that the plain text is processed
+ * and converted into BR and P elements. It will fire paste events for custom filtering.
+ *
+ * @param {String} text Text to paste as the current selection location.
+ */
+ function pasteText(text) {
+ text = editor.dom.encode(text).replace(/\r\n/g, '\n');
+ text = Newlines.convert(text, editor.settings.forced_root_block, editor.settings.forced_root_block_attrs);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Create start block html for example <p attr="value">
- var forcedRootBlockName = editor.settings.forced_root_block;
- var forcedRootBlockStartHtml;
- if (forcedRootBlockName) {
- forcedRootBlockStartHtml = editor.dom.createHTML(forcedRootBlockName, editor.settings.forced_root_block_attrs);
- forcedRootBlockStartHtml = forcedRootBlockStartHtml.substr(0, forcedRootBlockStartHtml.length - 3) + '>';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ pasteHtml(text, false);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ((startBlock && /^(PRE|DIV)$/.test(startBlock.nodeName)) || !forcedRootBlockName) {
- text = Utils.filter(text, [
- [/\n/g, "<br>"]
- ]);
- } else {
- text = Utils.filter(text, [
- [/\n\n/g, "</p>" + forcedRootBlockStartHtml],
- [/^(.*<\/p>)(<p>)$/, forcedRootBlockStartHtml + '$1'],
- [/\n/g, "<br />"]
- ]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates a paste bin element as close as possible to the current caret location and places the focus inside that element
+ * so that when the real paste event occurs the contents gets inserted into this element
+ * instead of the current editor selection element.
+ */
+ function createPasteBin() {
+ var dom = editor.dom, body = editor.getBody();
+ var viewport = editor.dom.getViewPort(editor.getWin()), scrollTop = viewport.y, top = 20;
+ var scrollContainer;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (text.indexOf('<p>') != -1) {
- text = forcedRootBlockStartHtml + text;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ lastRng = editor.selection.getRng();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- pasteHtml(text);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.inline) {
+ scrollContainer = editor.selection.getScrollContainer();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates a paste bin element as close as possible to the current caret location and places the focus inside that element
- * so that when the real paste event occurs the contents gets inserted into this element
- * instead of the current editor selection element.
- */
- function createPasteBin() {
- var dom = editor.dom, body = editor.getBody();
- var viewport = editor.dom.getViewPort(editor.getWin()), scrollTop = viewport.y, top = 20;
- var scrollContainer;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Can't always rely on scrollTop returning a useful value.
+ // It returns 0 if the browser doesn't support scrollTop for the element or is non-scrollable
+ if (scrollContainer && scrollContainer.scrollTop > 0) {
+ scrollTop = scrollContainer.scrollTop;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- lastRng = editor.selection.getRng();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the rect of the current caret if the caret is in an empty block before a
+ * BR we insert a temporary invisible character that we get the rect this way we always get a proper rect.
+ *
+ * TODO: This might be useful in core.
+ */
+ function getCaretRect(rng) {
+ var rects, textNode, node, container = rng.startContainer;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.inline) {
- scrollContainer = editor.selection.getScrollContainer();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rects = rng.getClientRects();
+ if (rects.length) {
+ return rects[0];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Can't always rely on scrollTop returning a useful value.
- // It returns 0 if the browser doesn't support scrollTop for the element or is non-scrollable
- if (scrollContainer && scrollContainer.scrollTop > 0) {
- scrollTop = scrollContainer.scrollTop;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!rng.collapsed || container.nodeType != 1) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the rect of the current caret if the caret is in an empty block before a
- * BR we insert a temporary invisible character that we get the rect this way we always get a proper rect.
- *
- * TODO: This might be useful in core.
- */
- function getCaretRect(rng) {
- var rects, textNode, node, container = rng.startContainer;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = container.childNodes[lastRng.startOffset];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rects = rng.getClientRects();
- if (rects.length) {
- return rects[0];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Skip empty whitespace nodes
+ while (node && node.nodeType == 3 && !node.data.length) {
+ node = node.nextSibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!rng.collapsed || container.nodeType != 1) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!node) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = container.childNodes[lastRng.startOffset];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if the location is |<br>
+ // TODO: Might need to expand this to say |<table>
+ if (node.tagName == 'BR') {
+ textNode = dom.doc.createTextNode('\uFEFF');
+ node.parentNode.insertBefore(textNode, node);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Skip empty whitespace nodes
- while (node && node.nodeType == 3 && !node.data.length) {
- node = node.nextSibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng = dom.createRng();
+ rng.setStartBefore(textNode);
+ rng.setEndAfter(textNode);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!node) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rects = rng.getClientRects();
+ dom.remove(textNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if the location is |<br>
- // TODO: Might need to expand this to say |<table>
- if (node.tagName == 'BR') {
- textNode = dom.doc.createTextNode('\uFEFF');
- node.parentNode.insertBefore(textNode, node);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rects.length) {
+ return rects[0];
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng = dom.createRng();
- rng.setStartBefore(textNode);
- rng.setEndAfter(textNode);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Calculate top cordinate this is needed to avoid scrolling to top of document
+ // We want the paste bin to be as close to the caret as possible to avoid scrolling
+ if (lastRng.getClientRects) {
+ var rect = getCaretRect(lastRng);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rects = rng.getClientRects();
- dom.remove(textNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rect) {
+ // Client rects gets us closes to the actual
+ // caret location in for example a wrapped paragraph block
+ top = scrollTop + (rect.top - dom.getPos(body).y);
+ } else {
+ top = scrollTop;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rects.length) {
- return rects[0];
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if we can find a closer location by checking the range element
+ var container = lastRng.startContainer;
+ if (container) {
+ if (container.nodeType == 3 && container.parentNode != body) {
+ container = container.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Calculate top cordinate this is needed to avoid scrolling to top of document
- // We want the paste bin to be as close to the caret as possible to avoid scrolling
- if (lastRng.getClientRects) {
- var rect = getCaretRect(lastRng);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (container.nodeType == 1) {
+ top = dom.getPos(container, scrollContainer || body).y;
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rect) {
- // Client rects gets us closes to the actual
- // caret location in for example a wrapped paragraph block
- top = scrollTop + (rect.top - dom.getPos(body).y);
- } else {
- top = scrollTop;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Create a pastebin
+ pasteBinElm = dom.add(editor.getBody(), 'div', {
+ id: "mcepastebin",
+ contentEditable: true,
+ "data-mce-bogus": "all",
+ style: 'position: absolute; top: ' + top + 'px;' +
+ 'width: 10px; height: 10px; overflow: hidden; opacity: 0'
+ }, pasteBinDefaultContent);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if we can find a closer location by checking the range element
- var container = lastRng.startContainer;
- if (container) {
- if (container.nodeType == 3 && container.parentNode != body) {
- container = container.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move paste bin out of sight since the controlSelection rect gets displayed otherwise on IE and Gecko
+ if (Env.ie || Env.gecko) {
+ dom.setStyle(pasteBinElm, 'left', dom.getStyle(body, 'direction', true) == 'rtl' ? 0xFFFF : -0xFFFF);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (container.nodeType == 1) {
- top = dom.getPos(container, scrollContainer || body).y;
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Prevent focus events from bubbeling fixed FocusManager issues
+ dom.bind(pasteBinElm, 'beforedeactivate focusin focusout', function (e) {
+ e.stopPropagation();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Create a pastebin
- pasteBinElm = dom.add(editor.getBody(), 'div', {
- id: "mcepastebin",
- contentEditable: true,
- "data-mce-bogus": "all",
- style: 'position: absolute; top: ' + top + 'px;' +
- 'width: 10px; height: 10px; overflow: hidden; opacity: 0'
- }, pasteBinDefaultContent);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ pasteBinElm.focus();
+ editor.selection.select(pasteBinElm, true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move paste bin out of sight since the controlSelection rect gets displayed otherwise on IE and Gecko
- if (Env.ie || Env.gecko) {
- dom.setStyle(pasteBinElm, 'left', dom.getStyle(body, 'direction', true) == 'rtl' ? 0xFFFF : -0xFFFF);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes the paste bin if it exists.
+ */
+ function removePasteBin() {
+ if (pasteBinElm) {
+ var pasteBinClone;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Prevent focus events from bubbeling fixed FocusManager issues
- dom.bind(pasteBinElm, 'beforedeactivate focusin focusout', function(e) {
- e.stopPropagation();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // WebKit/Blink might clone the div so
+ // lets make sure we remove all clones
+ // TODO: Man o man is this ugly. WebKit is the new IE! Remove this if they ever fix it!
+ while ((pasteBinClone = editor.dom.get('mcepastebin'))) {
+ editor.dom.remove(pasteBinClone);
+ editor.dom.unbind(pasteBinClone);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- pasteBinElm.focus();
- editor.selection.select(pasteBinElm, true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (lastRng) {
+ editor.selection.setRng(lastRng);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes the paste bin if it exists.
- */
- function removePasteBin() {
- if (pasteBinElm) {
- var pasteBinClone;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ pasteBinElm = lastRng = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // WebKit/Blink might clone the div so
- // lets make sure we remove all clones
- // TODO: Man o man is this ugly. WebKit is the new IE! Remove this if they ever fix it!
- while ((pasteBinClone = editor.dom.get('mcepastebin'))) {
- editor.dom.remove(pasteBinClone);
- editor.dom.unbind(pasteBinClone);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the contents of the paste bin as a HTML string.
+ *
+ * @return {String} Get the contents of the paste bin.
+ */
+ function getPasteBinHtml() {
+ var html = '', pasteBinClones, i, clone, cloneHtml;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (lastRng) {
- editor.selection.setRng(lastRng);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Since WebKit/Chrome might clone the paste bin when pasting
+ // for example: <img style="float: right"> we need to check if any of them contains some useful html.
+ // TODO: Man o man is this ugly. WebKit is the new IE! Remove this if they ever fix it!
+ pasteBinClones = editor.dom.select('div[id=mcepastebin]');
+ for (i = 0; i < pasteBinClones.length; i++) {
+ clone = pasteBinClones[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- pasteBinElm = lastRng = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Pasting plain text produces pastebins in pastebinds makes sence right!?
+ if (clone.firstChild && clone.firstChild.id == 'mcepastebin') {
+ clone = clone.firstChild;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the contents of the paste bin as a HTML string.
- *
- * @return {String} Get the contents of the paste bin.
- */
- function getPasteBinHtml() {
- var html = '', pasteBinClones, i, clone, cloneHtml;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ cloneHtml = clone.innerHTML;
+ if (html != pasteBinDefaultContent) {
+ html += cloneHtml;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Since WebKit/Chrome might clone the paste bin when pasting
- // for example: <img style="float: right"> we need to check if any of them contains some useful html.
- // TODO: Man o man is this ugly. WebKit is the new IE! Remove this if they ever fix it!
- pasteBinClones = editor.dom.select('div[id=mcepastebin]');
- for (i = 0; i < pasteBinClones.length; i++) {
- clone = pasteBinClones[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return html;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Pasting plain text produces pastebins in pastebinds makes sence right!?
- if (clone.firstChild && clone.firstChild.id == 'mcepastebin') {
- clone = clone.firstChild;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Gets various content types out of a datatransfer object.
+ *
+ * @param {DataTransfer} dataTransfer Event fired on paste.
+ * @return {Object} Object with mime types and data for those mime types.
+ */
+ function getDataTransferItems(dataTransfer) {
+ var items = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- cloneHtml = clone.innerHTML;
- if (html != pasteBinDefaultContent) {
- html += cloneHtml;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (dataTransfer) {
+ // Use old WebKit/IE API
+ if (dataTransfer.getData) {
+ var legacyText = dataTransfer.getData('Text');
+ if (legacyText && legacyText.length > 0) {
+ if (legacyText.indexOf(mceInternalUrlPrefix) == -1) {
+ items['text/plain'] = legacyText;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return html;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (dataTransfer.types) {
+ for (var i = 0; i < dataTransfer.types.length; i++) {
+ var contentType = dataTransfer.types[i];
+ items[contentType] = dataTransfer.getData(contentType);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Gets various content types out of a datatransfer object.
- *
- * @param {DataTransfer} dataTransfer Event fired on paste.
- * @return {Object} Object with mime types and data for those mime types.
- */
- function getDataTransferItems(dataTransfer) {
- var items = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return items;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (dataTransfer) {
- // Use old WebKit/IE API
- if (dataTransfer.getData) {
- var legacyText = dataTransfer.getData('Text');
- if (legacyText && legacyText.length > 0) {
- if (legacyText.indexOf(mceInternalUrlPrefix) == -1) {
- items['text/plain'] = legacyText;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Gets various content types out of the Clipboard API. It will also get the
+ * plain text using older IE and WebKit API:s.
+ *
+ * @param {ClipboardEvent} clipboardEvent Event fired on paste.
+ * @return {Object} Object with mime types and data for those mime types.
+ */
+ function getClipboardContent(clipboardEvent) {
+ var content = getDataTransferItems(clipboardEvent.clipboardData || editor.getDoc().dataTransfer);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (dataTransfer.types) {
- for (var i = 0; i < dataTransfer.types.length; i++) {
- var contentType = dataTransfer.types[i];
- items[contentType] = dataTransfer.getData(contentType);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Edge 15 has a broken HTML Clipboard API see https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/11877517/
+ return Utils.isMsEdge() ? Tools.extend(content, { 'text/html': '' }) : content;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return items;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hasHtmlOrText(content) {
+ return hasContentType(content, 'text/html') || hasContentType(content, 'text/plain');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Gets various content types out of the Clipboard API. It will also get the
- * plain text using older IE and WebKit API:s.
- *
- * @param {ClipboardEvent} clipboardEvent Event fired on paste.
- * @return {Object} Object with mime types and data for those mime types.
- */
- function getClipboardContent(clipboardEvent) {
- return getDataTransferItems(clipboardEvent.clipboardData || editor.getDoc().dataTransfer);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getBase64FromUri(uri) {
+ var idx;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hasHtmlOrText(content) {
- return hasContentType(content, 'text/html') || hasContentType(content, 'text/plain');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ idx = uri.indexOf(',');
+ if (idx !== -1) {
+ return uri.substr(idx + 1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getBase64FromUri(uri) {
- var idx;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- idx = uri.indexOf(',');
- if (idx !== -1) {
- return uri.substr(idx + 1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isValidDataUriImage(settings, imgElm) {
+ return settings.images_dataimg_filter ? settings.images_dataimg_filter(imgElm) : true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function pasteImage(rng, reader, blob) {
+ if (rng) {
+ editor.selection.setRng(rng);
+ rng = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isValidDataUriImage(settings, imgElm) {
- return settings.images_dataimg_filter ? settings.images_dataimg_filter(imgElm) : true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var dataUri = reader.result;
+ var base64 = getBase64FromUri(dataUri);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function pasteImage(rng, reader, blob) {
- if (rng) {
- editor.selection.setRng(rng);
- rng = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var img = new Image();
+ img.src = dataUri;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var dataUri = reader.result;
- var base64 = getBase64FromUri(dataUri);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // TODO: Move the bulk of the cache logic to EditorUpload
+ if (isValidDataUriImage(editor.settings, img)) {
+ var blobCache = editor.editorUpload.blobCache;
+ var blobInfo, existingBlobInfo;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var img = new Image();
- img.src = dataUri;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ existingBlobInfo = blobCache.findFirst(function (cachedBlobInfo) {
+ return cachedBlobInfo.base64() === base64;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // TODO: Move the bulk of the cache logic to EditorUpload
- if (isValidDataUriImage(editor.settings, img)) {
- var blobCache = editor.editorUpload.blobCache;
- var blobInfo, existingBlobInfo;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!existingBlobInfo) {
+ blobInfo = blobCache.create(uniqueId(), blob, base64);
+ blobCache.add(blobInfo);
+ } else {
+ blobInfo = existingBlobInfo;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- existingBlobInfo = blobCache.findFirst(function(cachedBlobInfo) {
- return cachedBlobInfo.base64() === base64;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ pasteHtml('<img src="' + blobInfo.blobUri() + '">', false);
+ } else {
+ pasteHtml('<img src="' + dataUri + '">', false);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!existingBlobInfo) {
- blobInfo = blobCache.create(uniqueId(), blob, base64);
- blobCache.add(blobInfo);
- } else {
- blobInfo = existingBlobInfo;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Checks if the clipboard contains image data if it does it will take that data
+ * and convert it into a data url image and paste that image at the caret location.
+ *
+ * @param {ClipboardEvent} e Paste/drop event object.
+ * @param {DOMRange} rng Rng object to move selection to.
+ * @return {Boolean} true/false if the image data was found or not.
+ */
+ function pasteImageData(e, rng) {
+ var dataTransfer = e.clipboardData || e.dataTransfer;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- pasteHtml('<img src="' + blobInfo.blobUri() + '">');
- } else {
- pasteHtml('<img src="' + dataUri + '">');
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function processItems(items) {
+ var i, item, reader, hadImage = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Checks if the clipboard contains image data if it does it will take that data
- * and convert it into a data url image and paste that image at the caret location.
- *
- * @param {ClipboardEvent} e Paste/drop event object.
- * @param {DOMRange} rng Rng object to move selection to.
- * @return {Boolean} true/false if the image data was found or not.
- */
- function pasteImageData(e, rng) {
- var dataTransfer = e.clipboardData || e.dataTransfer;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (items) {
+ for (i = 0; i < items.length; i++) {
+ item = items[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function processItems(items) {
- var i, item, reader, hadImage = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (/^image\/(jpeg|png|gif|bmp)$/.test(item.type)) {
+ var blob = item.getAsFile ? item.getAsFile() : item;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (items) {
- for (i = 0; i < items.length; i++) {
- item = items[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ reader = new FileReader();
+ reader.onload = pasteImage.bind(null, rng, reader, blob);
+ reader.readAsDataURL(blob);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (/^image\/(jpeg|png|gif|bmp)$/.test(item.type)) {
- var blob = item.getAsFile ? item.getAsFile() : item;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ e.preventDefault();
+ hadImage = true;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- reader = new FileReader();
- reader.onload = pasteImage.bind(null, rng, reader, blob);
- reader.readAsDataURL(blob);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return hadImage;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- e.preventDefault();
- hadImage = true;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.settings.paste_data_images && dataTransfer) {
+ return processItems(dataTransfer.items) || processItems(dataTransfer.files);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return hadImage;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Chrome on Android doesn't support proper clipboard access so we have no choice but to allow the browser default behavior.
+ *
+ * @param {Event} e Paste event object to check if it contains any data.
+ * @return {Boolean} true/false if the clipboard is empty or not.
+ */
+ function isBrokenAndroidClipboardEvent(e) {
+ var clipboardData = e.clipboardData;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.settings.paste_data_images && dataTransfer) {
- return processItems(dataTransfer.items) || processItems(dataTransfer.files);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return navigator.userAgent.indexOf('Android') != -1 && clipboardData && clipboardData.items && clipboardData.items.length === 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Chrome on Android doesn't support proper clipboard access so we have no choice but to allow the browser default behavior.
- *
- * @param {Event} e Paste event object to check if it contains any data.
- * @return {Boolean} true/false if the clipboard is empty or not.
- */
- function isBrokenAndroidClipboardEvent(e) {
- var clipboardData = e.clipboardData;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getCaretRangeFromEvent(e) {
+ return RangeUtils.getCaretRangeFromPoint(e.clientX, e.clientY, editor.getDoc());
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return navigator.userAgent.indexOf('Android') != -1 && clipboardData && clipboardData.items && clipboardData.items.length === 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hasContentType(clipboardContent, mimeType) {
+ return mimeType in clipboardContent && clipboardContent[mimeType].length > 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getCaretRangeFromEvent(e) {
- return RangeUtils.getCaretRangeFromPoint(e.clientX, e.clientY, editor.getDoc());
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isKeyboardPasteEvent(e) {
+ return (VK.metaKeyPressed(e) && e.keyCode == 86) || (e.shiftKey && e.keyCode == 45);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hasContentType(clipboardContent, mimeType) {
- return mimeType in clipboardContent && clipboardContent[mimeType].length > 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function registerEventHandlers() {
+ editor.on('keydown', function (e) {
+ function removePasteBinOnKeyUp(e) {
+ // Ctrl+V or Shift+Insert
+ if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) {
+ removePasteBin();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isKeyboardPasteEvent(e) {
- return (VK.metaKeyPressed(e) && e.keyCode == 86) || (e.shiftKey && e.keyCode == 45);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Ctrl+V or Shift+Insert
+ if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) {
+ keyboardPastePlainTextState = e.shiftKey && e.keyCode == 86;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function registerEventHandlers() {
- editor.on('keydown', function(e) {
- function removePasteBinOnKeyUp(e) {
- // Ctrl+V or Shift+Insert
- if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) {
- removePasteBin();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Edge case on Safari on Mac where it doesn't handle Cmd+Shift+V correctly
+ // it fires the keydown but no paste or keyup so we are left with a paste bin
+ if (keyboardPastePlainTextState && Env.webkit && navigator.userAgent.indexOf('Version/') != -1) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Ctrl+V or Shift+Insert
- if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) {
- keyboardPastePlainTextState = e.shiftKey && e.keyCode == 86;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Prevent undoManager keydown handler from making an undo level with the pastebin in it
+ e.stopImmediatePropagation();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Edge case on Safari on Mac where it doesn't handle Cmd+Shift+V correctly
- // it fires the keydown but no paste or keyup so we are left with a paste bin
- if (keyboardPastePlainTextState && Env.webkit && navigator.userAgent.indexOf('Version/') != -1) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ keyboardPasteTimeStamp = new Date().getTime();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Prevent undoManager keydown handler from making an undo level with the pastebin in it
- e.stopImmediatePropagation();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // IE doesn't support Ctrl+Shift+V and it doesn't even produce a paste event
+ // so lets fake a paste event and let IE use the execCommand/dataTransfer methods
+ if (Env.ie && keyboardPastePlainTextState) {
+ e.preventDefault();
+ editor.fire('paste', { ieFake: true });
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- keyboardPasteTimeStamp = new Date().getTime();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ removePasteBin();
+ createPasteBin();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // IE doesn't support Ctrl+Shift+V and it doesn't even produce a paste event
- // so lets fake a paste event and let IE use the execCommand/dataTransfer methods
- if (Env.ie && keyboardPastePlainTextState) {
- e.preventDefault();
- editor.fire('paste', {ieFake: true});
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove pastebin if we get a keyup and no paste event
+ // For example pasting a file in IE 11 will not produce a paste event
+ editor.once('keyup', removePasteBinOnKeyUp);
+ editor.once('paste', function () {
+ editor.off('keyup', removePasteBinOnKeyUp);
+ });
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- removePasteBin();
- createPasteBin();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal) {
+ var content, isPlainTextHtml;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove pastebin if we get a keyup and no paste event
- // For example pasting a file in IE 11 will not produce a paste event
- editor.once('keyup', removePasteBinOnKeyUp);
- editor.once('paste', function() {
- editor.off('keyup', removePasteBinOnKeyUp);
- });
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Grab HTML from Clipboard API or paste bin as a fallback
+ if (hasContentType(clipboardContent, 'text/html')) {
+ content = clipboardContent['text/html'];
+ } else {
+ content = getPasteBinHtml();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode) {
- var content;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If paste bin is empty try using plain text mode
+ // since that is better than nothing right
+ if (content == pasteBinDefaultContent) {
+ plainTextMode = true;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Grab HTML from Clipboard API or paste bin as a fallback
- if (hasContentType(clipboardContent, 'text/html')) {
- content = clipboardContent['text/html'];
- } else {
- content = getPasteBinHtml();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ content = Utils.trimHtml(content);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If paste bin is empty try using plain text mode
- // since that is better than nothing right
- if (content == pasteBinDefaultContent) {
- plainTextMode = true;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // WebKit has a nice bug where it clones the paste bin if you paste from for example notepad
+ // so we need to force plain text mode in this case
+ if (pasteBinElm && pasteBinElm.firstChild && pasteBinElm.firstChild.id === 'mcepastebin') {
+ plainTextMode = true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- content = Utils.trimHtml(content);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ removePasteBin();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // WebKit has a nice bug where it clones the paste bin if you paste from for example notepad
- // so we need to force plain text mode in this case
- if (pasteBinElm && pasteBinElm.firstChild && pasteBinElm.firstChild.id === 'mcepastebin') {
- plainTextMode = true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ isPlainTextHtml = internal === false && Newlines.isPlainText(content);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- removePasteBin();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If we got nothing from clipboard API and pastebin or the content is a plain text (with only
+ // some BRs, Ps or DIVs as newlines) then we fallback to plain/text
+ if (!content.length || isPlainTextHtml) {
+ plainTextMode = true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If we got nothing from clipboard API and pastebin then we could try the last resort: plain/text
- if (!content.length) {
- plainTextMode = true;
- }
</del><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Grab plain text from Clipboard API or convert existing HTML to plain text
- if (plainTextMode) {
- // Use plain text contents from Clipboard API unless the HTML contains paragraphs then
- // we should convert the HTML to plain text since works better when pasting HTML/Word contents as plain text
- if (hasContentType(clipboardContent, 'text/plain') && content.indexOf('</p>') == -1) {
- content = clipboardContent['text/plain'];
- } else {
- content = Utils.innerText(content);
- }
- }
</del><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If the content is the paste bin default HTML then it was
- // impossible to get the cliboard data out.
- if (content == pasteBinDefaultContent) {
- if (!isKeyBoardPaste) {
- editor.windowManager.alert('Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents.');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Grab plain text from Clipboard API or convert existing HTML to plain text
+ if (plainTextMode) {
+ // Use plain text contents from Clipboard API unless the HTML contains paragraphs then
+ // we should convert the HTML to plain text since works better when pasting HTML/Word contents as plain text
+ if (hasContentType(clipboardContent, 'text/plain') && isPlainTextHtml) {
+ content = clipboardContent['text/plain'];
+ } else {
+ content = Utils.innerText(content);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If the content is the paste bin default HTML then it was
+ // impossible to get the cliboard data out.
+ if (content == pasteBinDefaultContent) {
+ if (!isKeyBoardPaste) {
+ editor.windowManager.alert('Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents.');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (plainTextMode) {
- pasteText(content);
- } else {
- pasteHtml(content);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getLastRng = function() {
- return lastRng || editor.selection.getRng();
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (plainTextMode) {
+ pasteText(content);
+ } else {
+ pasteHtml(content, internal);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('paste', function(e) {
- // Getting content from the Clipboard can take some time
- var clipboardTimer = new Date().getTime();
- var clipboardContent = getClipboardContent(e);
- var clipboardDelay = new Date().getTime() - clipboardTimer;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getLastRng = function () {
+ return lastRng || editor.selection.getRng();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isKeyBoardPaste = (new Date().getTime() - keyboardPasteTimeStamp - clipboardDelay) < 1000;
- var plainTextMode = self.pasteFormat == "text" || keyboardPastePlainTextState;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('paste', function (e) {
+ // Getting content from the Clipboard can take some time
+ var clipboardTimer = new Date().getTime();
+ var clipboardContent = getClipboardContent(e);
+ var clipboardDelay = new Date().getTime() - clipboardTimer;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- keyboardPastePlainTextState = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isKeyBoardPaste = (new Date().getTime() - keyboardPasteTimeStamp - clipboardDelay) < 1000;
+ var plainTextMode = self.pasteFormat == "text" || keyboardPastePlainTextState;
+ var internal = hasContentType(clipboardContent, InternalHtml.internalHtmlMime());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.isDefaultPrevented() || isBrokenAndroidClipboardEvent(e)) {
- removePasteBin();
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ keyboardPastePlainTextState = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!hasHtmlOrText(clipboardContent) && pasteImageData(e, getLastRng())) {
- removePasteBin();
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.isDefaultPrevented() || isBrokenAndroidClipboardEvent(e)) {
+ removePasteBin();
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Not a keyboard paste prevent default paste and try to grab the clipboard contents using different APIs
- if (!isKeyBoardPaste) {
- e.preventDefault();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!hasHtmlOrText(clipboardContent) && pasteImageData(e, getLastRng())) {
+ removePasteBin();
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Try IE only method if paste isn't a keyboard paste
- if (Env.ie && (!isKeyBoardPaste || e.ieFake)) {
- createPasteBin();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Not a keyboard paste prevent default paste and try to grab the clipboard contents using different APIs
+ if (!isKeyBoardPaste) {
+ e.preventDefault();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.dom.bind(pasteBinElm, 'paste', function(e) {
- e.stopPropagation();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Try IE only method if paste isn't a keyboard paste
+ if (Env.ie && (!isKeyBoardPaste || e.ieFake) && !hasContentType(clipboardContent, 'text/html')) {
+ createPasteBin();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.getDoc().execCommand('Paste', false, null);
- clipboardContent["text/html"] = getPasteBinHtml();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.dom.bind(pasteBinElm, 'paste', function (e) {
+ e.stopPropagation();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If clipboard API has HTML then use that directly
- if (hasContentType(clipboardContent, 'text/html')) {
- e.preventDefault();
- insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode);
- } else {
- Delay.setEditorTimeout(editor, function() {
- insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode);
- }, 0);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.getDoc().execCommand('Paste', false, null);
+ clipboardContent["text/html"] = getPasteBinHtml();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('dragstart dragend', function(e) {
- draggingInternally = e.type == 'dragstart';
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If clipboard API has HTML then use that directly
+ if (hasContentType(clipboardContent, 'text/html')) {
+ e.preventDefault();
+ insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal);
+ } else {
+ Delay.setEditorTimeout(editor, function () {
+ insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal);
+ }, 0);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isPlainTextFileUrl(content) {
- var plainTextContent = content['text/plain'];
- return plainTextContent ? plainTextContent.indexOf('file://') === 0 : false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('dragstart dragend', function (e) {
+ draggingInternally = e.type == 'dragstart';
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('drop', function(e) {
- var dropContent, rng;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isPlainTextFileUrl(content) {
+ var plainTextContent = content['text/plain'];
+ return plainTextContent ? plainTextContent.indexOf('file://') === 0 : false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng = getCaretRangeFromEvent(e);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('drop', function (e) {
+ var dropContent, rng;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.isDefaultPrevented() || draggingInternally) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng = getCaretRangeFromEvent(e);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dropContent = getDataTransferItems(e.dataTransfer);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.isDefaultPrevented() || draggingInternally) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ((!hasHtmlOrText(dropContent) || isPlainTextFileUrl(dropContent)) && pasteImageData(e, rng)) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dropContent = getDataTransferItems(e.dataTransfer);
+ var internal = hasContentType(dropContent, InternalHtml.internalHtmlMime());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rng && editor.settings.paste_filter_drop !== false) {
- var content = dropContent['mce-internal'] || dropContent['text/html'] || dropContent['text/plain'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((!hasHtmlOrText(dropContent) || isPlainTextFileUrl(dropContent)) && pasteImageData(e, rng)) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (content) {
- e.preventDefault();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rng && editor.settings.paste_filter_drop !== false) {
+ var content = dropContent['mce-internal'] || dropContent['text/html'] || dropContent['text/plain'];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // FF 45 doesn't paint a caret when dragging in text in due to focus call by execCommand
- Delay.setEditorTimeout(editor, function() {
- editor.undoManager.transact(function() {
- if (dropContent['mce-internal']) {
- editor.execCommand('Delete');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (content) {
+ e.preventDefault();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.selection.setRng(rng);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // FF 45 doesn't paint a caret when dragging in text in due to focus call by execCommand
+ Delay.setEditorTimeout(editor, function () {
+ editor.undoManager.transact(function () {
+ if (dropContent['mce-internal']) {
+ editor.execCommand('Delete');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- content = Utils.trimHtml(content);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.selection.setRng(rng);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!dropContent['text/html']) {
- pasteText(content);
- } else {
- pasteHtml(content);
- }
- });
- });
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ content = Utils.trimHtml(content);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('dragover dragend', function(e) {
- if (editor.settings.paste_data_images) {
- e.preventDefault();
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!dropContent['text/html']) {
+ pasteText(content);
+ } else {
+ pasteHtml(content, internal);
+ }
+ });
+ });
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.pasteHtml = pasteHtml;
- self.pasteText = pasteText;
- self.pasteImageData = pasteImageData;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('dragover dragend', function (e) {
+ if (editor.settings.paste_data_images) {
+ e.preventDefault();
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('preInit', function() {
- registerEventHandlers();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.pasteHtml = pasteHtml;
+ self.pasteText = pasteText;
+ self.pasteImageData = pasteImageData;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove all data images from paste for example from Gecko
- // except internal images like video elements
- editor.parser.addNodeFilter('img', function(nodes, name, args) {
- function isPasteInsert(args) {
- return args.data && args.data.paste === true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('preInit', function () {
+ registerEventHandlers();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function remove(node) {
- if (!node.attr('data-mce-object') && src !== Env.transparentSrc) {
- node.remove();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove all data images from paste for example from Gecko
+ // except internal images like video elements
+ editor.parser.addNodeFilter('img', function (nodes, name, args) {
+ function isPasteInsert(args) {
+ return args.data && args.data.paste === true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isWebKitFakeUrl(src) {
- return src.indexOf("webkit-fake-url") === 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function remove(node) {
+ if (!node.attr('data-mce-object') && src !== Env.transparentSrc) {
+ node.remove();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isDataUri(src) {
- return src.indexOf("data:") === 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isWebKitFakeUrl(src) {
+ return src.indexOf("webkit-fake-url") === 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!editor.settings.paste_data_images && isPasteInsert(args)) {
- var i = nodes.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isDataUri(src) {
+ return src.indexOf("data:") === 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- var src = nodes[i].attributes.map.src;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!editor.settings.paste_data_images && isPasteInsert(args)) {
+ var i = nodes.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!src) {
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ var src = nodes[i].attributes.map.src;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Safari on Mac produces webkit-fake-url see: https://bugs.webkit.org/show_bug.cgi?id=49141
- if (isWebKitFakeUrl(src)) {
- remove(nodes[i]);
- } else if (!editor.settings.allow_html_data_urls && isDataUri(src)) {
- remove(nodes[i]);
- }
- }
- }
- });
- });
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!src) {
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/plugins/paste/classes/WordFilter.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Safari on Mac produces webkit-fake-url see: https://bugs.webkit.org/show_bug.cgi?id=49141
+ if (isWebKitFakeUrl(src)) {
+ remove(nodes[i]);
+ } else if (!editor.settings.allow_html_data_urls && isDataUri(src)) {
+ remove(nodes[i]);
+ }
+ }
+ }
+ });
+ });
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.core.html.Serializer',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.html.Serializer');
+ }
+);
+
+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.core.html.Node',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.html.Node');
+ }
+);
+
+/**
</ins><span class="cx" style="display: block; padding: 0 10px"> * WordFilter.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1061,493 +1528,495 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.pasteplugin.WordFilter
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/pasteplugin/WordFilter", [
- "tinymce/util/Tools",
- "tinymce/html/DomParser",
- "tinymce/html/Schema",
- "tinymce/html/Serializer",
- "tinymce/html/Node",
- "tinymce/pasteplugin/Utils"
-], function(Tools, DomParser, Schema, Serializer, Node, Utils) {
- /**
- * Checks if the specified content is from any of the following sources: MS Word/Office 365/Google docs.
- */
- function isWordContent(content) {
- return (
- (/<font face="Times New Roman"|class="?Mso|style="[^"]*\bmso-|style='[^'']*\bmso-|w:WordDocument/i).test(content) ||
- (/class="OutlineElement/).test(content) ||
- (/id="?docs\-internal\-guid\-/.test(content))
- );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.paste.core.WordFilter',
+ [
+ 'tinymce.core.util.Tools',
+ 'tinymce.core.html.DomParser',
+ 'tinymce.core.html.Schema',
+ 'tinymce.core.html.Serializer',
+ 'tinymce.core.html.Node',
+ 'tinymce.plugins.paste.core.Utils'
+ ],
+ function (Tools, DomParser, Schema, Serializer, Node, Utils) {
+ /**
+ * Checks if the specified content is from any of the following sources: MS Word/Office 365/Google docs.
+ */
+ function isWordContent(content) {
+ return (
+ (/<font face="Times New Roman"|class="?Mso|style="[^"]*\bmso-|style='[^'']*\bmso-|w:WordDocument/i).test(content) ||
+ (/class="OutlineElement/).test(content) ||
+ (/id="?docs\-internal\-guid\-/.test(content))
+ );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Checks if the specified text starts with "1. " or "a. " etc.
- */
- function isNumericList(text) {
- var found, patterns;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Checks if the specified text starts with "1. " or "a. " etc.
+ */
+ function isNumericList(text) {
+ var found, patterns;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- patterns = [
- /^[IVXLMCD]{1,2}\.[ \u00a0]/, // Roman upper case
- /^[ivxlmcd]{1,2}\.[ \u00a0]/, // Roman lower case
- /^[a-z]{1,2}[\.\)][ \u00a0]/, // Alphabetical a-z
- /^[A-Z]{1,2}[\.\)][ \u00a0]/, // Alphabetical A-Z
- /^[0-9]+\.[ \u00a0]/, // Numeric lists
- /^[\u3007\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d]+\.[ \u00a0]/, // Japanese
- /^[\u58f1\u5f10\u53c2\u56db\u4f0d\u516d\u4e03\u516b\u4e5d\u62fe]+\.[ \u00a0]/ // Chinese
- ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ patterns = [
+ /^[IVXLMCD]{1,2}\.[ \u00a0]/, // Roman upper case
+ /^[ivxlmcd]{1,2}\.[ \u00a0]/, // Roman lower case
+ /^[a-z]{1,2}[\.\)][ \u00a0]/, // Alphabetical a-z
+ /^[A-Z]{1,2}[\.\)][ \u00a0]/, // Alphabetical A-Z
+ /^[0-9]+\.[ \u00a0]/, // Numeric lists
+ /^[\u3007\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d]+\.[ \u00a0]/, // Japanese
+ /^[\u58f1\u5f10\u53c2\u56db\u4f0d\u516d\u4e03\u516b\u4e5d\u62fe]+\.[ \u00a0]/ // Chinese
+ ];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- text = text.replace(/^[\u00a0 ]+/, '');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ text = text.replace(/^[\u00a0 ]+/, '');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(patterns, function(pattern) {
- if (pattern.test(text)) {
- found = true;
- return false;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(patterns, function (pattern) {
+ if (pattern.test(text)) {
+ found = true;
+ return false;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return found;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return found;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isBulletList(text) {
- return /^[\s\u00a0]*[\u2022\u00b7\u00a7\u25CF]\s*/.test(text);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isBulletList(text) {
+ return /^[\s\u00a0]*[\u2022\u00b7\u00a7\u25CF]\s*/.test(text);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function WordFilter(editor) {
- var settings = editor.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function WordFilter(editor) {
+ var settings = editor.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('BeforePastePreProcess', function(e) {
- var content = e.content, retainStyleProperties, validStyles;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('BeforePastePreProcess', function (e) {
+ var content = e.content, retainStyleProperties, validStyles;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove google docs internal guid markers
- content = content.replace(/<b[^>]+id="?docs-internal-[^>]*>/gi, '');
- content = content.replace(/<br class="?Apple-interchange-newline"?>/gi, '');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove google docs internal guid markers
+ content = content.replace(/<b[^>]+id="?docs-internal-[^>]*>/gi, '');
+ content = content.replace(/<br class="?Apple-interchange-newline"?>/gi, '');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- retainStyleProperties = settings.paste_retain_style_properties;
- if (retainStyleProperties) {
- validStyles = Tools.makeMap(retainStyleProperties.split(/[, ]/));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ retainStyleProperties = settings.paste_retain_style_properties;
+ if (retainStyleProperties) {
+ validStyles = Tools.makeMap(retainStyleProperties.split(/[, ]/));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Converts fake bullet and numbered lists to real semantic OL/UL.
- *
- * @param {tinymce.html.Node} node Root node to convert children of.
- */
- function convertFakeListsToProperLists(node) {
- var currentListNode, prevListNode, lastLevel = 1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Converts fake bullet and numbered lists to real semantic OL/UL.
+ *
+ * @param {tinymce.html.Node} node Root node to convert children of.
+ */
+ function convertFakeListsToProperLists(node) {
+ var currentListNode, prevListNode, lastLevel = 1;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getText(node) {
- var txt = '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getText(node) {
+ var txt = '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.type === 3) {
- return node.value;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.type === 3) {
+ return node.value;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ((node = node.firstChild)) {
- do {
- txt += getText(node);
- } while ((node = node.next));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((node = node.firstChild)) {
+ do {
+ txt += getText(node);
+ } while ((node = node.next));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return txt;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return txt;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function trimListStart(node, regExp) {
- if (node.type === 3) {
- if (regExp.test(node.value)) {
- node.value = node.value.replace(regExp, '');
- return false;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function trimListStart(node, regExp) {
+ if (node.type === 3) {
+ if (regExp.test(node.value)) {
+ node.value = node.value.replace(regExp, '');
+ return false;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ((node = node.firstChild)) {
- do {
- if (!trimListStart(node, regExp)) {
- return false;
- }
- } while ((node = node.next));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((node = node.firstChild)) {
+ do {
+ if (!trimListStart(node, regExp)) {
+ return false;
+ }
+ } while ((node = node.next));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function removeIgnoredNodes(node) {
- if (node._listIgnore) {
- node.remove();
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function removeIgnoredNodes(node) {
+ if (node._listIgnore) {
+ node.remove();
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ((node = node.firstChild)) {
- do {
- removeIgnoredNodes(node);
- } while ((node = node.next));
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((node = node.firstChild)) {
+ do {
+ removeIgnoredNodes(node);
+ } while ((node = node.next));
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function convertParagraphToLi(paragraphNode, listName, start) {
- var level = paragraphNode._listLevel || lastLevel;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function convertParagraphToLi(paragraphNode, listName, start) {
+ var level = paragraphNode._listLevel || lastLevel;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle list nesting
- if (level != lastLevel) {
- if (level < lastLevel) {
- // Move to parent list
- if (currentListNode) {
- currentListNode = currentListNode.parent.parent;
- }
- } else {
- // Create new list
- prevListNode = currentListNode;
- currentListNode = null;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handle list nesting
+ if (level != lastLevel) {
+ if (level < lastLevel) {
+ // Move to parent list
+ if (currentListNode) {
+ currentListNode = currentListNode.parent.parent;
+ }
+ } else {
+ // Create new list
+ prevListNode = currentListNode;
+ currentListNode = null;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!currentListNode || currentListNode.name != listName) {
- prevListNode = prevListNode || currentListNode;
- currentListNode = new Node(listName, 1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!currentListNode || currentListNode.name != listName) {
+ prevListNode = prevListNode || currentListNode;
+ currentListNode = new Node(listName, 1);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (start > 1) {
- currentListNode.attr('start', '' + start);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (start > 1) {
+ currentListNode.attr('start', '' + start);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- paragraphNode.wrap(currentListNode);
- } else {
- currentListNode.append(paragraphNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ paragraphNode.wrap(currentListNode);
+ } else {
+ currentListNode.append(paragraphNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- paragraphNode.name = 'li';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ paragraphNode.name = 'li';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Append list to previous list if it exists
- if (level > lastLevel && prevListNode) {
- prevListNode.lastChild.append(currentListNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Append list to previous list if it exists
+ if (level > lastLevel && prevListNode) {
+ prevListNode.lastChild.append(currentListNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- lastLevel = level;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ lastLevel = level;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove start of list item "1. " or "· " etc
- removeIgnoredNodes(paragraphNode);
- trimListStart(paragraphNode, /^\u00a0+/);
- trimListStart(paragraphNode, /^\s*([\u2022\u00b7\u00a7\u25CF]|\w+\.)/);
- trimListStart(paragraphNode, /^\u00a0+/);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove start of list item "1. " or "· " etc
+ removeIgnoredNodes(paragraphNode);
+ trimListStart(paragraphNode, /^\u00a0+/);
+ trimListStart(paragraphNode, /^\s*([\u2022\u00b7\u00a7\u25CF]|\w+\.)/);
+ trimListStart(paragraphNode, /^\u00a0+/);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Build a list of all root level elements before we start
- // altering them in the loop below.
- var elements = [], child = node.firstChild;
- while (typeof child !== 'undefined' && child !== null) {
- elements.push(child);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Build a list of all root level elements before we start
+ // altering them in the loop below.
+ var elements = [], child = node.firstChild;
+ while (typeof child !== 'undefined' && child !== null) {
+ elements.push(child);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- child = child.walk();
- if (child !== null) {
- while (typeof child !== 'undefined' && child.parent !== node) {
- child = child.walk();
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ child = child.walk();
+ if (child !== null) {
+ while (typeof child !== 'undefined' && child.parent !== node) {
+ child = child.walk();
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var i = 0; i < elements.length; i++) {
- node = elements[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (var i = 0; i < elements.length; i++) {
+ node = elements[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.name == 'p' && node.firstChild) {
- // Find first text node in paragraph
- var nodeText = getText(node);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.name == 'p' && node.firstChild) {
+ // Find first text node in paragraph
+ var nodeText = getText(node);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Detect unordered lists look for bullets
- if (isBulletList(nodeText)) {
- convertParagraphToLi(node, 'ul');
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Detect unordered lists look for bullets
+ if (isBulletList(nodeText)) {
+ convertParagraphToLi(node, 'ul');
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Detect ordered lists 1., a. or ixv.
- if (isNumericList(nodeText)) {
- // Parse OL start number
- var matches = /([0-9]+)\./.exec(nodeText);
- var start = 1;
- if (matches) {
- start = parseInt(matches[1], 10);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Detect ordered lists 1., a. or ixv.
+ if (isNumericList(nodeText)) {
+ // Parse OL start number
+ var matches = /([0-9]+)\./.exec(nodeText);
+ var start = 1;
+ if (matches) {
+ start = parseInt(matches[1], 10);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- convertParagraphToLi(node, 'ol', start);
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ convertParagraphToLi(node, 'ol', start);
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Convert paragraphs marked as lists but doesn't look like anything
- if (node._listLevel) {
- convertParagraphToLi(node, 'ul', 1);
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Convert paragraphs marked as lists but doesn't look like anything
+ if (node._listLevel) {
+ convertParagraphToLi(node, 'ul', 1);
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- currentListNode = null;
- } else {
- // If the root level element isn't a p tag which can be
- // processed by convertParagraphToLi, it interrupts the
- // lists, causing a new list to start instead of having
- // elements from the next list inserted above this tag.
- prevListNode = currentListNode;
- currentListNode = null;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ currentListNode = null;
+ } else {
+ // If the root level element isn't a p tag which can be
+ // processed by convertParagraphToLi, it interrupts the
+ // lists, causing a new list to start instead of having
+ // elements from the next list inserted above this tag.
+ prevListNode = currentListNode;
+ currentListNode = null;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function filterStyles(node, styleValue) {
- var outputStyles = {}, matches, styles = editor.dom.parseStyle(styleValue);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function filterStyles(node, styleValue) {
+ var outputStyles = {}, matches, styles = editor.dom.parseStyle(styleValue);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(styles, function(value, name) {
- // Convert various MS styles to W3C styles
- switch (name) {
- case 'mso-list':
- // Parse out list indent level for lists
- matches = /\w+ \w+([0-9]+)/i.exec(styleValue);
- if (matches) {
- node._listLevel = parseInt(matches[1], 10);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(styles, function (value, name) {
+ // Convert various MS styles to W3C styles
+ switch (name) {
+ case 'mso-list':
+ // Parse out list indent level for lists
+ matches = /\w+ \w+([0-9]+)/i.exec(styleValue);
+ if (matches) {
+ node._listLevel = parseInt(matches[1], 10);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove these nodes <span style="mso-list:Ignore">o</span>
- // Since the span gets removed we mark the text node and the span
- if (/Ignore/i.test(value) && node.firstChild) {
- node._listIgnore = true;
- node.firstChild._listIgnore = true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove these nodes <span style="mso-list:Ignore">o</span>
+ // Since the span gets removed we mark the text node and the span
+ if (/Ignore/i.test(value) && node.firstChild) {
+ node._listIgnore = true;
+ node.firstChild._listIgnore = true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case "horiz-align":
- name = "text-align";
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case "horiz-align":
+ name = "text-align";
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case "vert-align":
- name = "vertical-align";
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case "vert-align":
+ name = "vertical-align";
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case "font-color":
- case "mso-foreground":
- name = "color";
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case "font-color":
+ case "mso-foreground":
+ name = "color";
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case "mso-background":
- case "mso-highlight":
- name = "background";
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case "mso-background":
+ case "mso-highlight":
+ name = "background";
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case "font-weight":
- case "font-style":
- if (value != "normal") {
- outputStyles[name] = value;
- }
- return;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case "font-weight":
+ case "font-style":
+ if (value != "normal") {
+ outputStyles[name] = value;
+ }
+ return;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case "mso-element":
- // Remove track changes code
- if (/^(comment|comment-list)$/i.test(value)) {
- node.remove();
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case "mso-element":
+ // Remove track changes code
+ if (/^(comment|comment-list)$/i.test(value)) {
+ node.remove();
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name.indexOf('mso-comment') === 0) {
- node.remove();
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name.indexOf('mso-comment') === 0) {
+ node.remove();
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Never allow mso- prefixed names
- if (name.indexOf('mso-') === 0) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Never allow mso- prefixed names
+ if (name.indexOf('mso-') === 0) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Output only valid styles
- if (retainStyleProperties == "all" || (validStyles && validStyles[name])) {
- outputStyles[name] = value;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Output only valid styles
+ if (retainStyleProperties == "all" || (validStyles && validStyles[name])) {
+ outputStyles[name] = value;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Convert bold style to "b" element
- if (/(bold)/i.test(outputStyles["font-weight"])) {
- delete outputStyles["font-weight"];
- node.wrap(new Node("b", 1));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Convert bold style to "b" element
+ if (/(bold)/i.test(outputStyles["font-weight"])) {
+ delete outputStyles["font-weight"];
+ node.wrap(new Node("b", 1));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Convert italic style to "i" element
- if (/(italic)/i.test(outputStyles["font-style"])) {
- delete outputStyles["font-style"];
- node.wrap(new Node("i", 1));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Convert italic style to "i" element
+ if (/(italic)/i.test(outputStyles["font-style"])) {
+ delete outputStyles["font-style"];
+ node.wrap(new Node("i", 1));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Serialize the styles and see if there is something left to keep
- outputStyles = editor.dom.serializeStyle(outputStyles, node.name);
- if (outputStyles) {
- return outputStyles;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Serialize the styles and see if there is something left to keep
+ outputStyles = editor.dom.serializeStyle(outputStyles, node.name);
+ if (outputStyles) {
+ return outputStyles;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.paste_enable_default_filters === false) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.paste_enable_default_filters === false) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Detect is the contents is Word junk HTML
- if (isWordContent(e.content)) {
- e.wordContent = true; // Mark it for other processors
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Detect is the contents is Word junk HTML
+ if (isWordContent(e.content)) {
+ e.wordContent = true; // Mark it for other processors
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove basic Word junk
- content = Utils.filter(content, [
- // Word comments like conditional comments etc
- /<!--[\s\S]+?-->/gi,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove basic Word junk
+ content = Utils.filter(content, [
+ // Word comments like conditional comments etc
+ /<!--[\s\S]+?-->/gi,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove comments, scripts (e.g., msoShowComment), XML tag, VML content,
- // MS Office namespaced tags, and a few other tags
- /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove comments, scripts (e.g., msoShowComment), XML tag, VML content,
+ // MS Office namespaced tags, and a few other tags
+ /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Convert <s> into <strike> for line-though
- [/<(\/?)s>/gi, "<$1strike>"],
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Convert <s> into <strike> for line-though
+ [/<(\/?)s>/gi, "<$1strike>"],
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Replace nsbp entites to char since it's easier to handle
- [/ /gi, "\u00a0"],
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Replace nsbp entites to char since it's easier to handle
+ [/ /gi, "\u00a0"],
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Convert <span style="mso-spacerun:yes">___</span> to string of alternating
- // breaking/non-breaking spaces of same length
- [/<span\s+style\s*=\s*"\s*mso-spacerun\s*:\s*yes\s*;?\s*"\s*>([\s\u00a0]*)<\/span>/gi,
- function(str, spaces) {
- return (spaces.length > 0) ?
- spaces.replace(/./, " ").slice(Math.floor(spaces.length / 2)).split("").join("\u00a0") : "";
- }
- ]
- ]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Convert <span style="mso-spacerun:yes">___</span> to string of alternating
+ // breaking/non-breaking spaces of same length
+ [/<span\s+style\s*=\s*"\s*mso-spacerun\s*:\s*yes\s*;?\s*"\s*>([\s\u00a0]*)<\/span>/gi,
+ function (str, spaces) {
+ return (spaces.length > 0) ?
+ spaces.replace(/./, " ").slice(Math.floor(spaces.length / 2)).split("").join("\u00a0") : "";
+ }
+ ]
+ ]);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var validElements = settings.paste_word_valid_elements;
- if (!validElements) {
- validElements = (
- '-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-h1,-h2,-h3,-h4,-h5,-h6,' +
- '-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,' +
- 'td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody'
- );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var validElements = settings.paste_word_valid_elements;
+ if (!validElements) {
+ validElements = (
+ '-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-h1,-h2,-h3,-h4,-h5,-h6,' +
+ '-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,' +
+ 'td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody'
+ );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup strict schema
- var schema = new Schema({
- valid_elements: validElements,
- valid_children: '-li[p]'
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup strict schema
+ var schema = new Schema({
+ valid_elements: validElements,
+ valid_children: '-li[p]'
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add style/class attribute to all element rules since the user might have removed them from
- // paste_word_valid_elements config option and we need to check them for properties
- Tools.each(schema.elements, function(rule) {
- /*eslint dot-notation:0*/
- if (!rule.attributes["class"]) {
- rule.attributes["class"] = {};
- rule.attributesOrder.push("class");
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add style/class attribute to all element rules since the user might have removed them from
+ // paste_word_valid_elements config option and we need to check them for properties
+ Tools.each(schema.elements, function (rule) {
+ /*eslint dot-notation:0*/
+ if (!rule.attributes["class"]) {
+ rule.attributes["class"] = {};
+ rule.attributesOrder.push("class");
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!rule.attributes.style) {
- rule.attributes.style = {};
- rule.attributesOrder.push("style");
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!rule.attributes.style) {
+ rule.attributes.style = {};
+ rule.attributesOrder.push("style");
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Parse HTML into DOM structure
- var domParser = new DomParser({}, schema);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Parse HTML into DOM structure
+ var domParser = new DomParser({}, schema);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Filter styles to remove "mso" specific styles and convert some of them
- domParser.addAttributeFilter('style', function(nodes) {
- var i = nodes.length, node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Filter styles to remove "mso" specific styles and convert some of them
+ domParser.addAttributeFilter('style', function (nodes) {
+ var i = nodes.length, node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i];
- node.attr('style', filterStyles(node, node.attr('style')));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i];
+ node.attr('style', filterStyles(node, node.attr('style')));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove pointess spans
- if (node.name == 'span' && node.parent && !node.attributes.length) {
- node.unwrap();
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove pointess spans
+ if (node.name == 'span' && node.parent && !node.attributes.length) {
+ node.unwrap();
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check the class attribute for comments or del items and remove those
- domParser.addAttributeFilter('class', function(nodes) {
- var i = nodes.length, node, className;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check the class attribute for comments or del items and remove those
+ domParser.addAttributeFilter('class', function (nodes) {
+ var i = nodes.length, node, className;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- className = node.attr('class');
- if (/^(MsoCommentReference|MsoCommentText|msoDel)$/i.test(className)) {
- node.remove();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ className = node.attr('class');
+ if (/^(MsoCommentReference|MsoCommentText|msoDel)$/i.test(className)) {
+ node.remove();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node.attr('class', null);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node.attr('class', null);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove all del elements since we don't want the track changes code in the editor
- domParser.addNodeFilter('del', function(nodes) {
- var i = nodes.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove all del elements since we don't want the track changes code in the editor
+ domParser.addNodeFilter('del', function (nodes) {
+ var i = nodes.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- nodes[i].remove();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ nodes[i].remove();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Keep some of the links and anchors
- domParser.addNodeFilter('a', function(nodes) {
- var i = nodes.length, node, href, name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Keep some of the links and anchors
+ domParser.addNodeFilter('a', function (nodes) {
+ var i = nodes.length, node, href, name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i];
- href = node.attr('href');
- name = node.attr('name');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i];
+ href = node.attr('href');
+ name = node.attr('name');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (href && href.indexOf('#_msocom_') != -1) {
- node.remove();
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (href && href.indexOf('#_msocom_') != -1) {
+ node.remove();
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (href && href.indexOf('file://') === 0) {
- href = href.split('#')[1];
- if (href) {
- href = '#' + href;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (href && href.indexOf('file://') === 0) {
+ href = href.split('#')[1];
+ if (href) {
+ href = '#' + href;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!href && !name) {
- node.unwrap();
- } else {
- // Remove all named anchors that aren't specific to TOC, Footnotes or Endnotes
- if (name && !/^_?(?:toc|edn|ftn)/i.test(name)) {
- node.unwrap();
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!href && !name) {
+ node.unwrap();
+ } else {
+ // Remove all named anchors that aren't specific to TOC, Footnotes or Endnotes
+ if (name && !/^_?(?:toc|edn|ftn)/i.test(name)) {
+ node.unwrap();
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node.attr({
- href: href,
- name: name
- });
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node.attr({
+ href: href,
+ name: name
+ });
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Parse into DOM structure
- var rootNode = domParser.parse(content);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Parse into DOM structure
+ var rootNode = domParser.parse(content);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Process DOM
- if (settings.paste_convert_word_fake_lists !== false) {
- convertFakeListsToProperLists(rootNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Process DOM
+ if (settings.paste_convert_word_fake_lists !== false) {
+ convertFakeListsToProperLists(rootNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Serialize DOM back to HTML
- e.content = new Serializer({
- validate: settings.validate
- }, schema).serialize(rootNode);
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Serialize DOM back to HTML
+ e.content = new Serializer({
+ validate: settings.validate
+ }, schema).serialize(rootNode);
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- WordFilter.isWordContent = isWordContent;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ WordFilter.isWordContent = isWordContent;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return WordFilter;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return WordFilter;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/plugins/paste/classes/Quirks.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Quirks.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1566,304 +2035,313 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.pasteplugin.Quirks
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/pasteplugin/Quirks", [
- "tinymce/Env",
- "tinymce/util/Tools",
- "tinymce/pasteplugin/WordFilter",
- "tinymce/pasteplugin/Utils"
-], function(Env, Tools, WordFilter, Utils) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.paste.core.Quirks',
+ [
+ 'tinymce.core.Env',
+ 'tinymce.core.util.Tools',
+ 'tinymce.plugins.paste.core.WordFilter',
+ 'tinymce.plugins.paste.core.Utils'
+ ],
+ function (Env, Tools, WordFilter, Utils) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function(editor) {
- function addPreProcessFilter(filterFunc) {
- editor.on('BeforePastePreProcess', function(e) {
- e.content = filterFunc(e.content);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function (editor) {
+ function addPreProcessFilter(filterFunc) {
+ editor.on('BeforePastePreProcess', function (e) {
+ e.content = filterFunc(e.content);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function addPostProcessFilter(filterFunc) {
- editor.on('PastePostProcess', function(e) {
- filterFunc(e.node);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function addPostProcessFilter(filterFunc) {
+ editor.on('PastePostProcess', function (e) {
+ filterFunc(e.node);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes BR elements after block elements. IE9 has a nasty bug where it puts a BR element after each
- * block element when pasting from word. This removes those elements.
- *
- * This:
- * <p>a</p><br><p>b</p>
- *
- * Becomes:
- * <p>a</p><p>b</p>
- */
- function removeExplorerBrElementsAfterBlocks(html) {
- // Only filter word specific content
- if (!WordFilter.isWordContent(html)) {
- return html;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes BR elements after block elements. IE9 has a nasty bug where it puts a BR element after each
+ * block element when pasting from word. This removes those elements.
+ *
+ * This:
+ * <p>a</p><br><p>b</p>
+ *
+ * Becomes:
+ * <p>a</p><p>b</p>
+ */
+ function removeExplorerBrElementsAfterBlocks(html) {
+ // Only filter word specific content
+ if (!WordFilter.isWordContent(html)) {
+ return html;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Produce block regexp based on the block elements in schema
- var blockElements = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Produce block regexp based on the block elements in schema
+ var blockElements = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(editor.schema.getBlockElements(), function(block, blockName) {
- blockElements.push(blockName);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(editor.schema.getBlockElements(), function (block, blockName) {
+ blockElements.push(blockName);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var explorerBlocksRegExp = new RegExp(
- '(?:<br> [\\s\\r\\n]+|<br>)*(<\\/?(' + blockElements.join('|') + ')[^>]*>)(?:<br> [\\s\\r\\n]+|<br>)*',
- 'g'
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var explorerBlocksRegExp = new RegExp(
+ '(?:<br> [\\s\\r\\n]+|<br>)*(<\\/?(' + blockElements.join('|') + ')[^>]*>)(?:<br> [\\s\\r\\n]+|<br>)*',
+ 'g'
+ );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove BR:s from: <BLOCK>X</BLOCK><BR>
- html = Utils.filter(html, [
- [explorerBlocksRegExp, '$1']
- ]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove BR:s from: <BLOCK>X</BLOCK><BR>
+ html = Utils.filter(html, [
+ [explorerBlocksRegExp, '$1']
+ ]);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // IE9 also adds an extra BR element for each soft-linefeed and it also adds a BR for each word wrap break
- html = Utils.filter(html, [
- [/<br><br>/g, '<BR><BR>'], // Replace multiple BR elements with uppercase BR to keep them intact
- [/<br>/g, ' '], // Replace single br elements with space since they are word wrap BR:s
- [/<BR><BR>/g, '<br>'] // Replace back the double brs but into a single BR
- ]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // IE9 also adds an extra BR element for each soft-linefeed and it also adds a BR for each word wrap break
+ html = Utils.filter(html, [
+ [/<br><br>/g, '<BR><BR>'], // Replace multiple BR elements with uppercase BR to keep them intact
+ [/<br>/g, ' '], // Replace single br elements with space since they are word wrap BR:s
+ [/<BR><BR>/g, '<br>'] // Replace back the double brs but into a single BR
+ ]);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return html;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return html;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * WebKit has a nasty bug where the all computed styles gets added to style attributes when copy/pasting contents.
- * This fix solves that by simply removing the whole style attribute.
- *
- * The paste_webkit_styles option can be set to specify what to keep:
- * paste_webkit_styles: "none" // Keep no styles
- * paste_webkit_styles: "all", // Keep all of them
- * paste_webkit_styles: "font-weight color" // Keep specific ones
- *
- * @param {String} content Content that needs to be processed.
- * @return {String} Processed contents.
- */
- function removeWebKitStyles(content) {
- // Passthrough all styles from Word and let the WordFilter handle that junk
- if (WordFilter.isWordContent(content)) {
- return content;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * WebKit has a nasty bug where the all computed styles gets added to style attributes when copy/pasting contents.
+ * This fix solves that by simply removing the whole style attribute.
+ *
+ * The paste_webkit_styles option can be set to specify what to keep:
+ * paste_webkit_styles: "none" // Keep no styles
+ * paste_webkit_styles: "all", // Keep all of them
+ * paste_webkit_styles: "font-weight color" // Keep specific ones
+ *
+ * @param {String} content Content that needs to be processed.
+ * @return {String} Processed contents.
+ */
+ function removeWebKitStyles(content) {
+ // Passthrough all styles from Word and let the WordFilter handle that junk
+ if (WordFilter.isWordContent(content)) {
+ return content;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Filter away styles that isn't matching the target node
- var webKitStyles = editor.settings.paste_webkit_styles;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Filter away styles that isn't matching the target node
+ var webKitStyles = editor.settings.paste_webkit_styles;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.settings.paste_remove_styles_if_webkit === false || webKitStyles == "all") {
- return content;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.settings.paste_remove_styles_if_webkit === false || webKitStyles == "all") {
+ return content;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (webKitStyles) {
- webKitStyles = webKitStyles.split(/[, ]/);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (webKitStyles) {
+ webKitStyles = webKitStyles.split(/[, ]/);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Keep specific styles that doesn't match the current node computed style
- if (webKitStyles) {
- var dom = editor.dom, node = editor.selection.getNode();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Keep specific styles that doesn't match the current node computed style
+ if (webKitStyles) {
+ var dom = editor.dom, node = editor.selection.getNode();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, function(all, before, value, after) {
- var inputStyles = dom.parseStyle(value, 'span'), outputStyles = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, function (all, before, value, after) {
+ var inputStyles = dom.parseStyle(value, 'span'), outputStyles = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (webKitStyles === "none") {
- return before + after;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (webKitStyles === "none") {
+ return before + after;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var i = 0; i < webKitStyles.length; i++) {
- var inputValue = inputStyles[webKitStyles[i]], currentValue = dom.getStyle(node, webKitStyles[i], true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (var i = 0; i < webKitStyles.length; i++) {
+ var inputValue = inputStyles[webKitStyles[i]], currentValue = dom.getStyle(node, webKitStyles[i], true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (/color/.test(webKitStyles[i])) {
- inputValue = dom.toHex(inputValue);
- currentValue = dom.toHex(currentValue);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (/color/.test(webKitStyles[i])) {
+ inputValue = dom.toHex(inputValue);
+ currentValue = dom.toHex(currentValue);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (currentValue != inputValue) {
- outputStyles[webKitStyles[i]] = inputValue;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (currentValue != inputValue) {
+ outputStyles[webKitStyles[i]] = inputValue;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- outputStyles = dom.serializeStyle(outputStyles, 'span');
- if (outputStyles) {
- return before + ' style="' + outputStyles + '"' + after;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ outputStyles = dom.serializeStyle(outputStyles, 'span');
+ if (outputStyles) {
+ return before + ' style="' + outputStyles + '"' + after;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return before + after;
- });
- } else {
- // Remove all external styles
- content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, '$1$3');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return before + after;
+ });
+ } else {
+ // Remove all external styles
+ content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, '$1$3');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Keep internal styles
- content = content.replace(/(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi, function(all, before, value, after) {
- return before + ' style="' + value + '"' + after;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Keep internal styles
+ content = content.replace(/(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi, function (all, before, value, after) {
+ return before + ' style="' + value + '"' + after;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return content;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return content;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function removeUnderlineAndFontInAnchor(root) {
- editor.$('a', root).find('font,u').each(function(i, node) {
- editor.dom.remove(node, true);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function removeUnderlineAndFontInAnchor(root) {
+ editor.$('a', root).find('font,u').each(function (i, node) {
+ editor.dom.remove(node, true);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Sniff browsers and apply fixes since we can't feature detect
- if (Env.webkit) {
- addPreProcessFilter(removeWebKitStyles);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Sniff browsers and apply fixes since we can't feature detect
+ if (Env.webkit) {
+ addPreProcessFilter(removeWebKitStyles);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (Env.ie) {
- addPreProcessFilter(removeExplorerBrElementsAfterBlocks);
- addPostProcessFilter(removeUnderlineAndFontInAnchor);
- }
- };
-});
-
-// Included from: js/tinymce/plugins/paste/classes/Plugin.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (Env.ie) {
+ addPreProcessFilter(removeExplorerBrElementsAfterBlocks);
+ addPostProcessFilter(removeUnderlineAndFontInAnchor);
+ }
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Plugin.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * This class contains the tinymce plugin logic for the paste plugin.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * This class contains all core logic for the paste plugin.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @class tinymce.pasteplugin.Plugin
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @class tinymce.paste.Plugin
</ins><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/pasteplugin/Plugin", [
- "tinymce/PluginManager",
- "tinymce/pasteplugin/Clipboard",
- "tinymce/pasteplugin/WordFilter",
- "tinymce/pasteplugin/Quirks"
-], function(PluginManager, Clipboard, WordFilter, Quirks) {
- var userIsInformed;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.plugins.paste.Plugin',
+ [
+ 'tinymce.core.PluginManager',
+ 'tinymce.plugins.paste.core.Clipboard',
+ 'tinymce.plugins.paste.core.CutCopy',
+ 'tinymce.plugins.paste.core.Quirks',
+ 'tinymce.plugins.paste.core.WordFilter'
+ ],
+ function (PluginManager, Clipboard, CutCopy, Quirks, WordFilter) {
+ var userIsInformed;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- PluginManager.add('paste', function(editor) {
- var self = this, clipboard, settings = editor.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ PluginManager.add('paste', function (editor) {
+ var self = this, clipboard, settings = editor.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isUserInformedAboutPlainText() {
- return userIsInformed || editor.settings.paste_plaintext_inform === false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isUserInformedAboutPlainText() {
+ return userIsInformed || editor.settings.paste_plaintext_inform === false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function togglePlainTextPaste() {
- if (clipboard.pasteFormat == "text") {
- clipboard.pasteFormat = "html";
- editor.fire('PastePlainTextToggle', {state: false});
- } else {
- clipboard.pasteFormat = "text";
- editor.fire('PastePlainTextToggle', {state: true});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function togglePlainTextPaste() {
+ if (clipboard.pasteFormat == "text") {
+ clipboard.pasteFormat = "html";
+ editor.fire('PastePlainTextToggle', { state: false });
+ } else {
+ clipboard.pasteFormat = "text";
+ editor.fire('PastePlainTextToggle', { state: true });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isUserInformedAboutPlainText()) {
- var message = editor.translate('Paste is now in plain text mode. Contents will now ' +
- 'be pasted as plain text until you toggle this option off.');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isUserInformedAboutPlainText()) {
+ var message = editor.translate('Paste is now in plain text mode. Contents will now ' +
+ 'be pasted as plain text until you toggle this option off.');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.notificationManager.open({
- text: message,
- type: 'info'
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.notificationManager.open({
+ text: message,
+ type: 'info'
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- userIsInformed = true;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ userIsInformed = true;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.focus();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.focus();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function stateChange() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function stateChange() {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.active(clipboard.pasteFormat === 'text');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.active(clipboard.pasteFormat === 'text');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('PastePlainTextToggle', function (e) {
- self.active(e.state);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('PastePlainTextToggle', function (e) {
+ self.active(e.state);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // draw back if power version is requested and registered
- if (/(^|[ ,])powerpaste([, ]|$)/.test(settings.plugins) && PluginManager.get('powerpaste')) {
- /*eslint no-console:0 */
- if (typeof console !== "undefined" && console.log) {
- console.log("PowerPaste is incompatible with Paste plugin! Remove 'paste' from the 'plugins' option.");
- }
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // draw back if power version is requested and registered
+ if (/(^|[ ,])powerpaste([, ]|$)/.test(settings.plugins) && PluginManager.get('powerpaste')) {
+ /*eslint no-console:0 */
+ if (typeof console !== "undefined" && console.log) {
+ console.log("PowerPaste is incompatible with Paste plugin! Remove 'paste' from the 'plugins' option.");
+ }
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.clipboard = clipboard = new Clipboard(editor);
- self.quirks = new Quirks(editor);
- self.wordFilter = new WordFilter(editor);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.clipboard = clipboard = new Clipboard(editor);
+ self.quirks = new Quirks(editor);
+ self.wordFilter = new WordFilter(editor);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.settings.paste_as_text) {
- self.clipboard.pasteFormat = "text";
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.settings.paste_as_text) {
+ self.clipboard.pasteFormat = "text";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.paste_preprocess) {
- editor.on('PastePreProcess', function(e) {
- settings.paste_preprocess.call(self, self, e);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.paste_preprocess) {
+ editor.on('PastePreProcess', function (e) {
+ settings.paste_preprocess.call(self, self, e);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.paste_postprocess) {
- editor.on('PastePostProcess', function(e) {
- settings.paste_postprocess.call(self, self, e);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.paste_postprocess) {
+ editor.on('PastePostProcess', function (e) {
+ settings.paste_postprocess.call(self, self, e);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addCommand('mceInsertClipboardContent', function(ui, value) {
- if (value.content) {
- self.clipboard.pasteHtml(value.content);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addCommand('mceInsertClipboardContent', function (ui, value) {
+ if (value.content) {
+ self.clipboard.pasteHtml(value.content, value.internal);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value.text) {
- self.clipboard.pasteText(value.text);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value.text) {
+ self.clipboard.pasteText(value.text);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Block all drag/drop events
- if (editor.settings.paste_block_drop) {
- editor.on('dragend dragover draggesture dragdrop drop drag', function(e) {
- e.preventDefault();
- e.stopPropagation();
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Block all drag/drop events
+ if (editor.settings.paste_block_drop) {
+ editor.on('dragend dragover draggesture dragdrop drop drag', function (e) {
+ e.preventDefault();
+ e.stopPropagation();
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Prevent users from dropping data images on Gecko
- if (!editor.settings.paste_data_images) {
- editor.on('drop', function(e) {
- var dataTransfer = e.dataTransfer;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Prevent users from dropping data images on Gecko
+ if (!editor.settings.paste_data_images) {
+ editor.on('drop', function (e) {
+ var dataTransfer = e.dataTransfer;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
- e.preventDefault();
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
+ e.preventDefault();
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addCommand('mceTogglePlainTextPaste', togglePlainTextPaste);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addCommand('mceTogglePlainTextPaste', togglePlainTextPaste);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addButton('pastetext', {
- icon: 'pastetext',
- tooltip: 'Paste as text',
- onclick: togglePlainTextPaste,
- onPostRender: stateChange
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addButton('pastetext', {
+ icon: 'pastetext',
+ tooltip: 'Paste as text',
+ onclick: togglePlainTextPaste,
+ onPostRender: stateChange
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addMenuItem('pastetext', {
- text: 'Paste as text',
- selectable: true,
- active: clipboard.pasteFormat,
- onclick: togglePlainTextPaste,
- onPostRender: stateChange
- });
- });
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addMenuItem('pastetext', {
+ text: 'Paste as text',
+ selectable: true,
+ active: clipboard.pasteFormat,
+ onclick: togglePlainTextPaste,
+ onPostRender: stateChange
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-expose(["tinymce/pasteplugin/Utils"]);
-})(window);
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ CutCopy.register(editor);
+ });
+
+ return function () { };
+ }
+);
+dem('tinymce.plugins.paste.Plugin')();
+})();
</ins></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginspastepluginminjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/paste/plugin.min.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/paste/plugin.min.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/paste/plugin.min.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1 +1 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-!function(e,t){"use strict";function n(e,t){for(var n,r=[],o=0;o<e.length;++o){if(n=a[e[o]]||i(e[o]),!n)throw"module definition dependecy not found: "+e[o];r.push(n)}t.apply(null,r)}function r(e,r,i){if("string"!=typeof e)throw"invalid module definition, module id must be defined and be a string";if(r===t)throw"invalid module definition, dependencies must be specified";if(i===t)throw"invalid module definition, definition function must be specified";n(r,function(){a[e]=i.apply(null,arguments)})}function i(t){for(var n=e,r=t.split(/[.\/]/),i=0;i<r.length;++i){if(!n[r[i]])return;n=n[r[i]]}return n}function o(n){var r,i,o,s,l;for(r=0;r<n.length;r++){i=e,o=n[r],s=o.split(/[.\/]/);for(var u=0;u<s.length-1;++u)i[s[u]]===t&&(i[s[u]]={}),i=i[s[u]];i[s[s.length-1]]=a[o]}if(e.AMDLC_TESTS){l=e.privateModules||{};for(o in
a)l[o]=a[o];for(r=0;r<n.length;r++)delete l[n[r]];e.privateModules=l}}var a={};r("tinymce/pasteplugin/Utils",["tinymce/util/Tools","tinymce/html/DomParser","tinymce/html/Schema"],function(e,t,n){function r(t,n){return e.each(n,function(e){t=e.constructor==RegExp?t.replace(e,""):t.replace(e[0],e[1])}),t}function i(i){function o(e){var t=e.name,n=e;if("br"===t)return void(l+="\n");if(u[t]&&(l+=" "),c[t])return void(l+=" ");if(3==e.type&&(l+=e.value),!e.shortEnded&&(e=e.firstChild))do o(e);while(e=e.next);d[t]&&n.next&&(l+="\n","p"==t&&(l+="\n"))}var a=new n,s=new t({},a),l="",u=a.getShortEndedElements(),c=e.makeMap("script noscript style textarea video audio iframe object"," "),d=a.getBlockElements();return i=r(i,[/<!\[[^\]]+\]>/g]),o(s.parse(i)),l}function o(e){function t(e,t,n){
return t||n?"\xa0":" "}return e=r(e,[/^[\s\S]*<body[^>]*>\s*|\s*<\/body[^>]*>[\s\S]*$/g,/<!--StartFragment-->|<!--EndFragment-->/g,[/( ?)<span class="Apple-converted-space">\u00a0<\/span>( ?)/g,t],/<br class="Apple-interchange-newline">/g,/<br>$/i])}function a(e){var t=0;return function(){return e+t++}}return{filter:r,innerText:i,trimHtml:o,createIdGenerator:a}}),r("tinymce/pasteplugin/SmartPaste",["tinymce/util/Tools"],function(e){var t=function(e){return/^https?:\/\/[\w\?\-\/+=.&%@~#]+$/i.test(e)},n=function(e){return t(e)&&/.(gif|jpe?g|png)$/.test(e)},r=function(e,t,n){return e.undoManager.extra(function(){n(e,t)},function(){e.insertContent('<img src="'+t+'">')}),!0},i=function(e,t,n){return e.undoManager.extra(function(){n(e,t)},function(){e.execCommand("mceInsertLink",!1,t)}),!0},o=function(e,n,r){return!(e.selection.isCollapsed
()!==!1||!t(n))&&i(e,n,r)},a=function(e,t,i){return!!n(t)&&r(e,t,i)},s=function(e,t){return e.insertContent(t,{merge:e.settings.paste_merge_formats!==!1,paste:!0}),!0},l=function(t,n){e.each([o,a,s],function(e){return e(t,n,s)!==!0})},u=function(e,t){e.settings.smart_paste===!1?s(e,t):l(e,t)};return{isImageUrl:n,isAbsoluteUrl:t,insertContent:u}}),r("tinymce/pasteplugin/Clipboard",["tinymce/Env","tinymce/dom/RangeUtils","tinymce/util/VK","tinymce/pasteplugin/Utils","tinymce/pasteplugin/SmartPaste","tinymce/util/Delay"],function(e,t,n,r,i,o){return function(a){function s(e){var t,n=a.dom;if(t=a.fire("BeforePastePreProcess",{content:e}),t=a.fire("PastePreProcess",t),e=t.content,!t.isDefaultPrevented()){if(a.hasEventListeners("PastePostProcess")&&!t.isDefaultPrevented()){var r=n.add(a.getBody(),"div",{style:"display:none"},e);t=a.fire("Past
ePostProcess",{node:r}),n.remove(r),e=t.node.innerHTML}t.isDefaultPrevented()||i.insertContent(a,e)}}function l(e){e=a.dom.encode(e).replace(/\r\n/g,"\n");var t,n=a.dom.getParent(a.selection.getStart(),a.dom.isBlock),i=a.settings.forced_root_block;i&&(t=a.dom.createHTML(i,a.settings.forced_root_block_attrs),t=t.substr(0,t.length-3)+">"),n&&/^(PRE|DIV)$/.test(n.nodeName)||!i?e=r.filter(e,[[/\n/g,"<br>"]]):(e=r.filter(e,[[/\n\n/g,"</p>"+t],[/^(.*<\/p>)(<p>)$/,t+"$1"],[/\n/g,"<br />"]]),e.indexOf("<p>")!=-1&&(e=t+e)),s(e)}function u(){function t(e){var t,n,i,o=e.startContainer;if(t=e.getClientRects(),t.length)return t[0];if(e.collapsed&&1==o.nodeType){for(i=o.childNodes[_.startOffset];i&&3==i.nodeType&&!i.data.length;)i=i.nextSibling;if(i)return"BR"==i.tagName&&(n=r.doc.createTextNode("\ufeff"),i.pa
rentNode.insertBefore(n,i),e=r.createRng(),e.setStartBefore(n),e.setEndAfter(n),t=e.getClientRects(),r.remove(n)),t.length?t[0]:void 0}}var n,r=a.dom,i=a.getBody(),o=a.dom.getViewPort(a.getWin()),s=o.y,l=20;if(_=a.selection.getRng(),a.inline&&(n=a.selection.getScrollContainer(),n&&n.scrollTop>0&&(s=n.scrollTop)),_.getClientRects){var u=t(_);if(u)l=s+(u.top-r.getPos(i).y);else{l=s;var c=_.startContainer;c&&(3==c.nodeType&&c.parentNode!=i&&(c=c.parentNode),1==c.nodeType&&(l=r.getPos(c,n||i).y))}}N=r.add(a.getBody(),"div",{id:"mcepastebin",contentEditable:!0,"data-mce-bogus":"all",style:"position: absolute; top: "+l+"px;width: 10px; height: 10px; overflow: hidden; opacity: 0"},A),(e.ie||e.gecko)&&r.setStyle(N,"left","rtl"==r.getStyle(i,"direction",!0)?65535:-65535),r.bind(N,"beforedeactivate focusin focusout",function(e){
e.stopPropagation()}),N.focus(),a.selection.select(N,!0)}function c(){if(N){for(var e;e=a.dom.get("mcepastebin");)a.dom.remove(e),a.dom.unbind(e);_&&a.selection.setRng(_)}N=_=null}function d(){var e,t,n,r,i="";for(e=a.dom.select("div[id=mcepastebin]"),t=0;t<e.length;t++)n=e[t],n.firstChild&&"mcepastebin"==n.firstChild.id&&(n=n.firstChild),r=n.innerHTML,i!=A&&(i+=r);return i}function f(e){var t={};if(e){if(e.getData){var n=e.getData("Text");n&&n.length>0&&n.indexOf(B)==-1&&(t["text/plain"]=n)}if(e.types)for(var r=0;r<e.types.length;r++){var i=e.types[r];t[i]=e.getData(i)}}return t}function p(e){return f(e.clipboardData||a.getDoc().dataTransfer)}function h(e){return x(e,"text/html")||x(e,"text/plain")}function m(e){var t;return t=e.indexOf(","),t!==-1?e.substr(t+1):null}function g(e,t){return!e.images_dataimg_filter||e.images_dataim
g_filter(t)}function v(e,t,n){e&&(a.selection.setRng(e),e=null);var r=t.result,i=m(r),o=new Image;if(o.src=r,g(a.settings,o)){var l,u,c=a.editorUpload.blobCache;u=c.findFirst(function(e){return e.base64()===i}),u?l=u:(l=c.create(D(),n,i),c.add(l)),s('<img src="'+l.blobUri()+'">')}else s('<img src="'+r+'">')}function y(e,t){function n(n){var r,i,o,a=!1;if(n)for(r=0;r<n.length;r++)if(i=n[r],/^image\/(jpeg|png|gif|bmp)$/.test(i.type)){var s=i.getAsFile?i.getAsFile():i;o=new FileReader,o.onload=v.bind(null,t,o,s),o.readAsDataURL(s),e.preventDefault(),a=!0}return a}var r=e.clipboardData||e.dataTransfer;if(a.settings.paste_data_images&&r)return n(r.items)||n(r.files)}function b(e){var t=e.clipboardData;return navigator.userAgent.indexOf("Android")!=-1&&t&&t.items&&0===t.items.length}function C(e){return t.getCaretRangeFromPoint(e.clientX,e.clientY,a.getDoc())}function x(e,t){return t in e&&e[t].le
ngth>0}function w(e){return n.metaKeyPressed(e)&&86==e.keyCode||e.shiftKey&&45==e.keyCode}function E(){function t(e,t,n){var i;return x(e,"text/html")?i=e["text/html"]:(i=d(),i==A&&(n=!0)),i=r.trimHtml(i),N&&N.firstChild&&"mcepastebin"===N.firstChild.id&&(n=!0),c(),i.length||(n=!0),n&&(i=x(e,"text/plain")&&i.indexOf("</p>")==-1?e["text/plain"]:r.innerText(i)),i==A?void(t||a.windowManager.alert("Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents.")):void(n?l(i):s(i))}function n(e){var t=e["text/plain"];return!!t&&0===t.indexOf("file://")}a.on("keydown",function(t){function n(e){w(e)&&!e.isDefaultPrevented()&&c()}if(w(t)&&!t.isDefaultPrevented()){if(S=t.shiftKey&&86==t.keyCode,S&&e.webkit&&navigator.userAgent.indexOf("Version/")!=-1)return;
if(t.stopImmediatePropagation(),T=(new Date).getTime(),e.ie&&S)return t.preventDefault(),void a.fire("paste",{ieFake:!0});c(),u(),a.once("keyup",n),a.once("paste",function(){a.off("keyup",n)})}});var i=function(){return _||a.selection.getRng()};a.on("paste",function(n){var r=(new Date).getTime(),s=p(n),l=(new Date).getTime()-r,f=(new Date).getTime()-T-l<1e3,m="text"==k.pasteFormat||S;return S=!1,n.isDefaultPrevented()||b(n)?void c():!h(s)&&y(n,i())?void c():(f||n.preventDefault(),!e.ie||f&&!n.ieFake||(u(),a.dom.bind(N,"paste",function(e){e.stopPropagation()}),a.getDoc().execCommand("Paste",!1,null),s["text/html"]=d()),void(x(s,"text/html")?(n.preventDefault(),t(s,f,m)):o.setEditorTimeout(a,function(){t(s,f,m)},0)))}),a.on("dragstart dragend",function(e){R="dragstart"==e.type}),a.on("drop",function(e){var t,i;if(i=C(e),!e.isDefau
ltPrevented()&&!R&&(t=f(e.dataTransfer),(h(t)&&!n(t)||!y(e,i))&&i&&a.settings.paste_filter_drop!==!1)){var u=t["mce-internal"]||t["text/html"]||t["text/plain"];u&&(e.preventDefault(),o.setEditorTimeout(a,function(){a.undoManager.transact(function(){t["mce-internal"]&&a.execCommand("Delete"),a.selection.setRng(i),u=r.trimHtml(u),t["text/html"]?s(u):l(u)})}))}}),a.on("dragover dragend",function(e){a.settings.paste_data_images&&e.preventDefault()})}var N,_,S,k=this,T=0,R=!1,A="%MCEPASTEBIN%",B="data:text/mce-internal,",D=r.createIdGenerator("mceclip");k.pasteHtml=s,k.pasteText=l,k.pasteImageData=y,a.on("preInit",function(){E(),a.parser.addNodeFilter("img",function(t,n,r){function i(e){return e.data&&e.data.paste===!0}function o(t){t.attr("data-mce-object")||c===e.transparentSrc||t.remove
()}function s(e){return 0===e.indexOf("webkit-fake-url")}function l(e){return 0===e.indexOf("data:")}if(!a.settings.paste_data_images&&i(r))for(var u=t.length;u--;){var c=t[u].attributes.map.src;c&&(s(c)?o(t[u]):!a.settings.allow_html_data_urls&&l(c)&&o(t[u]))}})})}}),r("tinymce/pasteplugin/WordFilter",["tinymce/util/Tools","tinymce/html/DomParser","tinymce/html/Schema","tinymce/html/Serializer","tinymce/html/Node","tinymce/pasteplugin/Utils"],function(e,t,n,r,i,o){function a(e){return/<font face="Times New Roman"|class="?Mso|style="[^"]*\bmso-|style='[^'']*\bmso-|w:WordDocument/i.test(e)||/class="OutlineElement/.test(e)||/id="?docs\-internal\-guid\-/.test(e)}function s(t){var n,r;return r=[/^[IVXLMCD]{1,2}\.[ \u00a0]/,/^[ivxlmcd]{1,2}\.[ \u00a0]/,/^[a-z]{1,2}[\.\)][ \u00a0]/,/^[A-Z]{1,2}[\.\)][ \u00a0]/,/^[0-9]+\.[ \u00a0]/,
/^[\u3007\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d]+\.[ \u00a0]/,/^[\u58f1\u5f10\u53c2\u56db\u4f0d\u516d\u4e03\u516b\u4e5d\u62fe]+\.[ \u00a0]/],t=t.replace(/^[\u00a0 ]+/,""),e.each(r,function(e){if(e.test(t))return n=!0,!1}),n}function l(e){return/^[\s\u00a0]*[\u2022\u00b7\u00a7\u25CF]\s*/.test(e)}function u(u){var c=u.settings;u.on("BeforePastePreProcess",function(d){function f(e){function t(e){var n="";if(3===e.type)return e.value;if(e=e.firstChild)do n+=t(e);while(e=e.next);return n}function n(e,t){if(3===e.type&&t.test(e.value))return e.value=e.value.replace(t,""),!1;if(e=e.firstChild)do if(!n(e,t))return!1;while(e=e.next);return!0}function r(e){if(e._listIgnore)return void e.remove();if(e=e.firstChild)do r(e);while(e=e.next)}function o(e,t,o){var s=e._listLevel||c;s!=c&&(s<c?a&&(a=a.parent.parent):(u=a,a=null)),a&&a.name==t?a.append(e):(u=u||a,a=new i(t,1),o>1&&a.attr("start&
quot;,""+o),e.wrap(a)),e.name="li",s>c&&u&&u.lastChild.append(a),c=s,r(e),n(e,/^\u00a0+/),n(e,/^\s*([\u2022\u00b7\u00a7\u25CF]|\w+\.)/),n(e,/^\u00a0+/)}for(var a,u,c=1,d=[],f=e.firstChild;"undefined"!=typeof f&&null!==f;)if(d.push(f),f=f.walk(),null!==f)for(;"undefined"!=typeof f&&f.parent!==e;)f=f.walk();for(var p=0;p<d.length;p++)if(e=d[p],"p"==e.name&&e.firstChild){var h=t(e);if(l(h)){o(e,"ul");continue}if(s(h)){var m=/([0-9]+)\./.exec(h),g=1;m&&(g=parseInt(m[1],10)),o(e,"ol",g);continue}if(e._listLevel){o(e,"ul",1);continue}a=null}else u=a,a=null}function p(t,n){var r,o={},a=u.dom.parseStyle(n);return e.each(a,function(e,i){switch(i){case"mso-list":r=/\w+ \w+([0-9]+)/i.exec(n),r&&(t._listLevel=parseInt(r[1],10)),/Ignore/i.test(e)&&t.firstChild&&(t._listIgnore=!0,t.firstChild._listIgnore=!0);break;case"horiz-a
lign":i="text-align";break;case"vert-align":i="vertical-align";break;case"font-color":case"mso-foreground":i="color";break;case"mso-background":case"mso-highlight":i="background";break;case"font-weight":case"font-style":return void("normal"!=e&&(o[i]=e));case"mso-element":if(/^(comment|comment-list)$/i.test(e))return void t.remove()}return 0===i.indexOf("mso-comment")?void t.remove():void(0!==i.indexOf("mso-")&&("all"==h||m&&m[i])&&(o[i]=e))}),/(bold)/i.test(o["font-weight"])&&(delete o["font-weight"],t.wrap(new i("b",1))),/(italic)/i.test(o["font-style"])&&(delete o["font-style"],t.wrap(new i("i",1))),o=u.dom.serializeStyle(o,t.name),o?o:null}var h,m,g=d.content;if(g=g.replace(/<b[^>]+id="?docs-internal
-[^>]*>/gi,""),g=g.replace(/<br class="?Apple-interchange-newline"?>/gi,""),h=c.paste_retain_style_properties,h&&(m=e.makeMap(h.split(/[, ]/))),c.paste_enable_default_filters!==!1&&a(d.content)){d.wordContent=!0,g=o.filter(g,[/<!--[\s\S]+?-->/gi,/<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,[/<(\/?)s>/gi,"<$1strike>"],[/ /gi,"\xa0"],[/<span\s+style\s*=\s*"\s*mso-spacerun\s*:\s*yes\s*;?\s*"\s*>([\s\u00a0]*)<\/span>/gi,function(e,t){return t.length>0?t.replace(/./," ").slice(Math.floor(t.length/2)).split("").join("\xa0"):""}]]);var v=c.paste_word_valid_elements;v||(v="-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-h1,-h2,-h3,-h4,-h5,-h6,-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,td[colspan|rowspan|width],th[colspan|rowspa
n|width],thead,tfoot,tbody");var y=new n({valid_elements:v,valid_children:"-li[p]"});e.each(y.elements,function(e){e.attributes["class"]||(e.attributes["class"]={},e.attributesOrder.push("class")),e.attributes.style||(e.attributes.style={},e.attributesOrder.push("style"))});var b=new t({},y);b.addAttributeFilter("style",function(e){for(var t,n=e.length;n--;)t=e[n],t.attr("style",p(t,t.attr("style"))),"span"==t.name&&t.parent&&!t.attributes.length&&t.unwrap()}),b.addAttributeFilter("class",function(e){for(var t,n,r=e.length;r--;)t=e[r],n=t.attr("class"),/^(MsoCommentReference|MsoCommentText|msoDel)$/i.test(n)&&t.remove(),t.attr("class",null)}),b.addNodeFilter("del",function(e){for(var t=e.length;t--;)e[t].remove()}),b.addNodeFilter("a",function(e){for(var t,n,r,i=e.length;i--;)if(t=e[i],n=t.attr("href&quo
t;),r=t.attr("name"),n&&n.indexOf("#_msocom_")!=-1)t.remove();else if(n&&0===n.indexOf("file://")&&(n=n.split("#")[1],n&&(n="#"+n)),n||r){if(r&&!/^_?(?:toc|edn|ftn)/i.test(r)){t.unwrap();continue}t.attr({href:n,name:r})}else t.unwrap()});var C=b.parse(g);c.paste_convert_word_fake_lists!==!1&&f(C),d.content=new r({validate:c.validate},y).serialize(C)}})}return u.isWordContent=a,u}),r("tinymce/pasteplugin/Quirks",["tinymce/Env","tinymce/util/Tools","tinymce/pasteplugin/WordFilter","tinymce/pasteplugin/Utils"],function(e,t,n,r){return function(i){function o(e){i.on("BeforePastePreProcess",function(t){t.content=e(t.content)})}function a(e){i.on("PastePostProcess",function(t){e(t.node)})}function s(e){if(!n.isWordContent(e))return e;var o=[];t.each(i.schema.getBlockElements(),function(e,t){o.push(t)});var a=new RegExp(&quo
t;(?:<br> [\\s\\r\\n]+|<br>)*(<\\/?("+o.join("|")+")[^>]*>)(?:<br> [\\s\\r\\n]+|<br>)*","g");return e=r.filter(e,[[a,"$1"]]),e=r.filter(e,[[/<br><br>/g,"<BR><BR>"],[/<br>/g," "],[/<BR><BR>/g,"<br>"]])}function l(e){if(n.isWordContent(e))return e;var t=i.settings.paste_webkit_styles;if(i.settings.paste_remove_styles_if_webkit===!1||"all"==t)return e;if(t&&(t=t.split(/[, ]/)),t){var r=i.dom,o=i.selection.getNode();e=e.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi,function(e,n,i,a){var s=r.parseStyle(i,"span"),l={};if("none"===t)return n+a;for(var u=0;u<t.length;u++){var c=s[t[u]],d=r.getStyle(o,t[u],!0);/color/.test(t[u])&&(c=r.toHex(c),d=r.toHex(d)),d!=c&&(l[t[u]]=c)}return l=r.serializeStyle(l,"span"),l?n+' style="'
+l+'"'+a:n+a})}else e=e.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi,"$1$3");return e=e.replace(/(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi,function(e,t,n,r){return t+' style="'+n+'"'+r})}function u(e){i.$("a",e).find("font,u").each(function(e,t){i.dom.remove(t,!0)})}e.webkit&&o(l),e.ie&&(o(s),a(u))}}),r("tinymce/pasteplugin/Plugin",["tinymce/PluginManager","tinymce/pasteplugin/Clipboard","tinymce/pasteplugin/WordFilter","tinymce/pasteplugin/Quirks"],function(e,t,n,r){var i;e.add("paste",function(o){function a(){return i||o.settings.paste_plaintext_inform===!1}function s(){if("text"==u.pasteFormat)u.pasteFormat="html",o.fire("PastePlainTextToggle",{state:!1});else if(u.pasteFormat="text",o.fire("PastePlainTextToggle",{state:!0}),!a()){var e=o.translate("P
aste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.");o.notificationManager.open({text:e,type:"info"}),i=!0}o.focus()}function l(){var e=this;e.active("text"===u.pasteFormat),o.on("PastePlainTextToggle",function(t){e.active(t.state)})}var u,c=this,d=o.settings;return/(^|[ ,])powerpaste([, ]|$)/.test(d.plugins)&&e.get("powerpaste")?void("undefined"!=typeof console&&console.log&&console.log("PowerPaste is incompatible with Paste plugin! Remove 'paste' from the 'plugins' option.")):(c.clipboard=u=new t(o),c.quirks=new r(o),c.wordFilter=new n(o),o.settings.paste_as_text&&(c.clipboard.pasteFormat="text"),d.paste_preprocess&&o.on("PastePreProcess",function(e){d.paste_preprocess.call(c,c,e)}),d.paste_postprocess&&o.on("PastePostProcess",function(e){d.paste_postprocess.call(c,c,e)}),o.addCommand
("mceInsertClipboardContent",function(e,t){t.content&&c.clipboard.pasteHtml(t.content),t.text&&c.clipboard.pasteText(t.text)}),o.settings.paste_block_drop&&o.on("dragend dragover draggesture dragdrop drop drag",function(e){e.preventDefault(),e.stopPropagation()}),o.settings.paste_data_images||o.on("drop",function(e){var t=e.dataTransfer;t&&t.files&&t.files.length>0&&e.preventDefault()}),o.addCommand("mceTogglePlainTextPaste",s),o.addButton("pastetext",{icon:"pastetext",tooltip:"Paste as text",onclick:s,onPostRender:l}),void o.addMenuItem("pastetext",{text:"Paste as text",selectable:!0,active:u.pasteFormat,onclick:s,onPostRender:l}))})}),o(["tinymce/pasteplugin/Utils"])}(window);
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+!function(){var a={},b=function(b){for(var c=a[b],e=c.deps,f=c.defn,g=e.length,h=new Array(g),i=0;i<g;++i)h[i]=d(e[i]);var j=f.apply(null,h);if(void 0===j)throw"module ["+b+"] returned undefined";c.instance=j},c=function(b,c,d){if("string"!=typeof b)throw"module id must be a string";if(void 0===c)throw"no dependencies for "+b;if(void 0===d)throw"no definition function for "+b;a[b]={deps:c,defn:d,instance:void 0}},d=function(c){var d=a[c];if(void 0===d)throw"module ["+c+"] was undefined";return void 0===d.instance&&b(c),d.instance},e=function(a,b){for(var c=a.length,e=new Array(c),f=0;f<c;++f)e.push(d(a[f]));b.apply(null,b)},f={};f.bolt={module:{api:{define:c,require:e,demand:d}}};var g=c,h=function(a,b){g(a,[],function(){return b})};h("6",tinymce.util.Tools.resolve),g("1",[&q
uot;6"],function(a){return a("tinymce.PluginManager")}),g("7",["6"],function(a){return a("tinymce.dom.RangeUtils")}),g("8",["6"],function(a){return a("tinymce.Env")}),g("9",["6"],function(a){return a("tinymce.util.Delay")}),g("a",["6"],function(a){return a("tinymce.util.Tools")}),g("b",["6"],function(a){return a("tinymce.util.VK")}),g("c",[],function(){var a="x-tinymce/html",b="<!-- "+a+" -->",c=function(a){return b+a},d=function(a){return a.replace(b,"")},e=function(a){return a.indexOf(b)!==-1};return{mark:c,unmark:d,isMarked:e,internalHtmlMime:function(){return a}}}),g("g",["6"],function(a){return a("tinymce.html.DomParser")}),g("h",["6"],function(a){return a("tinymce.html.Schema")}),g("d",[&quo
t;a","g","h"],function(a,b,c){function d(b,c){return a.each(c,function(a){b=a.constructor==RegExp?b.replace(a,""):b.replace(a[0],a[1])}),b}function e(e){function f(a){var b=a.name,c=a;if("br"===b)return void(i+="\n");if(j[b]&&(i+=" "),k[b])return void(i+=" ");if(3==a.type&&(i+=a.value),!a.shortEnded&&(a=a.firstChild))do f(a);while(a=a.next);l[b]&&c.next&&(i+="\n","p"==b&&(i+="\n"))}var g=new c,h=new b({},g),i="",j=g.getShortEndedElements(),k=a.makeMap("script noscript style textarea video audio iframe object"," "),l=g.getBlockElements();return e=d(e,[/<!\[[^\]]+\]>/g]),f(h.parse(e)),i}function f(a){function b(a,b,c){return b||c?"\xa0":" "}return a=d(a,[/^[\s\S]*<body[^>]*>\s*|\s*<\/body[^>]*>[\s\S]*$/gi,/<!--StartFragment-->|<!--EndFragment-->/g,[/
( ?)<span class="Apple-converted-space">\u00a0<\/span>( ?)/g,b],/<br class="Apple-interchange-newline">/g,/<br>$/i])}function g(a){var b=0;return function(){return a+b++}}var h=function(){return navigator.userAgent.indexOf(" Edge/")!==-1};return{filter:d,innerText:e,trimHtml:f,createIdGenerator:g,isMsEdge:h}}),g("3",["8","c","d"],function(a,b,c){var d=function(){},e=function(b){return a.iOS===!1&&void 0!==b&&"function"==typeof b.setData&&c.isMsEdge()!==!0},f=function(a,c,d){if(!e(a))return!1;try{return a.clearData(),a.setData("text/html",c),a.setData("text/plain",d),a.setData(b.internalHtmlMime(),c),!0}catch(a){return!1}},g=function(a,b,c,d){f(a.clipboardData,b.html,b.text)?(a.preventDefault(),d()):c(b.html,d)},h=function(a){return function(c,d){var e=b.mark(c),f=a.dom.create("div",{contenteditable:"false"}),g=a.dom.c
reate("div",{contenteditable:"true"},e);a.dom.setStyles(f,{position:"fixed",left:"-3000px",width:"1000px",overflow:"hidden"}),f.appendChild(g),a.dom.add(a.getBody(),f);var h=a.selection.getRng();g.focus();var i=a.dom.createRng();i.selectNodeContents(g),a.selection.setRng(i),setTimeout(function(){f.parentNode.removeChild(f),a.selection.setRng(h),d()},0)}},i=function(a){return{html:a.selection.getContent(),text:a.selection.getContent({format:"text"})}},j=function(a){return function(b){a.selection.isCollapsed()===!1&&g(b,i(a),h(a),function(){a.execCommand("Delete")})}},k=function(a){return function(b){a.selection.isCollapsed()===!1&&g(b,i(a),h(a),d)}},l=function(a){a.on("cut",j(a)),a.on("copy",k(a))};return{register:l}}),g("k",["6"],function(a){return a("tinymce.html.Entities")}),g("e",["k"],function(a){var b=function(a){r
eturn!/<(?:(?!\/?(?:div|p|br))[^>]*|(?:div|p|br)\s+\w[^>]+)>/.test(a)},c=function(a){return a.replace(/\r?\n/g,"<br>")},d=function(b,c){var d,e=[],f="<"+b;if("object"==typeof c){for(d in c)c.hasOwnProperty(d)&&e.push(d+'="'+a.encodeAllRaw(c[d])+'"');e.length&&(f+=" "+e.join(" "))}return f+">"},e=function(a,b,c){var e,f,g,h=a.split(/\r?\n/),i=0,j=h.length,k=[],l=[],m=d(b,c),n="</"+b+">";if(1===h.length)return a;for(;i<j;i++)e=i===j-1,f=!e&&!h[i+1],g=!h[i]&&!k.length,k.push(h[i]?h[i]:" "),(e||f||g)&&(l.push(k.join("<br>")),k=[]),f&&i++;return 1===l.length?l[0]:m+l.join(n+m)+n},f=function(a,b,d){return b?e(a,b,d):c(a)};return{isPlainText:b,convert:f,toBRs:c,toBlockElements:e}}),g("f",["a"],function(a){var b=function(a){return/^https?:\/\/[\w\?\-\/+=.&%@~#]+$/i
.test(a)},c=function(a){return b(a)&&/.(gif|jpe?g|png)$/.test(a)},d=function(a,b,c){return a.undoManager.extra(function(){c(a,b)},function(){a.insertContent('<img src="'+b+'">')}),!0},e=function(a,b,c){return a.undoManager.extra(function(){c(a,b)},function(){a.execCommand("mceInsertLink",!1,b)}),!0},f=function(a,c,d){return!(a.selection.isCollapsed()!==!1||!b(c))&&e(a,c,d)},g=function(a,b,e){return!!c(b)&&d(a,b,e)},h=function(a,b){return a.insertContent(b,{merge:a.settings.paste_merge_formats!==!1,paste:!0}),!0},i=function(b,c){a.each([f,g,h],function(a){return a(b,c,h)!==!0})},j=function(a,b){a.settings.smart_paste===!1?h(a,b):i(a,b)};return{isImageUrl:c,isAbsoluteUrl:b,insertContent:j}}),g("2",["7","8","9","a","b","3","c","e","f","d"],function(a,b,c,d,e,f,g,h,i,j){return function(f){function k(a,b){var c,d,e=f.dom;if(d=b||g
.isMarked(a),a=g.unmark(a),c=f.fire("BeforePastePreProcess",{content:a,internal:d}),c=f.fire("PastePreProcess",c),a=c.content,!c.isDefaultPrevented()){if(f.hasEventListeners("PastePostProcess")&&!c.isDefaultPrevented()){var h=e.add(f.getBody(),"div",{style:"display:none"},a);c=f.fire("PastePostProcess",{node:h,internal:d}),e.remove(h),a=c.node.innerHTML}c.isDefaultPrevented()||i.insertContent(f,a)}}function l(a){a=f.dom.encode(a).replace(/\r\n/g,"\n"),a=h.convert(a,f.settings.forced_root_block,f.settings.forced_root_block_attrs),k(a,!1)}function m(){function a(a){var b,c,e,f=a.startContainer;if(b=a.getClientRects(),b.length)return b[0];if(a.collapsed&&1==f.nodeType){for(e=f.childNodes[C.startOffset];e&&3==e.nodeType&&!e.data.length;)e=e.nextSibling;if(e)return"BR"==e.tagName&&(c=d.doc.createTextNode("\ufeff"),e.parentNode.insertBefore(c,e),a=d.createRng()
,a.setStartBefore(c),a.setEndAfter(c),b=a.getClientRects(),d.remove(c)),b.length?b[0]:void 0}}var c,d=f.dom,e=f.getBody(),g=f.dom.getViewPort(f.getWin()),h=g.y,i=20;if(C=f.selection.getRng(),f.inline&&(c=f.selection.getScrollContainer(),c&&c.scrollTop>0&&(h=c.scrollTop)),C.getClientRects){var j=a(C);if(j)i=h+(j.top-d.getPos(e).y);else{i=h;var k=C.startContainer;k&&(3==k.nodeType&&k.parentNode!=e&&(k=k.parentNode),1==k.nodeType&&(i=d.getPos(k,c||e).y))}}B=d.add(f.getBody(),"div",{id:"mcepastebin",contentEditable:!0,"data-mce-bogus":"all",style:"position: absolute; top: "+i+"px;width: 10px; height: 10px; overflow: hidden; opacity: 0"},H),(b.ie||b.gecko)&&d.setStyle(B,"left","rtl"==d.getStyle(e,"direction",!0)?65535:-65535),d.bind(B,"beforedeactivate focusin focusout",function(a){a.stopPropagation()}),B.focus(),f.selectio
n.select(B,!0)}function n(){if(B){for(var a;a=f.dom.get("mcepastebin");)f.dom.remove(a),f.dom.unbind(a);C&&f.selection.setRng(C)}B=C=null}function o(){var a,b,c,d,e="";for(a=f.dom.select("div[id=mcepastebin]"),b=0;b<a.length;b++)c=a[b],c.firstChild&&"mcepastebin"==c.firstChild.id&&(c=c.firstChild),d=c.innerHTML,e!=H&&(e+=d);return e}function p(a){var b={};if(a){if(a.getData){var c=a.getData("Text");c&&c.length>0&&c.indexOf(I)==-1&&(b["text/plain"]=c)}if(a.types)for(var d=0;d<a.types.length;d++){var e=a.types[d];b[e]=a.getData(e)}}return b}function q(a){var b=p(a.clipboardData||f.getDoc().dataTransfer);return j.isMsEdge()?d.extend(b,{"text/html":""}):b}function r(a){return y(a,"text/html")||y(a,"text/plain")}function s(a){var b;return b=a.indexOf(","),b!==-1?a.substr(b+1):null}function t(a,b){return!a.images_dat
aimg_filter||a.images_dataimg_filter(b)}function u(a,b,c){a&&(f.selection.setRng(a),a=null);var d=b.result,e=s(d),g=new Image;if(g.src=d,t(f.settings,g)){var h,i,j=f.editorUpload.blobCache;i=j.findFirst(function(a){return a.base64()===e}),i?h=i:(h=j.create(J(),c,e),j.add(h)),k('<img src="'+h.blobUri()+'">',!1)}else k('<img src="'+d+'">',!1)}function v(a,b){function c(c){var d,e,f,g=!1;if(c)for(d=0;d<c.length;d++)if(e=c[d],/^image\/(jpeg|png|gif|bmp)$/.test(e.type)){var h=e.getAsFile?e.getAsFile():e;f=new FileReader,f.onload=u.bind(null,b,f,h),f.readAsDataURL(h),a.preventDefault(),g=!0}return g}var d=a.clipboardData||a.dataTransfer;if(f.settings.paste_data_images&&d)return c(d.items)||c(d.files)}function w(a){var b=a.clipboardData;return navigator.userAgent.indexOf("Android")!=-1&&b&&b.items&&0===b.items.length}function x(b){return a.getCaretRangeFromPoint(b.clientX,b.clientY,f.getDoc())}function y(a
,b){return b in a&&a[b].length>0}function z(a){return e.metaKeyPressed(a)&&86==a.keyCode||a.shiftKey&&45==a.keyCode}function A(){function a(a,b,c,d){var e,g;return y(a,"text/html")?e=a["text/html"]:(e=o(),e==H&&(c=!0)),e=j.trimHtml(e),B&&B.firstChild&&"mcepastebin"===B.firstChild.id&&(c=!0),n(),g=d===!1&&h.isPlainText(e),e.length&&!g||(c=!0),c&&(e=y(a,"text/plain")&&g?a["text/plain"]:j.innerText(e)),e==H?void(b||f.windowManager.alert("Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents.")):void(c?l(e):k(e,d))}function d(a){var b=a["text/plain"];return!!b&&0===b.indexOf("file://")}f.on("keydown",function(a){function c(a){z(a)&&!a.isDefaultPrevented()&&n()}if(z(a)&&!a.isDefaultPrevented()){if(D=a.shiftKey&&86==a.keyCode,D&&b.webkit&&navigator.
userAgent.indexOf("Version/")!=-1)return;if(a.stopImmediatePropagation(),F=(new Date).getTime(),b.ie&&D)return a.preventDefault(),void f.fire("paste",{ieFake:!0});n(),m(),f.once("keyup",c),f.once("paste",function(){f.off("keyup",c)})}});var e=function(){return C||f.selection.getRng()};f.on("paste",function(d){var h=(new Date).getTime(),i=q(d),j=(new Date).getTime()-h,k=(new Date).getTime()-F-j<1e3,l="text"==E.pasteFormat||D,p=y(i,g.internalHtmlMime());return D=!1,d.isDefaultPrevented()||w(d)?void n():!r(i)&&v(d,e())?void n():(k||d.preventDefault(),!b.ie||k&&!d.ieFake||y(i,"text/html")||(m(),f.dom.bind(B,"paste",function(a){a.stopPropagation()}),f.getDoc().execCommand("Paste",!1,null),i["text/html"]=o()),void(y(i,"text/html")?(d.preventDefault(),a(i,k,l,p)):c.setEditorTimeout(f,function(){a(i,k,l,p)},0)))}),f.on("dragstart dragend&quo
t;,function(a){G="dragstart"==a.type}),f.on("drop",function(a){var b,e;if(e=x(a),!a.isDefaultPrevented()&&!G){b=p(a.dataTransfer);var h=y(b,g.internalHtmlMime());if((r(b)&&!d(b)||!v(a,e))&&e&&f.settings.paste_filter_drop!==!1){var i=b["mce-internal"]||b["text/html"]||b["text/plain"];i&&(a.preventDefault(),c.setEditorTimeout(f,function(){f.undoManager.transact(function(){b["mce-internal"]&&f.execCommand("Delete"),f.selection.setRng(e),i=j.trimHtml(i),b["text/html"]?k(i,h):l(i)})}))}}}),f.on("dragover dragend",function(a){f.settings.paste_data_images&&a.preventDefault()})}var B,C,D,E=this,F=0,G=!1,H="%MCEPASTEBIN%",I="data:text/mce-internal,",J=j.createIdGenerator("mceclip");E.pasteHtml=k,E.pasteText=l,E.pasteImageData=v,f.on("preInit",function(){A(),f.parser.addNodeFilter("img",function(a,c,
d){function e(a){return a.data&&a.data.paste===!0}function g(a){a.attr("data-mce-object")||k===b.transparentSrc||a.remove()}function h(a){return 0===a.indexOf("webkit-fake-url")}function i(a){return 0===a.indexOf("data:")}if(!f.settings.paste_data_images&&e(d))for(var j=a.length;j--;){var k=a[j].attributes.map.src;k&&(h(k)?g(a[j]):!f.settings.allow_html_data_urls&&i(k)&&g(a[j]))}})})}}),g("i",["6"],function(a){return a("tinymce.html.Serializer")}),g("j",["6"],function(a){return a("tinymce.html.Node")}),g("5",["a","g","h","i","j","d"],function(a,b,c,d,e,f){function g(a){return/<font face="Times New Roman"|class="?Mso|style="[^"]*\bmso-|style='[^'']*\bmso-|w:WordDocument/i.test(a)||/class="OutlineElement/.test(a)||/id="?docs\-internal\-guid\-/.test(a)
}function h(b){var c,d;return d=[/^[IVXLMCD]{1,2}\.[ \u00a0]/,/^[ivxlmcd]{1,2}\.[ \u00a0]/,/^[a-z]{1,2}[\.\)][ \u00a0]/,/^[A-Z]{1,2}[\.\)][ \u00a0]/,/^[0-9]+\.[ \u00a0]/,/^[\u3007\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d]+\.[ \u00a0]/,/^[\u58f1\u5f10\u53c2\u56db\u4f0d\u516d\u4e03\u516b\u4e5d\u62fe]+\.[ \u00a0]/],b=b.replace(/^[\u00a0 ]+/,""),a.each(d,function(a){if(a.test(b))return c=!0,!1}),c}function i(a){return/^[\s\u00a0]*[\u2022\u00b7\u00a7\u25CF]\s*/.test(a)}function j(j){var k=j.settings;j.on("BeforePastePreProcess",function(l){function m(a){function b(a){var c="";if(3===a.type)return a.value;if(a=a.firstChild)do c+=b(a);while(a=a.next);return c}function c(a,b){if(3===a.type&&b.test(a.value))return a.value=a.value.replace(b,""),!1;if(a=a.firstChild)do if(!c(a,b))return!1;while(a=a.next);return!0}function d(a){if(a._listIgnore)return void a.remove();if(a=a.firstChild)do d(a);while(a=a.next)}function f(a,b,f){var h=a.
_listLevel||k;h!=k&&(h<k?g&&(g=g.parent.parent):(j=g,g=null)),g&&g.name==b?g.append(a):(j=j||g,g=new e(b,1),f>1&&g.attr("start",""+f),a.wrap(g)),a.name="li",h>k&&j&&j.lastChild.append(g),k=h,d(a),c(a,/^\u00a0+/),c(a,/^\s*([\u2022\u00b7\u00a7\u25CF]|\w+\.)/),c(a,/^\u00a0+/)}for(var g,j,k=1,l=[],m=a.firstChild;"undefined"!=typeof m&&null!==m;)if(l.push(m),m=m.walk(),null!==m)for(;"undefined"!=typeof m&&m.parent!==a;)m=m.walk();for(var n=0;n<l.length;n++)if(a=l[n],"p"==a.name&&a.firstChild){var o=b(a);if(i(o)){f(a,"ul");continue}if(h(o)){var p=/([0-9]+)\./.exec(o),q=1;p&&(q=parseInt(p[1],10)),f(a,"ol",q);continue}if(a._listLevel){f(a,"ul",1);continue}g=null}else j=g,g=null}function n(b,c){var d,f={},g=j.dom.parseStyle(c);return a.each(g,function(a,e){switch(e){case"mso-list":d=/\w+ \w+([0-9]+)/i.e
xec(c),d&&(b._listLevel=parseInt(d[1],10)),/Ignore/i.test(a)&&b.firstChild&&(b._listIgnore=!0,b.firstChild._listIgnore=!0);break;case"horiz-align":e="text-align";break;case"vert-align":e="vertical-align";break;case"font-color":case"mso-foreground":e="color";break;case"mso-background":case"mso-highlight":e="background";break;case"font-weight":case"font-style":return void("normal"!=a&&(f[e]=a));case"mso-element":if(/^(comment|comment-list)$/i.test(a))return void b.remove()}return 0===e.indexOf("mso-comment")?void b.remove():void(0!==e.indexOf("mso-")&&("all"==o||p&&p[e])&&(f[e]=a))}),/(bold)/i.test(f["font-weight"])&&(delete f["font-weight"],b.wrap(new e("b",1))),/(italic)/i.test(f["font-style"])&&(delete f[
"font-style"],b.wrap(new e("i",1))),f=j.dom.serializeStyle(f,b.name),f?f:null}var o,p,q=l.content;if(q=q.replace(/<b[^>]+id="?docs-internal-[^>]*>/gi,""),q=q.replace(/<br class="?Apple-interchange-newline"?>/gi,""),o=k.paste_retain_style_properties,o&&(p=a.makeMap(o.split(/[, ]/))),k.paste_enable_default_filters!==!1&&g(l.content)){l.wordContent=!0,q=f.filter(q,[/<!--[\s\S]+?-->/gi,/<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,[/<(\/?)s>/gi,"<$1strike>"],[/ /gi,"\xa0"],[/<span\s+style\s*=\s*"\s*mso-spacerun\s*:\s*yes\s*;?\s*"\s*>([\s\u00a0]*)<\/span>/gi,function(a,b){return b.length>0?b.replace(/./," ").slice(Math.floor(b.length/2)).split("").join("\xa0"):""}]]);var r=k.paste_word_valid_elements;r||(r=&q
uot;-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-h1,-h2,-h3,-h4,-h5,-h6,-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody");var s=new c({valid_elements:r,valid_children:"-li[p]"});a.each(s.elements,function(a){a.attributes["class"]||(a.attributes["class"]={},a.attributesOrder.push("class")),a.attributes.style||(a.attributes.style={},a.attributesOrder.push("style"))});var t=new b({},s);t.addAttributeFilter("style",function(a){for(var b,c=a.length;c--;)b=a[c],b.attr("style",n(b,b.attr("style"))),"span"==b.name&&b.parent&&!b.attributes.length&&b.unwrap()}),t.addAttributeFilter("class",function(a){for(var b,c,d=a.length;d--;)b=a[d],c=b.attr("class"),/^(MsoCommentReference|MsoCommentText|msoDel)$/i.test(c)&&b.remove(),b.attr("class",null)}),t.addNodeFilter(&qu
ot;del",function(a){for(var b=a.length;b--;)a[b].remove()}),t.addNodeFilter("a",function(a){for(var b,c,d,e=a.length;e--;)if(b=a[e],c=b.attr("href"),d=b.attr("name"),c&&c.indexOf("#_msocom_")!=-1)b.remove();else if(c&&0===c.indexOf("file://")&&(c=c.split("#")[1],c&&(c="#"+c)),c||d){if(d&&!/^_?(?:toc|edn|ftn)/i.test(d)){b.unwrap();continue}b.attr({href:c,name:d})}else b.unwrap()});var u=t.parse(q);k.paste_convert_word_fake_lists!==!1&&m(u),l.content=new d({validate:k.validate},s).serialize(u)}})}return j.isWordContent=g,j}),g("4",["8","a","5","d"],function(a,b,c,d){"use strict";return function(e){function f(a){e.on("BeforePastePreProcess",function(b){b.content=a(b.content)})}function g(a){e.on("PastePostProcess",function(b){a(b.node)})}function h(a){if(!c.isWordContent(a))return a;var
f=[];b.each(e.schema.getBlockElements(),function(a,b){f.push(b)});var g=new RegExp("(?:<br> [\\s\\r\\n]+|<br>)*(<\\/?("+f.join("|")+")[^>]*>)(?:<br> [\\s\\r\\n]+|<br>)*","g");return a=d.filter(a,[[g,"$1"]]),a=d.filter(a,[[/<br><br>/g,"<BR><BR>"],[/<br>/g," "],[/<BR><BR>/g,"<br>"]])}function i(a){if(c.isWordContent(a))return a;var b=e.settings.paste_webkit_styles;if(e.settings.paste_remove_styles_if_webkit===!1||"all"==b)return a;if(b&&(b=b.split(/[, ]/)),b){var d=e.dom,f=e.selection.getNode();a=a.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi,function(a,c,e,g){var h=d.parseStyle(e,"span"),i={};if("none"===b)return c+g;for(var j=0;j<b.length;j++){var k=h[b[j]],l=d.getStyle(f,b[j],!0);/color/.test(b[j])&&(k=d.toHex(k),l=d.toHex(l)),l!=
k&&(i[b[j]]=k)}return i=d.serializeStyle(i,"span"),i?c+' style="'+i+'"'+g:c+g})}else a=a.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi,"$1$3");return a=a.replace(/(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi,function(a,b,c,d){return b+' style="'+c+'"'+d})}function j(a){e.$("a",a).find("font,u").each(function(a,b){e.dom.remove(b,!0)})}a.webkit&&f(i),a.ie&&(f(h),g(j))}}),g("0",["1","2","3","4","5"],function(a,b,c,d,e){var f;return a.add("paste",function(g){function h(){return f||g.settings.paste_plaintext_inform===!1}function i(){if("text"==k.pasteFormat)k.pasteFormat="html",g.fire("PastePlainTextToggle",{state:!1});else if(k.pasteFormat="text",g.fire("PastePlainTextToggle",{state:!0}),!h()){var a=g.translate("Paste is now in p
lain text mode. Contents will now be pasted as plain text until you toggle this option off.");g.notificationManager.open({text:a,type:"info"}),f=!0}g.focus()}function j(){var a=this;a.active("text"===k.pasteFormat),g.on("PastePlainTextToggle",function(b){a.active(b.state)})}var k,l=this,m=g.settings;return/(^|[ ,])powerpaste([, ]|$)/.test(m.plugins)&&a.get("powerpaste")?void("undefined"!=typeof console&&console.log&&console.log("PowerPaste is incompatible with Paste plugin! Remove 'paste' from the 'plugins' option.")):(l.clipboard=k=new b(g),l.quirks=new d(g),l.wordFilter=new e(g),g.settings.paste_as_text&&(l.clipboard.pasteFormat="text"),m.paste_preprocess&&g.on("PastePreProcess",function(a){m.paste_preprocess.call(l,l,a)}),m.paste_postprocess&&g.on("PastePostProcess",function(a){m.paste_postprocess.call(l,l,a)}),g.addCommand("mceInsert
ClipboardContent",function(a,b){b.content&&l.clipboard.pasteHtml(b.content,b.internal),b.text&&l.clipboard.pasteText(b.text)}),g.settings.paste_block_drop&&g.on("dragend dragover draggesture dragdrop drop drag",function(a){a.preventDefault(),a.stopPropagation()}),g.settings.paste_data_images||g.on("drop",function(a){var b=a.dataTransfer;b&&b.files&&b.files.length>0&&a.preventDefault()}),g.addCommand("mceTogglePlainTextPaste",i),g.addButton("pastetext",{icon:"pastetext",tooltip:"Paste as text",onclick:i,onPostRender:j}),g.addMenuItem("pastetext",{text:"Paste as text",selectable:!0,active:k.pasteFormat,onclick:i,onPostRender:j}),void c.register(g))}),function(){}}),d("0")()}();
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginstabfocuspluginjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/tabfocus/plugin.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/tabfocus/plugin.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/tabfocus/plugin.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,120 +1,348 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+(function () {
+
+var defs = {}; // id -> {dependencies, definition, instance (possibly undefined)}
+
+// Used when there is no 'main' module.
+// The name is probably (hopefully) unique so minification removes for releases.
+var register_3795 = function (id) {
+ var module = dem(id);
+ var fragments = id.split('.');
+ var target = Function('return this;')();
+ for (var i = 0; i < fragments.length - 1; ++i) {
+ if (target[fragments[i]] === undefined)
+ target[fragments[i]] = {};
+ target = target[fragments[i]];
+ }
+ target[fragments[fragments.length - 1]] = module;
+};
+
+var instantiate = function (id) {
+ var actual = defs[id];
+ var dependencies = actual.deps;
+ var definition = actual.defn;
+ var len = dependencies.length;
+ var instances = new Array(len);
+ for (var i = 0; i < len; ++i)
+ instances[i] = dem(dependencies[i]);
+ var defResult = definition.apply(null, instances);
+ if (defResult === undefined)
+ throw 'module [' + id + '] returned undefined';
+ actual.instance = defResult;
+};
+
+var def = function (id, dependencies, definition) {
+ if (typeof id !== 'string')
+ throw 'module id must be a string';
+ else if (dependencies === undefined)
+ throw 'no dependencies for ' + id;
+ else if (definition === undefined)
+ throw 'no definition function for ' + id;
+ defs[id] = {
+ deps: dependencies,
+ defn: definition,
+ instance: undefined
+ };
+};
+
+var dem = function (id) {
+ var actual = defs[id];
+ if (actual === undefined)
+ throw 'module [' + id + '] was undefined';
+ else if (actual.instance === undefined)
+ instantiate(id);
+ return actual.instance;
+};
+
+var req = function (ids, callback) {
+ var len = ids.length;
+ var instances = new Array(len);
+ for (var i = 0; i < len; ++i)
+ instances.push(dem(ids[i]));
+ callback.apply(null, callback);
+};
+
+var ephox = {};
+
+ephox.bolt = {
+ module: {
+ api: {
+ define: def,
+ require: req,
+ demand: dem
+ }
+ }
+};
+
+var define = def;
+var require = req;
+var demand = dem;
+// this helps with minificiation when using a lot of global references
+var defineGlobal = function (id, ref) {
+ define(id, [], function () { return ref; });
+};
+/*jsc
+["tinymce.plugins.tabfocus.Plugin","tinymce.core.PluginManager","tinymce.core.dom.DOMUtils","tinymce.core.util.Tools","tinymce.core.EditorManager","tinymce.core.util.Delay","tinymce.core.Env","global!tinymce.util.Tools.resolve"]
+jsc*/
+defineGlobal("global!tinymce.util.Tools.resolve", tinymce.util.Tools.resolve);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * plugin.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ResolveGlobal.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/*global tinymce:true */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.PluginManager',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.PluginManager');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-tinymce.PluginManager.add('tabfocus', function(editor) {
- var DOM = tinymce.DOM, each = tinymce.each, explode = tinymce.explode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function tabCancel(e) {
- if (e.keyCode === 9 && !e.ctrlKey && !e.altKey && !e.metaKey) {
- e.preventDefault();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.DOMUtils',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.dom.DOMUtils');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function tabHandler(e) {
- var x, el, v, i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.keyCode !== 9 || e.ctrlKey || e.altKey || e.metaKey || e.isDefaultPrevented()) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.Tools',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.util.Tools');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function find(direction) {
- el = DOM.select(':input:enabled,*[tabindex]:not(iframe)');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function canSelectRecursive(e) {
- return e.nodeName === "BODY" || (e.type != 'hidden' &&
- e.style.display != "none" &&
- e.style.visibility != "hidden" && canSelectRecursive(e.parentNode));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.EditorManager',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.EditorManager');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function canSelect(el) {
- return /INPUT|TEXTAREA|BUTTON/.test(el.tagName) && tinymce.get(e.id) && el.tabIndex != -1 && canSelectRecursive(el);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(el, function(e, i) {
- if (e.id == editor.id) {
- x = i;
- return false;
- }
- });
- if (direction > 0) {
- for (i = x + 1; i < el.length; i++) {
- if (canSelect(el[i])) {
- return el[i];
- }
- }
- } else {
- for (i = x - 1; i >= 0; i--) {
- if (canSelect(el[i])) {
- return el[i];
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.Delay',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.util.Delay');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- v = explode(editor.getParam('tab_focus', editor.getParam('tabfocus_elements', ':prev,:next')));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.Env',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.Env');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (v.length == 1) {
- v[1] = v[0];
- v[0] = ':prev';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Plugin.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Find element to focus
- if (e.shiftKey) {
- if (v[0] == ':prev') {
- el = find(-1);
- } else {
- el = DOM.get(v[0]);
- }
- } else {
- if (v[1] == ':next') {
- el = find(1);
- } else {
- el = DOM.get(v[1]);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * This class contains all core logic for the code plugin.
+ *
+ * @class tinymce.tabfocus.Plugin
+ * @private
+ */
+define(
+ 'tinymce.plugins.tabfocus.Plugin',
+ [
+ 'tinymce.core.PluginManager',
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.core.util.Tools',
+ 'tinymce.core.EditorManager',
+ 'tinymce.core.util.Delay',
+ 'tinymce.core.Env'
+ ],
+ function (PluginManager, DOMUtils, Tools, EditorManager, Delay, Env) {
+ PluginManager.add('tabfocus', function (editor) {
+ var DOM = DOMUtils.DOM;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (el) {
- var focusEditor = tinymce.get(el.id || el.name);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function tabCancel(e) {
+ if (e.keyCode === 9 && !e.ctrlKey && !e.altKey && !e.metaKey) {
+ e.preventDefault();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (el.id && focusEditor) {
- focusEditor.focus();
- } else {
- tinymce.util.Delay.setTimeout(function() {
- if (!tinymce.Env.webkit) {
- window.focus();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function tabHandler(e) {
+ var x, el, v, i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- el.focus();
- }, 10);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.keyCode !== 9 || e.ctrlKey || e.altKey || e.metaKey || e.isDefaultPrevented()) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- e.preventDefault();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function find(direction) {
+ el = DOM.select(':input:enabled,*[tabindex]:not(iframe)');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('init', function() {
- if (editor.inline) {
- // Remove default tabIndex in inline mode
- tinymce.DOM.setAttrib(editor.getBody(), 'tabIndex', null);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function canSelectRecursive(e) {
+ return e.nodeName === "BODY" || (e.type != 'hidden' &&
+ e.style.display != "none" &&
+ e.style.visibility != "hidden" && canSelectRecursive(e.parentNode));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('keyup', tabCancel);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function canSelect(el) {
+ return /INPUT|TEXTAREA|BUTTON/.test(el.tagName) && EditorManager.get(e.id) && el.tabIndex != -1 && canSelectRecursive(el);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (tinymce.Env.gecko) {
- editor.on('keypress keydown', tabHandler);
- } else {
- editor.on('keydown', tabHandler);
- }
- });
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(el, function (e, i) {
+ if (e.id == editor.id) {
+ x = i;
+ return false;
+ }
+ });
+ if (direction > 0) {
+ for (i = x + 1; i < el.length; i++) {
+ if (canSelect(el[i])) {
+ return el[i];
+ }
+ }
+ } else {
+ for (i = x - 1; i >= 0; i--) {
+ if (canSelect(el[i])) {
+ return el[i];
+ }
+ }
+ }
+
+ return null;
+ }
+
+ v = Tools.explode(editor.getParam('tab_focus', editor.getParam('tabfocus_elements', ':prev,:next')));
+
+ if (v.length == 1) {
+ v[1] = v[0];
+ v[0] = ':prev';
+ }
+
+ // Find element to focus
+ if (e.shiftKey) {
+ if (v[0] == ':prev') {
+ el = find(-1);
+ } else {
+ el = DOM.get(v[0]);
+ }
+ } else {
+ if (v[1] == ':next') {
+ el = find(1);
+ } else {
+ el = DOM.get(v[1]);
+ }
+ }
+
+ if (el) {
+ var focusEditor = EditorManager.get(el.id || el.name);
+
+ if (el.id && focusEditor) {
+ focusEditor.focus();
+ } else {
+ Delay.setTimeout(function () {
+ if (!Env.webkit) {
+ window.focus();
+ }
+
+ el.focus();
+ }, 10);
+ }
+
+ e.preventDefault();
+ }
+ }
+
+ editor.on('init', function () {
+ if (editor.inline) {
+ // Remove default tabIndex in inline mode
+ DOM.setAttrib(editor.getBody(), 'tabIndex', null);
+ }
+
+ editor.on('keyup', tabCancel);
+
+ if (Env.gecko) {
+ editor.on('keypress keydown', tabHandler);
+ } else {
+ editor.on('keydown', tabHandler);
+ }
+ });
+ });
+
+
+ return function () { };
+ }
+);
+dem('tinymce.plugins.tabfocus.Plugin')();
+})();
</ins></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginstabfocuspluginminjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/tabfocus/plugin.min.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/tabfocus/plugin.min.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/tabfocus/plugin.min.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1 +1 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-tinymce.PluginManager.add("tabfocus",function(e){function t(e){9!==e.keyCode||e.ctrlKey||e.altKey||e.metaKey||e.preventDefault()}function n(t){function n(n){function o(e){return"BODY"===e.nodeName||"hidden"!=e.type&&"none"!=e.style.display&&"hidden"!=e.style.visibility&&o(e.parentNode)}function l(e){return/INPUT|TEXTAREA|BUTTON/.test(e.tagName)&&tinymce.get(t.id)&&e.tabIndex!=-1&&o(e)}if(s=r.select(":input:enabled,*[tabindex]:not(iframe)"),i(s,function(t,n){if(t.id==e.id)return a=n,!1}),n>0){for(u=a+1;u<s.length;u++)if(l(s[u]))return s[u]}else for(u=a-1;u>=0;u--)if(l(s[u]))return s[u];return null}var a,s,l,u;if(!(9!==t.keyCode||t.ctrlKey||t.altKey||t.metaKey||t.isDefaultPrevented())&&(l=o(e.getParam("tab_focus",e.getParam("tabfocus_elements",&qu
ot;:prev,:next"))),1==l.length&&(l[1]=l[0],l[0]=":prev"),s=t.shiftKey?":prev"==l[0]?n(-1):r.get(l[0]):":next"==l[1]?n(1):r.get(l[1]))){var c=tinymce.get(s.id||s.name);s.id&&c?c.focus():tinymce.util.Delay.setTimeout(function(){tinymce.Env.webkit||window.focus(),s.focus()},10),t.preventDefault()}}var r=tinymce.DOM,i=tinymce.each,o=tinymce.explode;e.on("init",function(){e.inline&&tinymce.DOM.setAttrib(e.getBody(),"tabIndex",null),e.on("keyup",t),tinymce.Env.gecko?e.on("keypress keydown",n):e.on("keydown",n)})});
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+!function(){var a={},b=function(b){for(var c=a[b],e=c.deps,f=c.defn,g=e.length,h=new Array(g),i=0;i<g;++i)h[i]=d(e[i]);var j=f.apply(null,h);if(void 0===j)throw"module ["+b+"] returned undefined";c.instance=j},c=function(b,c,d){if("string"!=typeof b)throw"module id must be a string";if(void 0===c)throw"no dependencies for "+b;if(void 0===d)throw"no definition function for "+b;a[b]={deps:c,defn:d,instance:void 0}},d=function(c){var d=a[c];if(void 0===d)throw"module ["+c+"] was undefined";return void 0===d.instance&&b(c),d.instance},e=function(a,b){for(var c=a.length,e=new Array(c),f=0;f<c;++f)e.push(d(a[f]));b.apply(null,b)},f={};f.bolt={module:{api:{define:c,require:e,demand:d}}};var g=c,h=function(a,b){g(a,[],function(){return b})};h("7",tinymce.util.Tools.resolve),g("1",[&q
uot;7"],function(a){return a("tinymce.PluginManager")}),g("2",["7"],function(a){return a("tinymce.dom.DOMUtils")}),g("3",["7"],function(a){return a("tinymce.util.Tools")}),g("4",["7"],function(a){return a("tinymce.EditorManager")}),g("5",["7"],function(a){return a("tinymce.util.Delay")}),g("6",["7"],function(a){return a("tinymce.Env")}),g("0",["1","2","3","4","5","6"],function(a,b,c,d,e,f){return a.add("tabfocus",function(a){function g(a){9!==a.keyCode||a.ctrlKey||a.altKey||a.metaKey||a.preventDefault()}function h(b){function g(e){function f(a){return"BODY"===a.nodeName||"hidden"!=a.type&&"none"!=a.style.display&&"hidden"!=a.style.visibility&&f(a.parentNode)}function g(a){return/
INPUT|TEXTAREA|BUTTON/.test(a.tagName)&&d.get(b.id)&&a.tabIndex!=-1&&f(a)}if(j=i.select(":input:enabled,*[tabindex]:not(iframe)"),c.each(j,function(b,c){if(b.id==a.id)return h=c,!1}),e>0){for(l=h+1;l<j.length;l++)if(g(j[l]))return j[l]}else for(l=h-1;l>=0;l--)if(g(j[l]))return j[l];return null}var h,j,k,l;if(!(9!==b.keyCode||b.ctrlKey||b.altKey||b.metaKey||b.isDefaultPrevented())&&(k=c.explode(a.getParam("tab_focus",a.getParam("tabfocus_elements",":prev,:next"))),1==k.length&&(k[1]=k[0],k[0]=":prev"),j=b.shiftKey?":prev"==k[0]?g(-1):i.get(k[0]):":next"==k[1]?g(1):i.get(k[1]))){var m=d.get(j.id||j.name);j.id&&m?m.focus():e.setTimeout(function(){f.webkit||window.focus(),j.focus()},10),b.preventDefault()}}var i=b.DOM;a.on("init",function(){a.inline&&i.setAttrib(a.getBody(),"tabIndex",null),a.on("keyup",g),f.gecko?a.on("
;keypress keydown",h):a.on("keydown",h)})}),function(){}}),d("0")()}();
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginstextcolorpluginjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/textcolor/plugin.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/textcolor/plugin.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/textcolor/plugin.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,297 +1,483 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+(function () {
+
+var defs = {}; // id -> {dependencies, definition, instance (possibly undefined)}
+
+// Used when there is no 'main' module.
+// The name is probably (hopefully) unique so minification removes for releases.
+var register_3795 = function (id) {
+ var module = dem(id);
+ var fragments = id.split('.');
+ var target = Function('return this;')();
+ for (var i = 0; i < fragments.length - 1; ++i) {
+ if (target[fragments[i]] === undefined)
+ target[fragments[i]] = {};
+ target = target[fragments[i]];
+ }
+ target[fragments[fragments.length - 1]] = module;
+};
+
+var instantiate = function (id) {
+ var actual = defs[id];
+ var dependencies = actual.deps;
+ var definition = actual.defn;
+ var len = dependencies.length;
+ var instances = new Array(len);
+ for (var i = 0; i < len; ++i)
+ instances[i] = dem(dependencies[i]);
+ var defResult = definition.apply(null, instances);
+ if (defResult === undefined)
+ throw 'module [' + id + '] returned undefined';
+ actual.instance = defResult;
+};
+
+var def = function (id, dependencies, definition) {
+ if (typeof id !== 'string')
+ throw 'module id must be a string';
+ else if (dependencies === undefined)
+ throw 'no dependencies for ' + id;
+ else if (definition === undefined)
+ throw 'no definition function for ' + id;
+ defs[id] = {
+ deps: dependencies,
+ defn: definition,
+ instance: undefined
+ };
+};
+
+var dem = function (id) {
+ var actual = defs[id];
+ if (actual === undefined)
+ throw 'module [' + id + '] was undefined';
+ else if (actual.instance === undefined)
+ instantiate(id);
+ return actual.instance;
+};
+
+var req = function (ids, callback) {
+ var len = ids.length;
+ var instances = new Array(len);
+ for (var i = 0; i < len; ++i)
+ instances.push(dem(ids[i]));
+ callback.apply(null, callback);
+};
+
+var ephox = {};
+
+ephox.bolt = {
+ module: {
+ api: {
+ define: def,
+ require: req,
+ demand: dem
+ }
+ }
+};
+
+var define = def;
+var require = req;
+var demand = dem;
+// this helps with minificiation when using a lot of global references
+var defineGlobal = function (id, ref) {
+ define(id, [], function () { return ref; });
+};
+/*jsc
+["tinymce.plugins.textcolor.Plugin","tinymce.core.dom.DOMUtils","tinymce.core.PluginManager","tinymce.core.util.I18n","tinymce.core.util.Tools","global!tinymce.util.Tools.resolve"]
+jsc*/
+defineGlobal("global!tinymce.util.Tools.resolve", tinymce.util.Tools.resolve);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * plugin.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ResolveGlobal.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/*global tinymce:true */
-/*eslint consistent-this:0 */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.DOMUtils',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.dom.DOMUtils');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-tinymce.PluginManager.add('textcolor', function(editor) {
- var cols, rows;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rows = {
- forecolor: editor.settings.forecolor_rows || editor.settings.textcolor_rows || 5,
- backcolor: editor.settings.backcolor_rows || editor.settings.textcolor_rows || 5
- };
- cols = {
- forecolor: editor.settings.forecolor_cols || editor.settings.textcolor_cols || 8,
- backcolor: editor.settings.backcolor_cols || editor.settings.textcolor_cols || 8
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.PluginManager',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.PluginManager');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getCurrentColor(format) {
- var color;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.dom.getParents(editor.selection.getStart(), function(elm) {
- var value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.I18n',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.util.I18n');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ((value = elm.style[format == 'forecolor' ? 'color' : 'background-color'])) {
- color = value;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return color;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.Tools',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.util.Tools');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function mapColors(type) {
- var i, colors = [], colorMap;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Plugin.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- colorMap = [
- "000000", "Black",
- "993300", "Burnt orange",
- "333300", "Dark olive",
- "003300", "Dark green",
- "003366", "Dark azure",
- "000080", "Navy Blue",
- "333399", "Indigo",
- "333333", "Very dark gray",
- "800000", "Maroon",
- "FF6600", "Orange",
- "808000", "Olive",
- "008000", "Green",
- "008080", "Teal",
- "0000FF", "Blue",
- "666699", "Grayish blue",
- "808080", "Gray",
- "FF0000", "Red",
- "FF9900", "Amber",
- "99CC00", "Yellow green",
- "339966", "Sea green",
- "33CCCC", "Turquoise",
- "3366FF", "Royal blue",
- "800080", "Purple",
- "999999", "Medium gray",
- "FF00FF", "Magenta",
- "FFCC00", "Gold",
- "FFFF00", "Yellow",
- "00FF00", "Lime",
- "00FFFF", "Aqua",
- "00CCFF", "Sky blue",
- "993366", "Red violet",
- "FFFFFF", "White",
- "FF99CC", "Pink",
- "FFCC99", "Peach",
- "FFFF99", "Light yellow",
- "CCFFCC", "Pale green",
- "CCFFFF", "Pale cyan",
- "99CCFF", "Light sky blue",
- "CC99FF", "Plum"
- ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * This class contains all core logic for the code plugin.
+ *
+ * @class tinymce.textcolor.Plugin
+ * @private
+ */
+define(
+ 'tinymce.plugins.textcolor.Plugin',
+ [
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.core.PluginManager',
+ 'tinymce.core.util.I18n',
+ 'tinymce.core.util.Tools'
+ ],
+ function (DOMUtils, PluginManager, I18n, Tools) {
+ var translate = I18n.translate;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- colorMap = editor.settings.textcolor_map || colorMap;
- colorMap = editor.settings[type + '_map'] || colorMap;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ PluginManager.add('textcolor', function (editor) {
+ var cols, rows;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0; i < colorMap.length; i += 2) {
- colors.push({
- text: colorMap[i + 1],
- color: '#' + colorMap[i]
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rows = {
+ forecolor: editor.settings.forecolor_rows || editor.settings.textcolor_rows || 5,
+ backcolor: editor.settings.backcolor_rows || editor.settings.textcolor_rows || 5
+ };
+ cols = {
+ forecolor: editor.settings.forecolor_cols || editor.settings.textcolor_cols || 8,
+ backcolor: editor.settings.backcolor_cols || editor.settings.textcolor_cols || 8
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return colors;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getCurrentColor(format) {
+ var color;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function renderColorPicker() {
- var ctrl = this, colors, color, html, last, x, y, i, id = ctrl._id, count = 0, type;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.dom.getParents(editor.selection.getStart(), function (elm) {
+ var value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- type = ctrl.settings.origin;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((value = elm.style[format == 'forecolor' ? 'color' : 'background-color'])) {
+ color = value;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getColorCellHtml(color, title) {
- var isNoColor = color == 'transparent';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return color;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<td class="mce-grid-cell' + (isNoColor ? ' mce-colorbtn-trans' : '') + '">' +
- '<div id="' + id + '-' + (count++) + '"' +
- ' data-mce-color="' + (color ? color : '') + '"' +
- ' role="option"' +
- ' tabIndex="-1"' +
- ' style="' + (color ? 'background-color: ' + color : '') + '"' +
- ' title="' + tinymce.translate(title) + '">' +
- (isNoColor ? '×' : '') +
- '</div>' +
- '</td>'
- );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function mapColors(type) {
+ var i, colors = [], colorMap;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- colors = mapColors(type);
- colors.push({
- text: tinymce.translate("No color"),
- color: "transparent"
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ colorMap = [
+ "000000", "Black",
+ "993300", "Burnt orange",
+ "333300", "Dark olive",
+ "003300", "Dark green",
+ "003366", "Dark azure",
+ "000080", "Navy Blue",
+ "333399", "Indigo",
+ "333333", "Very dark gray",
+ "800000", "Maroon",
+ "FF6600", "Orange",
+ "808000", "Olive",
+ "008000", "Green",
+ "008080", "Teal",
+ "0000FF", "Blue",
+ "666699", "Grayish blue",
+ "808080", "Gray",
+ "FF0000", "Red",
+ "FF9900", "Amber",
+ "99CC00", "Yellow green",
+ "339966", "Sea green",
+ "33CCCC", "Turquoise",
+ "3366FF", "Royal blue",
+ "800080", "Purple",
+ "999999", "Medium gray",
+ "FF00FF", "Magenta",
+ "FFCC00", "Gold",
+ "FFFF00", "Yellow",
+ "00FF00", "Lime",
+ "00FFFF", "Aqua",
+ "00CCFF", "Sky blue",
+ "993366", "Red violet",
+ "FFFFFF", "White",
+ "FF99CC", "Pink",
+ "FFCC99", "Peach",
+ "FFFF99", "Light yellow",
+ "CCFFCC", "Pale green",
+ "CCFFFF", "Pale cyan",
+ "99CCFF", "Light sky blue",
+ "CC99FF", "Plum"
+ ];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- html = '<table class="mce-grid mce-grid-border mce-colorbutton-grid" role="list" cellspacing="0"><tbody>';
- last = colors.length - 1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ colorMap = editor.settings.textcolor_map || colorMap;
+ colorMap = editor.settings[type + '_map'] || colorMap;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (y = 0; y < rows[type]; y++) {
- html += '<tr>';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0; i < colorMap.length; i += 2) {
+ colors.push({
+ text: colorMap[i + 1],
+ color: '#' + colorMap[i]
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (x = 0; x < cols[type]; x++) {
- i = y * cols[type] + x;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return colors;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (i > last) {
- html += '<td></td>';
- } else {
- color = colors[i];
- html += getColorCellHtml(color.color, color.text);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function renderColorPicker() {
+ var self = this, colors, color, html, last, x, y, i, id = self._id, count = 0, type;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- html += '</tr>';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ type = self.settings.origin;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.settings.color_picker_callback) {
- html += (
- '<tr>' +
- '<td colspan="' + cols[type] + '" class="mce-custom-color-btn">' +
- '<div id="' + id + '-c" class="mce-widget mce-btn mce-btn-small mce-btn-flat" ' +
- 'role="button" tabindex="-1" aria-labelledby="' + id + '-c" style="width: 100%">' +
- '<button type="button" role="presentation" tabindex="-1">' + tinymce.translate('Custom...') + '</button>' +
- '</div>' +
- '</td>' +
- '</tr>'
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getColorCellHtml(color, title) {
+ var isNoColor = color == 'transparent';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- html += '<tr>';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<td class="mce-grid-cell' + (isNoColor ? ' mce-colorbtn-trans' : '') + '">' +
+ '<div id="' + id + '-' + (count++) + '"' +
+ ' data-mce-color="' + (color ? color : '') + '"' +
+ ' role="option"' +
+ ' tabIndex="-1"' +
+ ' style="' + (color ? 'background-color: ' + color : '') + '"' +
+ ' title="' + translate(title) + '">' +
+ (isNoColor ? '×' : '') +
+ '</div>' +
+ '</td>'
+ );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (x = 0; x < cols[type]; x++) {
- html += getColorCellHtml('', 'Custom color');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ colors = mapColors(type);
+ colors.push({
+ text: translate("No color"),
+ color: "transparent"
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- html += '</tr>';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ html = '<table class="mce-grid mce-grid-border mce-colorbutton-grid" role="list" cellspacing="0"><tbody>';
+ last = colors.length - 1;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- html += '</tbody></table>';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (y = 0; y < rows[type]; y++) {
+ html += '<tr>';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return html;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (x = 0; x < cols[type]; x++) {
+ i = y * cols[type] + x;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function applyFormat(format, value) {
- editor.undoManager.transact(function() {
- editor.focus();
- editor.formatter.apply(format, {value: value});
- editor.nodeChanged();
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (i > last) {
+ html += '<td></td>';
+ } else {
+ color = colors[i];
+ html += getColorCellHtml(color.color, color.text);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function removeFormat(format) {
- editor.undoManager.transact(function() {
- editor.focus();
- editor.formatter.remove(format, {value: null}, null, true);
- editor.nodeChanged();
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ html += '</tr>';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function onPanelClick(e) {
- var buttonCtrl = this.parent(), value, type;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.settings.color_picker_callback) {
+ html += (
+ '<tr>' +
+ '<td colspan="' + cols[type] + '" class="mce-custom-color-btn">' +
+ '<div id="' + id + '-c" class="mce-widget mce-btn mce-btn-small mce-btn-flat" ' +
+ 'role="button" tabindex="-1" aria-labelledby="' + id + '-c" style="width: 100%">' +
+ '<button type="button" role="presentation" tabindex="-1">' + translate('Custom...') + '</button>' +
+ '</div>' +
+ '</td>' +
+ '</tr>'
+ );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- type = buttonCtrl.settings.origin;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ html += '<tr>';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function selectColor(value) {
- buttonCtrl.hidePanel();
- buttonCtrl.color(value);
- applyFormat(buttonCtrl.settings.format, value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (x = 0; x < cols[type]; x++) {
+ html += getColorCellHtml('', 'Custom color');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function resetColor() {
- buttonCtrl.hidePanel();
- buttonCtrl.resetColor();
- removeFormat(buttonCtrl.settings.format);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ html += '</tr>';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setDivColor(div, value) {
- div.style.background = value;
- div.setAttribute('data-mce-color', value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ html += '</tbody></table>';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (tinymce.DOM.getParent(e.target, '.mce-custom-color-btn')) {
- buttonCtrl.hidePanel();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return html;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.settings.color_picker_callback.call(editor, function(value) {
- var tableElm = buttonCtrl.panel.getEl().getElementsByTagName('table')[0];
- var customColorCells, div, i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function applyFormat(format, value) {
+ editor.undoManager.transact(function () {
+ editor.focus();
+ editor.formatter.apply(format, { value: value });
+ editor.nodeChanged();
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- customColorCells = tinymce.map(tableElm.rows[tableElm.rows.length - 1].childNodes, function(elm) {
- return elm.firstChild;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function removeFormat(format) {
+ editor.undoManager.transact(function () {
+ editor.focus();
+ editor.formatter.remove(format, { value: null }, null, true);
+ editor.nodeChanged();
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0; i < customColorCells.length; i++) {
- div = customColorCells[i];
- if (!div.getAttribute('data-mce-color')) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function onPanelClick(e) {
+ var buttonCtrl = this.parent(), value, type;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Shift colors to the right
- // TODO: Might need to be the left on RTL
- if (i == cols[type]) {
- for (i = 0; i < cols[type] - 1; i++) {
- setDivColor(customColorCells[i], customColorCells[i + 1].getAttribute('data-mce-color'));
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ type = buttonCtrl.settings.origin;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- setDivColor(div, value);
- selectColor(value);
- }, getCurrentColor(buttonCtrl.settings.format));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function selectColor(value) {
+ buttonCtrl.hidePanel();
+ buttonCtrl.color(value);
+ applyFormat(buttonCtrl.settings.format, value);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- value = e.target.getAttribute('data-mce-color');
- if (value) {
- if (this.lastId) {
- document.getElementById(this.lastId).setAttribute('aria-selected', false);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function resetColor() {
+ buttonCtrl.hidePanel();
+ buttonCtrl.resetColor();
+ removeFormat(buttonCtrl.settings.format);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- e.target.setAttribute('aria-selected', true);
- this.lastId = e.target.id;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setDivColor(div, value) {
+ div.style.background = value;
+ div.setAttribute('data-mce-color', value);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value == 'transparent') {
- resetColor();
- } else {
- selectColor(value);
- }
- } else if (value !== null) {
- buttonCtrl.hidePanel();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (DOMUtils.DOM.getParent(e.target, '.mce-custom-color-btn')) {
+ buttonCtrl.hidePanel();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function onButtonClick() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.settings.color_picker_callback.call(editor, function (value) {
+ var tableElm = buttonCtrl.panel.getEl().getElementsByTagName('table')[0];
+ var customColorCells, div, i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self._color) {
- applyFormat(self.settings.format, self._color);
- } else {
- removeFormat(self.settings.format);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ customColorCells = Tools.map(tableElm.rows[tableElm.rows.length - 1].childNodes, function (elm) {
+ return elm.firstChild;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addButton('forecolor', {
- type: 'colorbutton',
- tooltip: 'Text color',
- format: 'forecolor',
- panel: {
- origin: 'forecolor',
- role: 'application',
- ariaRemember: true,
- html: renderColorPicker,
- onclick: onPanelClick
- },
- onclick: onButtonClick
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0; i < customColorCells.length; i++) {
+ div = customColorCells[i];
+ if (!div.getAttribute('data-mce-color')) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addButton('backcolor', {
- type: 'colorbutton',
- tooltip: 'Background color',
- format: 'hilitecolor',
- panel: {
- origin: 'backcolor',
- role: 'application',
- ariaRemember: true,
- html: renderColorPicker,
- onclick: onPanelClick
- },
- onclick: onButtonClick
- });
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Shift colors to the right
+ // TODO: Might need to be the left on RTL
+ if (i == cols[type]) {
+ for (i = 0; i < cols[type] - 1; i++) {
+ setDivColor(customColorCells[i], customColorCells[i + 1].getAttribute('data-mce-color'));
+ }
+ }
+
+ setDivColor(div, value);
+ selectColor(value);
+ }, getCurrentColor(buttonCtrl.settings.format));
+ }
+
+ value = e.target.getAttribute('data-mce-color');
+ if (value) {
+ if (this.lastId) {
+ document.getElementById(this.lastId).setAttribute('aria-selected', false);
+ }
+
+ e.target.setAttribute('aria-selected', true);
+ this.lastId = e.target.id;
+
+ if (value == 'transparent') {
+ resetColor();
+ } else {
+ selectColor(value);
+ }
+ } else if (value !== null) {
+ buttonCtrl.hidePanel();
+ }
+ }
+
+ function onButtonClick() {
+ var self = this;
+
+ if (self._color) {
+ applyFormat(self.settings.format, self._color);
+ } else {
+ removeFormat(self.settings.format);
+ }
+ }
+
+ editor.addButton('forecolor', {
+ type: 'colorbutton',
+ tooltip: 'Text color',
+ format: 'forecolor',
+ panel: {
+ origin: 'forecolor',
+ role: 'application',
+ ariaRemember: true,
+ html: renderColorPicker,
+ onclick: onPanelClick
+ },
+ onclick: onButtonClick
+ });
+
+ editor.addButton('backcolor', {
+ type: 'colorbutton',
+ tooltip: 'Background color',
+ format: 'hilitecolor',
+ panel: {
+ origin: 'backcolor',
+ role: 'application',
+ ariaRemember: true,
+ html: renderColorPicker,
+ onclick: onPanelClick
+ },
+ onclick: onButtonClick
+ });
+ });
+
+ return function () { };
+ }
+);
+dem('tinymce.plugins.textcolor.Plugin')();
+})();
</ins></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginstextcolorpluginminjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/textcolor/plugin.min.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/textcolor/plugin.min.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/textcolor/plugin.min.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1 +1 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-tinymce.PluginManager.add("textcolor",function(e){function t(t){var n;return e.dom.getParents(e.selection.getStart(),function(e){var r;(r=e.style["forecolor"==t?"color":"background-color"])&&(n=r)}),n}function n(t){var n,r,i=[];for(r=["000000","Black","993300","Burnt orange","333300","Dark olive","003300","Dark green","003366","Dark azure","000080","Navy Blue","333399","Indigo","333333","Very dark gray","800000","Maroon","FF6600","Orange","808000","Olive","008000","Green","008080","Teal","0000FF","Blue","666699","Grayish blue","808080",
"Gray","FF0000","Red","FF9900","Amber","99CC00","Yellow green","339966","Sea green","33CCCC","Turquoise","3366FF","Royal blue","800080","Purple","999999","Medium gray","FF00FF","Magenta","FFCC00","Gold","FFFF00","Yellow","00FF00","Lime","00FFFF","Aqua","00CCFF","Sky blue","993366","Red violet","FFFFFF","White","FF99CC","Pink","FFCC99","Peach","FFFF99","Light yellow","CCFFCC","Pale green","CCFFFF","Pale cyan","99CCFF","Light sky blue","CC99FF","Plum"],r=e.settings.textcolor_map||r,r=e.settings[t+"_map"]||r,n=0;n&
lt;r.length;n+=2)i.push({text:r[n+1],color:"#"+r[n]});return i}function r(){function t(e,t){var n="transparent"==e;return'<td class="mce-grid-cell'+(n?" mce-colorbtn-trans":"")+'"><div id="'+h+"-"+m++ +'" data-mce-color="'+(e?e:"")+'" role="option" tabIndex="-1" style="'+(e?"background-color: "+e:"")+'" title="'+tinymce.translate(t)+'">'+(n?"×":"")+"</div></td>"}var r,i,o,a,s,c,d,f,p=this,h=p._id,m=0;for(f=p.settings.origin,r=n(f),r.push({text:tinymce.translate("No color"),color:"transparent"}),o='<table class="mce-grid mce-grid-border mce-colorbutton-grid" role="list" cellspacing="0"><tbody>',a=r.length-1,c=0;c<u[f];c++){for(o+="<tr>",s=0;s<l[f];s++)d=c*l[f]+s,d>a?o+="<td><
/td>":(i=r[d],o+=t(i.color,i.text));o+="</tr>"}if(e.settings.color_picker_callback){for(o+='<tr><td colspan="'+l[f]+'" class="mce-custom-color-btn"><div id="'+h+'-c" class="mce-widget mce-btn mce-btn-small mce-btn-flat" role="button" tabindex="-1" aria-labelledby="'+h+'-c" style="width: 100%"><button type="button" role="presentation" tabindex="-1">'+tinymce.translate("Custom...")+"</button></div></td></tr>",o+="<tr>",s=0;s<l[f];s++)o+=t("","Custom color");o+="</tr>"}return o+="</tbody></table>"}function i(t,n){e.undoManager.transact(function(){e.focus(),e.formatter.apply(t,{value:n}),e.nodeChanged()})}function o(t){e.undoManager.transact(function(){e.focus(),e.formatter.remove(t,{value:null},null,!0),e.nodeCh
anged()})}function a(n){function r(e){d.hidePanel(),d.color(e),i(d.settings.format,e)}function a(){d.hidePanel(),d.resetColor(),o(d.settings.format)}function s(e,t){e.style.background=t,e.setAttribute("data-mce-color",t)}var u,c,d=this.parent();c=d.settings.origin,tinymce.DOM.getParent(n.target,".mce-custom-color-btn")&&(d.hidePanel(),e.settings.color_picker_callback.call(e,function(e){var t,n,i,o=d.panel.getEl().getElementsByTagName("table")[0];for(t=tinymce.map(o.rows[o.rows.length-1].childNodes,function(e){return e.firstChild}),i=0;i<t.length&&(n=t[i],n.getAttribute("data-mce-color"));i++);if(i==l[c])for(i=0;i<l[c]-1;i++)s(t[i],t[i+1].getAttribute("data-mce-color"));s(n,e),r(e)},t(d.settings.format))),u=n.target.getAttribute("data-mce-color"),u?(this.lastId&&document.getElementById(this.lastId).setAttribute("aria-selected",!1),n.target.setAttribute("aria-selected",!0),thi
s.lastId=n.target.id,"transparent"==u?a():r(u)):null!==u&&d.hidePanel()}function s(){var e=this;e._color?i(e.settings.format,e._color):o(e.settings.format)}var l,u;u={forecolor:e.settings.forecolor_rows||e.settings.textcolor_rows||5,backcolor:e.settings.backcolor_rows||e.settings.textcolor_rows||5},l={forecolor:e.settings.forecolor_cols||e.settings.textcolor_cols||8,backcolor:e.settings.backcolor_cols||e.settings.textcolor_cols||8},e.addButton("forecolor",{type:"colorbutton",tooltip:"Text color",format:"forecolor",panel:{origin:"forecolor",role:"application",ariaRemember:!0,html:r,onclick:a},onclick:s}),e.addButton("backcolor",{type:"colorbutton",tooltip:"Background color",format:"hilitecolor",panel:{origin:"backcolor",role:"application",ariaRemember:!0,html:r,onclick:a},onclick:s})});
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+!function(){var a={},b=function(b){for(var c=a[b],e=c.deps,f=c.defn,g=e.length,h=new Array(g),i=0;i<g;++i)h[i]=d(e[i]);var j=f.apply(null,h);if(void 0===j)throw"module ["+b+"] returned undefined";c.instance=j},c=function(b,c,d){if("string"!=typeof b)throw"module id must be a string";if(void 0===c)throw"no dependencies for "+b;if(void 0===d)throw"no definition function for "+b;a[b]={deps:c,defn:d,instance:void 0}},d=function(c){var d=a[c];if(void 0===d)throw"module ["+c+"] was undefined";return void 0===d.instance&&b(c),d.instance},e=function(a,b){for(var c=a.length,e=new Array(c),f=0;f<c;++f)e.push(d(a[f]));b.apply(null,b)},f={};f.bolt={module:{api:{define:c,require:e,demand:d}}};var g=c,h=function(a,b){g(a,[],function(){return b})};h("5",tinymce.util.Tools.resolve),g("1",[&q
uot;5"],function(a){return a("tinymce.dom.DOMUtils")}),g("2",["5"],function(a){return a("tinymce.PluginManager")}),g("3",["5"],function(a){return a("tinymce.util.I18n")}),g("4",["5"],function(a){return a("tinymce.util.Tools")}),g("0",["1","2","3","4"],function(a,b,c,d){var e=c.translate;return b.add("textcolor",function(b){function c(a){var c;return b.dom.getParents(b.selection.getStart(),function(b){var d;(d=b.style["forecolor"==a?"color":"background-color"])&&(c=d)}),c}function f(a){var c,d,e=[];for(d=["000000","Black","993300","Burnt orange","333300","Dark olive","003300","Dark green","003366","Dark azure","000080","Navy Blue","333399","Indigo"
;,"333333","Very dark gray","800000","Maroon","FF6600","Orange","808000","Olive","008000","Green","008080","Teal","0000FF","Blue","666699","Grayish blue","808080","Gray","FF0000","Red","FF9900","Amber","99CC00","Yellow green","339966","Sea green","33CCCC","Turquoise","3366FF","Royal blue","800080","Purple","999999","Medium gray","FF00FF","Magenta","FFCC00","Gold","FFFF00","Yellow","00FF00","Lime","00FFFF","Aqua","00CCFF","Sky blue","993366","Red violet","FFFFFF","White","FF99CC",&qu
ot;Pink","FFCC99","Peach","FFFF99","Light yellow","CCFFCC","Pale green","CCFFFF","Pale cyan","99CCFF","Light sky blue","CC99FF","Plum"],d=b.settings.textcolor_map||d,d=b.settings[a+"_map"]||d,c=0;c<d.length;c+=2)e.push({text:d[c+1],color:"#"+d[c]});return e}function g(){function a(a,b){var c="transparent"==a;return'<td class="mce-grid-cell'+(c?" mce-colorbtn-trans":"")+'"><div id="'+p+"-"+q++ +'" data-mce-color="'+(a?a:"")+'" role="option" tabIndex="-1" style="'+(a?"background-color: "+a:"")+'" title="'+e(b)+'">'+(c?"×":"")+"</div></td>"}var c,d,g,h,i,j,k,n,o=this,p=o._id,q=0;for(n=o.settings.origin,c=f(n),c.push({text:e("No color&qu
ot;),color:"transparent"}),g='<table class="mce-grid mce-grid-border mce-colorbutton-grid" role="list" cellspacing="0"><tbody>',h=c.length-1,j=0;j<m[n];j++){for(g+="<tr>",i=0;i<l[n];i++)k=j*l[n]+i,k>h?g+="<td></td>":(d=c[k],g+=a(d.color,d.text));g+="</tr>"}if(b.settings.color_picker_callback){for(g+='<tr><td colspan="'+l[n]+'" class="mce-custom-color-btn"><div id="'+p+'-c" class="mce-widget mce-btn mce-btn-small mce-btn-flat" role="button" tabindex="-1" aria-labelledby="'+p+'-c" style="width: 100%"><button type="button" role="presentation" tabindex="-1">'+e("Custom...")+"</button></div></td></tr>",g+="<tr>",i=0;i<l[n];i++)g+=a("","Custom color");g+="&l
t;/tr>"}return g+="</tbody></table>"}function h(a,c){b.undoManager.transact(function(){b.focus(),b.formatter.apply(a,{value:c}),b.nodeChanged()})}function i(a){b.undoManager.transact(function(){b.focus(),b.formatter.remove(a,{value:null},null,!0),b.nodeChanged()})}function j(e){function f(a){n.hidePanel(),n.color(a),h(n.settings.format,a)}function g(){n.hidePanel(),n.resetColor(),i(n.settings.format)}function j(a,b){a.style.background=b,a.setAttribute("data-mce-color",b)}var k,m,n=this.parent();m=n.settings.origin,a.DOM.getParent(e.target,".mce-custom-color-btn")&&(n.hidePanel(),b.settings.color_picker_callback.call(b,function(a){var b,c,e,g=n.panel.getEl().getElementsByTagName("table")[0];for(b=d.map(g.rows[g.rows.length-1].childNodes,function(a){return a.firstChild}),e=0;e<b.length&&(c=b[e],c.getAttribute("data-mce-color"));e++);if(e==l[m])for(e=0;e<l[m]-1;e++)j(b[e],b[e+1].getAttribute(&qu
ot;data-mce-color"));j(c,a),f(a)},c(n.settings.format))),k=e.target.getAttribute("data-mce-color"),k?(this.lastId&&document.getElementById(this.lastId).setAttribute("aria-selected",!1),e.target.setAttribute("aria-selected",!0),this.lastId=e.target.id,"transparent"==k?g():f(k)):null!==k&&n.hidePanel()}function k(){var a=this;a._color?h(a.settings.format,a._color):i(a.settings.format)}var l,m;m={forecolor:b.settings.forecolor_rows||b.settings.textcolor_rows||5,backcolor:b.settings.backcolor_rows||b.settings.textcolor_rows||5},l={forecolor:b.settings.forecolor_cols||b.settings.textcolor_cols||8,backcolor:b.settings.backcolor_cols||b.settings.textcolor_cols||8},b.addButton("forecolor",{type:"colorbutton",tooltip:"Text color",format:"forecolor",panel:{origin:"forecolor",role:"application",ariaRemember:!0,html:g,onclick:j},onclick:k}),b.addButton("backcolor",{
type:"colorbutton",tooltip:"Background color",format:"hilitecolor",panel:{origin:"backcolor",role:"application",ariaRemember:!0,html:g,onclick:j},onclick:k})}),function(){}}),d("0")()}();
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginswordpresspluginjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/wordpress/plugin.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/wordpress/plugin.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/wordpress/plugin.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -682,6 +682,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> mceIframe = document.getElementById( editor.id + '_ifr' ),
</span><span class="cx" style="display: block; padding: 0 10px"> mceToolbar,
</span><span class="cx" style="display: block; padding: 0 10px"> mceStatusbar,
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ namesAdded,
</ins><span class="cx" style="display: block; padding: 0 10px"> wpStatusbar;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( container ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -699,7 +700,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> buttonGroup;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> each( buttons, function( item ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var itemName;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var itemName, ui, name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> function bindSelectorChanged() {
</span><span class="cx" style="display: block; padding: 0 10px"> var selection = editor.selection;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -767,6 +768,19 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> buttonGroup = null;
</span><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add the new WP* types to the factory
+ if ( ! namesAdded ) {
+ ui = tinymce.ui;
+
+ for ( name in ui ) {
+ if ( name.toLowerCase().indexOf( 'wp' ) === 0 ) {
+ Factory.add( name, ui[name] );
+ }
+ }
+
+ namesAdded = true;
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> if ( ! buttonGroup ) {
</span><span class="cx" style="display: block; padding: 0 10px"> buttonGroup = {
</span><span class="cx" style="display: block; padding: 0 10px"> type: 'buttongroup',
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcepluginswpviewpluginjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/plugins/wpview/plugin.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/plugins/wpview/plugin.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/plugins/wpview/plugin.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -92,13 +92,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Replace any new markers nodes with views.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on( 'setcontent', function( event ) {
- if ( event.load && ! event.initial && editor.quirks.refreshContentEditable ) {
- // Make sure there is a selection in Gecko browsers.
- // Or it will refresh the content internally which resets the iframes.
- editor.quirks.refreshContentEditable();
- }
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on( 'setcontent', function() {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp.mce.views.render();
</span><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymceskinslightgraycontentinlinemincss"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/skins/lightgray/content.inline.min.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/skins/lightgray/content.inline.min.css 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/skins/lightgray/content.inline.min.css 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1 +1 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-.mce-content-body .mce-reset{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:black;font-family:Arial;font-size:11px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;line-height:normal;font-weight:normal;text-align:left;-webkit-tap-highlight-color:transparent;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr;max-width:none}.mce-object{border:1px dotted #3A3A3A;background:#D5D5D5 url(img/object.gif) no-repeat center}.mce-preview-object{display:inline-block;position:relative;margin:0 2px 0 2px;line-height:0;border:1px solid gray}.mce-preview-object[data-mce-selected="2"] .mce-shim{display:none}.mce-preview-object .mce-shim{position:absolute;top:0;left:0;width:100%;height:100%;background:url(data:image/gif;base64,R0lGODlhAQABAI
AAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}figure.align-left{float:left}figure.align-right{float:right}figure.image.align-center{display:table;margin-left:auto;margin-right:auto}figure.image{display:inline-block;border:1px solid gray;margin:0 2px 0 1px;background:#f5f2f0}figure.image img{margin:8px 8px 0 8px}figure.image figcaption{margin:6px 8px 6px 8px;text-align:center}.mce-toc{border:1px solid gray}.mce-toc h2{margin:4px}.mce-toc li{list-style-type:none}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:15px;page-break-before:always}@media print{.mce-pagebreak{border:0}}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px !important;height:9px !important;border:1px dotted #3A3A3A;background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-nbsp,.mce-shy{background:#AAA}.mce
-shy::after{content:'-'}hr{cursor:default}.mce-match-marker{background:#AAA;color:#fff}.mce-match-marker-selected{background:#3399ff;color:#fff}.mce-spellchecker-word{border-bottom:2px solid #F00;cursor:default}.mce-spellchecker-grammar{border-bottom:2px solid #008000;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td[data-mce-selected],th[data-mce-selected]{background-color:#3399ff !important}.mce-edit-focus{outline:1px dotted #333}.mce-content-body *[contentEditable=false] *[contentEditable=true]:focus{outline:2px solid #2d8ac7}.mce-content-body *[contentEditable=false] *[contentEditable=true]:hover{outline:2px solid #7ACAFF}.mce-content-body *[contentEditable=false][data-mce-selected]{outline:2px solid #2d8ac7}.mce-resize-bar-dragging{background-color:blue;opacity:.25;filter:alpha(opacity=25);zoom:1}
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.mce-content-body .mce-reset{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:black;font-family:Arial;font-size:11px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;line-height:normal;font-weight:normal;text-align:left;-webkit-tap-highlight-color:transparent;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr;max-width:none}.mce-object{border:1px dotted #3A3A3A;background:#D5D5D5 url(img/object.gif) no-repeat center}.mce-preview-object{display:inline-block;position:relative;margin:0 2px 0 2px;line-height:0;border:1px solid gray}.mce-preview-object[data-mce-selected="2"] .mce-shim{display:none}.mce-preview-object .mce-shim{position:absolute;top:0;left:0;width:100%;height:100%;background:url(data:image/gif;base64,R0lGODlhAQABAI
AAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}figure.align-left{float:left}figure.align-right{float:right}figure.image.align-center{display:table;margin-left:auto;margin-right:auto}figure.image{display:inline-block;border:1px solid gray;margin:0 2px 0 1px;background:#f5f2f0}figure.image img{margin:8px 8px 0 8px}figure.image figcaption{margin:6px 8px 6px 8px;text-align:center}.mce-toc{border:1px solid gray}.mce-toc h2{margin:4px}.mce-toc li{list-style-type:none}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:15px;page-break-before:always}@media print{.mce-pagebreak{border:0}}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px !important;height:9px !important;border:1px dotted #3A3A3A;background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-nbsp,.mce-shy{background:#AAA}.mce
-shy::after{content:'-'}.mce-match-marker{background:#AAA;color:#fff}.mce-match-marker-selected{background:#3399ff;color:#fff}.mce-spellchecker-word{border-bottom:2px solid #F00;cursor:default}.mce-spellchecker-grammar{border-bottom:2px solid #008000;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td[data-mce-selected],th[data-mce-selected]{background-color:#3399ff !important}.mce-edit-focus{outline:1px dotted #333}.mce-resize-bar-dragging{background-color:blue;opacity:.25;filter:alpha(opacity=25);zoom:1}.mce-content-body p,.mce-content-body div,.mce-content-body h1,.mce-content-body h2,.mce-content-body h3,.mce-content-body h4,.mce-content-body h5,.mce-content-body h6{line-height:1.2em}.mce-content-body *[contentEditable=false] *[contentEditable=true]:focus{outline:2px solid #2d8ac7}.mce-content-body *[contentEditable=false] *[contentEditable=true]:hover{outline:2px solid #7ACAFF}.mce-content-body *[contentEditable
=false][data-mce-selected]{outline:2px solid #2d8ac7}.mce-content-body a[data-mce-selected],.mce-content-body code[data-mce-selected]{background:#bfe6ff}.mce-content-body hr{cursor:default}
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymceskinslightgraycontentmincss"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/skins/lightgray/content.min.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/skins/lightgray/content.min.css 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/skins/lightgray/content.min.css 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1 +1 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-body{background-color:#FFFFFF;color:#000000;font-family:Verdana,Arial,Helvetica,sans-serif;font-size:14px;scrollbar-3dlight-color:#F0F0EE;scrollbar-arrow-color:#676662;scrollbar-base-color:#F0F0EE;scrollbar-darkshadow-color:#DDDDDD;scrollbar-face-color:#E0E0DD;scrollbar-highlight-color:#F0F0EE;scrollbar-shadow-color:#F0F0EE;scrollbar-track-color:#F5F5F5}td,th{font-family:Verdana,Arial,Helvetica,sans-serif;font-size:14px}.mce-content-body .mce-reset{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:black;font-family:Arial;font-size:11px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;line-height:normal;font-weight:normal;text-align:left;-webkit-tap-highlight-color:transparent;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr;max-width:
none}.mce-object{border:1px dotted #3A3A3A;background:#D5D5D5 url(img/object.gif) no-repeat center}.mce-preview-object{display:inline-block;position:relative;margin:0 2px 0 2px;line-height:0;border:1px solid gray}.mce-preview-object[data-mce-selected="2"] .mce-shim{display:none}.mce-preview-object .mce-shim{position:absolute;top:0;left:0;width:100%;height:100%;background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}figure.align-left{float:left}figure.align-right{float:right}figure.image.align-center{display:table;margin-left:auto;margin-right:auto}figure.image{display:inline-block;border:1px solid gray;margin:0 2px 0 1px;background:#f5f2f0}figure.image img{margin:8px 8px 0 8px}figure.image figcaption{margin:6px 8px 6px 8px;text-align:center}.mce-toc{border:1px solid gray}.mce-toc h2{margin:4px}.mce-toc li{list-style-type:none}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:1
5px;page-break-before:always}@media print{.mce-pagebreak{border:0}}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px !important;height:9px !important;border:1px dotted #3A3A3A;background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-nbsp,.mce-shy{background:#AAA}.mce-shy::after{content:'-'}hr{cursor:default}.mce-match-marker{background:#AAA;color:#fff}.mce-match-marker-selected{background:#3399ff;color:#fff}.mce-spellchecker-word{border-bottom:2px solid #F00;cursor:default}.mce-spellchecker-grammar{border-bottom:2px solid #008000;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td[data-mce-selected],th[data-mce-selected]{background-color:#3399ff !important}.mce-edit-focus{outline:1px dotted #333}.mce-content-body *[contentEditable=false] *[contentEditable=true]:f
ocus{outline:2px solid #2d8ac7}.mce-content-body *[contentEditable=false] *[contentEditable=true]:hover{outline:2px solid #7ACAFF}.mce-content-body *[contentEditable=false][data-mce-selected]{outline:2px solid #2d8ac7}.mce-resize-bar-dragging{background-color:blue;opacity:.25;filter:alpha(opacity=25);zoom:1}
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+body{background-color:#FFFFFF;color:#000000;font-family:Verdana,Arial,Helvetica,sans-serif;font-size:14px;scrollbar-3dlight-color:#F0F0EE;scrollbar-arrow-color:#676662;scrollbar-base-color:#F0F0EE;scrollbar-darkshadow-color:#DDDDDD;scrollbar-face-color:#E0E0DD;scrollbar-highlight-color:#F0F0EE;scrollbar-shadow-color:#F0F0EE;scrollbar-track-color:#F5F5F5}td,th{font-family:Verdana,Arial,Helvetica,sans-serif;font-size:14px}.mce-content-body .mce-reset{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:black;font-family:Arial;font-size:11px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;line-height:normal;font-weight:normal;text-align:left;-webkit-tap-highlight-color:transparent;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr;max-width:
none}.mce-object{border:1px dotted #3A3A3A;background:#D5D5D5 url(img/object.gif) no-repeat center}.mce-preview-object{display:inline-block;position:relative;margin:0 2px 0 2px;line-height:0;border:1px solid gray}.mce-preview-object[data-mce-selected="2"] .mce-shim{display:none}.mce-preview-object .mce-shim{position:absolute;top:0;left:0;width:100%;height:100%;background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}figure.align-left{float:left}figure.align-right{float:right}figure.image.align-center{display:table;margin-left:auto;margin-right:auto}figure.image{display:inline-block;border:1px solid gray;margin:0 2px 0 1px;background:#f5f2f0}figure.image img{margin:8px 8px 0 8px}figure.image figcaption{margin:6px 8px 6px 8px;text-align:center}.mce-toc{border:1px solid gray}.mce-toc h2{margin:4px}.mce-toc li{list-style-type:none}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:1
5px;page-break-before:always}@media print{.mce-pagebreak{border:0}}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px !important;height:9px !important;border:1px dotted #3A3A3A;background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-nbsp,.mce-shy{background:#AAA}.mce-shy::after{content:'-'}.mce-match-marker{background:#AAA;color:#fff}.mce-match-marker-selected{background:#3399ff;color:#fff}.mce-spellchecker-word{border-bottom:2px solid #F00;cursor:default}.mce-spellchecker-grammar{border-bottom:2px solid #008000;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td[data-mce-selected],th[data-mce-selected]{background-color:#3399ff !important}.mce-edit-focus{outline:1px dotted #333}.mce-resize-bar-dragging{background-color:blue;opacity:.25;filter:alpha(opacity=25);zo
om:1}.mce-content-body p,.mce-content-body div,.mce-content-body h1,.mce-content-body h2,.mce-content-body h3,.mce-content-body h4,.mce-content-body h5,.mce-content-body h6{line-height:1.2em}.mce-content-body *[contentEditable=false] *[contentEditable=true]:focus{outline:2px solid #2d8ac7}.mce-content-body *[contentEditable=false] *[contentEditable=true]:hover{outline:2px solid #7ACAFF}.mce-content-body *[contentEditable=false][data-mce-selected]{outline:2px solid #2d8ac7}.mce-content-body a[data-mce-selected],.mce-content-body code[data-mce-selected]{background:#bfe6ff}.mce-content-body hr{cursor:default}
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymceskinslightgrayfontsreadmemd"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/src/wp-includes/js/tinymce/skins/lightgray/fonts/readme.md</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/skins/lightgray/fonts/readme.md 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/skins/lightgray/fonts/readme.md 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-Icons are generated and provided by the http://icomoon.io service.
</del></span></pre></div>
<a id="trunksrcwpincludesjstinymceskinslightgrayfontstinymcesmalljson"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/src/wp-includes/js/tinymce/skins/lightgray/fonts/tinymce-small.json</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/skins/lightgray/fonts/tinymce-small.json 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/skins/lightgray/fonts/tinymce-small.json 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,1277 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-{
- "IcoMoonType": "selection",
- "icons": [
- {
- "icon": {
- "paths": [
- "M704 832v-37.004c151.348-61.628 256-193.82 256-346.996 0-212.078-200.576-384-448-384s-448 171.922-448 384c0 153.176 104.654 285.368 256 346.996v37.004h-192l-64-96v224h320v-222.812c-100.9-51.362-170.666-161.54-170.666-289.188 0-176.732 133.718-320 298.666-320 164.948 0 298.666 143.268 298.666 320 0 127.648-69.766 237.826-170.666 289.188v222.812h320v-224l-64 96h-192z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57376,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 0,
- "order": 1,
- "prevSize": 32,
- "code": 57376,
- "name": "charmap",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 0
- },
- {
- "icon": {
- "paths": [
- "M256 64v896l256-256 256 256v-896h-512zM704 789.49l-192-192-192 192v-661.49h384v661.49z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57363,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 1,
- "order": 2,
- "prevSize": 32,
- "code": 57363,
- "name": "bookmark",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 1
- },
- {
- "icon": {
- "paths": [
- "M927.274 230.216l-133.49-133.488c-21.104-21.104-49.232-32.728-79.198-32.728s-58.094 11.624-79.196 32.726l-165.492 165.49c-43.668 43.668-43.668 114.724 0 158.392l2.746 2.746 67.882-67.882-2.746-2.746c-6.132-6.132-6.132-16.494 0-22.626l165.492-165.492c4.010-4.008 8.808-4.608 11.312-4.608s7.302 0.598 11.312 4.61l133.49 133.488c6.132 6.134 6.132 16.498 0.002 22.628l-165.494 165.494c-4.008 4.008-8.806 4.608-11.31 4.608s-7.302-0.6-11.312-4.612l-2.746-2.746-67.88 67.884 2.742 2.742c21.106 21.108 49.23 32.728 79.2 32.728s58.094-11.624 79.196-32.726l165.494-165.492c43.662-43.666 43.662-114.72-0.004-158.39zM551.356 600.644l-67.882 67.882 2.746 2.746c4.008 4.008 4.61 8.806 4.61 11.31 0 2.506-0.598 7.302-4.606 11.314l-165.494 165.49c-4.010 4.010-8.81 4.61-11.314 4.61s-7.304-0.6-11.314-4.61l-133.492-133.486c-4.010-4.010-4.61-8.81-4.61-11.314s0.598-7.3 4.61-11.312l165.49-165.488c4.010-4.012 8.81-4.612 11.314-4.612s7.304 0.6 11.314 4.612l2.746 2.742 67.882-67.88-2.746-2.746c-21.104-21.1
04-49.23-32.726-79.196-32.726s-58.092 11.624-79.196 32.726l-165.488 165.486c-21.106 21.104-32.73 49.234-32.73 79.198s11.624 58.094 32.726 79.198l133.49 133.49c21.106 21.102 49.232 32.726 79.198 32.726s58.092-11.624 79.196-32.726l165.494-165.492c21.104-21.104 32.722-49.23 32.722-79.196s-11.624-58.094-32.726-79.196l-2.744-2.746zM800 838c-9.724 0-19.45-3.708-26.87-11.13l-128-127.998c-14.844-14.84-14.844-38.898 0-53.738 14.84-14.844 38.896-14.844 53.736 0l128 128c14.844 14.84 14.844 38.896 0 53.736-7.416 7.422-17.142 11.13-26.866 11.13zM608 960c-17.674 0-32-14.326-32-32v-128c0-17.674 14.326-32 32-32s32 14.326 32 32v128c0 17.674-14.326 32-32 32zM928 640h-128c-17.674 0-32-14.326-32-32s14.326-32 32-32h128c17.674 0 32 14.326 32 32s-14.326 32-32 32zM224 186c9.724 0 19.45 3.708 26.87 11.13l128 128c14.842 14.84 14.842 38.898 0 53.738-14.84 14.844-38.898 14.844-53.738 0l-128-128c-14.842-14.84-14.842-38.898 0-53.738 7.418-7.422 17.144-11.13 26.868-11.13zM416 64c17.674 0 32 14.326 32 32v128c0 17.
674-14.326 32-32 32s-32-14.326-32-32v-128c0-17.674 14.326-32 32-32zM96 384h128c17.674 0 32 14.326 32 32s-14.326 32-32 32h-128c-17.674 0-32-14.326-32-32s14.326-32 32-32z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57362,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 2,
- "order": 3,
- "prevSize": 32,
- "code": 57362,
- "name": "link",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 2
- },
- {
- "icon": {
- "paths": [
- "M927.274 230.216l-133.49-133.488c-21.104-21.104-49.232-32.728-79.198-32.728s-58.094 11.624-79.196 32.726l-165.492 165.49c-43.668 43.668-43.668 114.724 0 158.392l2.746 2.746 67.882-67.882-2.746-2.746c-6.132-6.132-6.132-16.494 0-22.626l165.492-165.492c4.010-4.008 8.808-4.608 11.312-4.608s7.302 0.598 11.312 4.61l133.49 133.488c6.132 6.134 6.132 16.498 0.002 22.628l-165.494 165.494c-4.008 4.008-8.806 4.608-11.31 4.608s-7.302-0.6-11.312-4.612l-2.746-2.746-67.88 67.884 2.742 2.742c21.106 21.108 49.23 32.728 79.2 32.728s58.094-11.624 79.196-32.726l165.494-165.492c43.662-43.666 43.662-114.72-0.004-158.39zM551.356 600.644l-67.882 67.882 2.746 2.746c4.008 4.008 4.61 8.806 4.61 11.31 0 2.506-0.598 7.302-4.606 11.314l-165.494 165.49c-4.010 4.010-8.81 4.61-11.314 4.61s-7.304-0.6-11.314-4.61l-133.492-133.486c-4.010-4.010-4.61-8.81-4.61-11.314s0.598-7.3 4.61-11.312l165.49-165.488c4.010-4.012 8.81-4.612 11.314-4.612s7.304 0.6 11.314 4.612l2.746 2.742 67.882-67.88-2.746-2.746c-21.104-21.1
04-49.23-32.726-79.196-32.726s-58.092 11.624-79.196 32.726l-165.488 165.486c-21.106 21.104-32.73 49.234-32.73 79.198s11.624 58.094 32.726 79.198l133.49 133.49c21.106 21.102 49.232 32.726 79.198 32.726s58.092-11.624 79.196-32.726l165.494-165.492c21.104-21.104 32.722-49.23 32.722-79.196s-11.624-58.094-32.726-79.196l-2.744-2.746zM352 710c-9.724 0-19.45-3.71-26.87-11.128-14.84-14.84-14.84-38.898 0-53.738l320-320c14.84-14.84 38.896-14.84 53.736 0 14.844 14.84 14.844 38.9 0 53.74l-320 320c-7.416 7.416-17.142 11.126-26.866 11.126z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57361,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 3,
- "order": 4,
- "prevSize": 32,
- "code": 57361,
- "name": "unlink",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 3
- },
- {
- "icon": {
- "paths": [
- "M576 281.326v-217.326l336.002 336-336.002 336v-222.096c-390.906-9.17-315 247.096-256 446.096-288-320-212.092-690.874 256-678.674z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57360,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 4,
- "order": 5,
- "prevSize": 32,
- "code": 57360,
- "name": "redo",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 4
- },
- {
- "icon": {
- "paths": [
- "M704 960c59-199 134.906-455.266-256-446.096v222.096l-336.002-336 336.002-336v217.326c468.092-12.2 544 358.674 256 678.674z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57359,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 5,
- "order": 6,
- "prevSize": 32,
- "code": 57359,
- "name": "undo",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 5
- },
- {
- "icon": {
- "paths": [
- "M256.428 424.726c105.8 0 191.572 91.17 191.572 203.638 0 112.464-85.772 203.636-191.572 203.636-105.802 0-191.572-91.17-191.572-203.636l-0.856-29.092c0-224.93 171.54-407.272 383.144-407.272v116.364c-73.1 0-141.826 30.26-193.516 85.204-9.954 10.578-19.034 21.834-27.224 33.656 9.784-1.64 19.806-2.498 30.024-2.498zM768.428 424.726c105.8 0 191.572 91.17 191.572 203.638 0 112.464-85.772 203.636-191.572 203.636-105.802 0-191.572-91.17-191.572-203.636l-0.856-29.092c0-224.93 171.54-407.272 383.144-407.272v116.364c-73.1 0-141.826 30.26-193.516 85.204-9.956 10.578-19.036 21.834-27.224 33.656 9.784-1.64 19.806-2.498 30.024-2.498z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57358,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 6,
- "order": 7,
- "prevSize": 32,
- "code": 57358,
- "name": "blockquote",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 6
- },
- {
- "icon": {
- "paths": [
- "M64 192h896v128h-896zM384 576h576v128h-576zM384 384h576v128h-576zM64 768h896v128h-896zM64 384l224 160-224 160z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57356,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 7,
- "order": 8,
- "prevSize": 32,
- "code": 57356,
- "name": "indent",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 7
- },
- {
- "icon": {
- "paths": [
- "M64 192h896v128h-896zM64 576h576v128h-576zM64 384h576v128h-576zM64 768h896v128h-896zM960 384l-224 160 224 160z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57357,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 8,
- "order": 9,
- "prevSize": 32,
- "code": 57357,
- "name": "outdent",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 8
- },
- {
- "icon": {
- "paths": [
- "M384 128h576v128h-576zM384 448h576v128h-576zM384 768h576v128h-576zM320 530v-146h-64v-320h-128v64h64v256h-64v64h128v50l-128 60v146h128v64h-128v64h128v64h-128v64h192v-320h-128v-50z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57355,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 9,
- "order": 10,
- "prevSize": 32,
- "code": 57355,
- "name": "numlist",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 9
- },
- {
- "icon": {
- "paths": [
- "M384 128h576v128h-576zM384 448h576v128h-576zM384 768h576v128h-576zM128 192c0 35.346 28.654 64 64 64s64-28.654 64-64c0-35.346-28.654-64-64-64-35.346 0-64 28.654-64 64zM128 512c0 35.346 28.654 64 64 64s64-28.654 64-64c0-35.346-28.654-64-64-64-35.346 0-64 28.654-64 64zM128 832c0 35.346 28.654 64 64 64s64-28.654 64-64c0-35.346-28.654-64-64-64-35.346 0-64 28.654-64 64z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57354,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 10,
- "order": 11,
- "prevSize": 32,
- "code": 57354,
- "name": "bullist",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 10
- },
- {
- "icon": {
- "paths": [
- "M888 384h-56v-256h64v-64h-320v64h64v256h-256v-256h64v-64h-320v64h64v256h-56c-39.6 0-72 32.4-72 72v432c0 39.6 32.4 72 72 72h240c39.6 0 72-32.4 72-72v-312h128v312c0 39.6 32.4 72 72 72h240c39.6 0 72-32.4 72-72v-432c0-39.6-32.4-72-72-72zM348 896h-184c-19.8 0-36-14.4-36-32s16.2-32 36-32h184c19.8 0 36 14.4 36 32s-16.2 32-36 32zM544 512h-64c-17.6 0-32-14.4-32-32s14.4-32 32-32h64c17.6 0 32 14.4 32 32s-14.4 32-32 32zM860 896h-184c-19.8 0-36-14.4-36-32s16.2-32 36-32h184c19.8 0 36 14.4 36 32s-16.2 32-36 32z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57353,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 11,
- "order": 12,
- "prevSize": 32,
- "code": 57353,
- "name": "searchreplace",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 11
- },
- {
- "icon": {
- "paths": [
- "M704 384v-160c0-17.6-14.4-32-32-32h-160v-64c0-35.2-28.8-64-64-64h-128c-35.204 0-64 28.8-64 64v64h-160c-17.602 0-32 14.4-32 32v512c0 17.6 14.398 32 32 32h224v192h384l192-192v-384h-192zM320 128.114c0.034-0.038 0.072-0.078 0.114-0.114h127.768c0.042 0.036 0.082 0.076 0.118 0.114l0 63.886h-128v-63.886zM192 320v-64h384v64h-384zM704 869.49v-101.49h101.49l-101.49 101.49zM832 704h-192v192h-256v-448h448v256z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57352,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 12,
- "order": 13,
- "prevSize": 32,
- "code": 57352,
- "name": "paste",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 12
- },
- {
- "icon": {
- "paths": [
- "M832 320h-192v-64l-192-192h-384v704h384v192h576v-448l-192-192zM832 410.51l101.49 101.49h-101.49v-101.49zM448 154.51l101.49 101.49h-101.49v-101.49zM128 128h256v192h192v384h-448v-576zM960 896h-448v-128h128v-384h128v192h192v320z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57393,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 13,
- "order": 14,
- "prevSize": 32,
- "code": 57393,
- "name": "copy",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 13
- },
- {
- "icon": {
- "paths": [
- "M960 512h-265.876c-50.078-35.42-114.43-54.86-182.124-54.86-89.206 0-164.572-50.242-164.572-109.712 0-59.47 75.366-109.714 164.572-109.714 75.058 0 140.308 35.576 159.12 82.286h113.016c-7.93-50.644-37.58-97.968-84.058-132.826-50.88-38.16-117.676-59.174-188.078-59.174-70.404 0-137.196 21.014-188.074 59.174-54.788 41.090-86.212 99.502-86.212 160.254s31.424 119.164 86.212 160.254c1.956 1.466 3.942 2.898 5.946 4.316h-265.872v64h512.532c58.208 17.106 100.042 56.27 100.042 100.572 0 59.468-75.368 109.71-164.572 109.71-75.060 0-140.308-35.574-159.118-82.286h-113.016c7.93 50.64 37.582 97.968 84.060 132.826 50.876 38.164 117.668 59.18 188.072 59.18 70.402 0 137.198-21.016 188.074-59.174 54.79-41.090 86.208-99.502 86.208-160.254 0-35.298-10.654-69.792-30.294-100.572h204.012v-64z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57389,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 19,
- "order": 15,
- "prevSize": 32,
- "code": 57389,
- "name": "strikethrough",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 14
- },
- {
- "icon": {
- "paths": [
- "M192 832h576v64h-576v-64zM640 128v384c0 31.312-14.7 61.624-41.39 85.352-30.942 27.502-73.068 42.648-118.61 42.648-45.544 0-87.668-15.146-118.608-42.648-26.692-23.728-41.392-54.040-41.392-85.352v-384h-128v384c0 141.382 128.942 256 288 256s288-114.618 288-256v-384h-128z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57388,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 20,
- "order": 16,
- "prevSize": 32,
- "code": 57388,
- "name": "underline",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 15
- },
- {
- "icon": {
- "paths": [
- "M832 128v64h-144l-256 640h144v64h-448v-64h144l256-640h-144v-64h448z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57387,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 21,
- "order": 17,
- "prevSize": 32,
- "code": 57387,
- "name": "italic",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 16
- },
- {
- "icon": {
- "paths": [
- "M625.442 494.182c48.074-38.15 78.558-94.856 78.558-158.182 0-114.876-100.29-208-224-208h-224v768h288c123.712 0 224-93.124 224-208 0-88.196-59.118-163.562-142.558-193.818zM384 304c0-26.51 21.49-48 48-48h67.204c42.414 0 76.796 42.98 76.796 96s-34.382 96-76.796 96h-115.204v-144zM547.2 768h-115.2c-26.51 0-48-21.49-48-48v-144h163.2c42.418 0 76.8 42.98 76.8 96s-34.382 96-76.8 96z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57386,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 22,
- "order": 18,
- "prevSize": 32,
- "code": 57386,
- "name": "bold",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 17
- },
- {
- "icon": {
- "paths": [
- "M850.746 242.746l-133.492-133.49c-24.888-24.892-74.054-45.256-109.254-45.256h-416c-35.2 0-64 28.8-64 64v768c0 35.2 28.8 64 64 64h640c35.2 0 64-28.8 64-64v-544c0-35.2-20.366-84.364-45.254-109.254zM805.49 287.998c6.792 6.796 13.792 19.162 18.894 32.002h-184.384v-184.386c12.84 5.1 25.204 12.1 32 18.896l133.49 133.488zM831.884 896h-639.77c-0.040-0.034-0.082-0.076-0.114-0.116v-767.77c0.034-0.040 0.076-0.082 0.114-0.114h383.886v256h256v511.884c-0.034 0.040-0.076 0.082-0.116 0.116z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57345,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 23,
- "order": 19,
- "prevSize": 32,
- "code": 57345,
- "name": "newdocument",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 18
- },
- {
- "icon": {
- "paths": [
- "M960 880v-591.938l-223.938-224.062h-592.062c-44.182 0-80 35.816-80 80v736c0 44.184 35.818 80 80 80h736c44.184 0 80-35.816 80-80zM576 192h64v192h-64v-192zM704 832h-384v-255.882c0.034-0.042 0.076-0.082 0.116-0.118h383.77c0.040 0.036 0.082 0.076 0.116 0.118l-0.002 255.882zM832 832h-64v-256c0-35.2-28.8-64-64-64h-384c-35.2 0-64 28.8-64 64v256h-64v-640h64v192c0 35.2 28.8 64 64 64h320c35.2 0 64-28.8 64-64v-171.010l128 128.072v490.938z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57344,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 24,
- "order": 20,
- "prevSize": 32,
- "code": 57344,
- "name": "save",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 19
- },
- {
- "icon": {
- "paths": [
- "M64 192v704h896v-704h-896zM384 640v-128h256v128h-256zM640 704v128h-256v-128h256zM640 320v128h-256v-128h256zM320 320v128h-192v-128h192zM128 512h192v128h-192v-128zM704 512h192v128h-192v-128zM704 448v-128h192v128h-192zM128 704h192v128h-192v-128zM704 832v-128h192v128h-192z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57371,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 25,
- "order": 21,
- "prevSize": 32,
- "code": 57371,
- "name": "table",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 20
- },
- {
- "icon": {
- "paths": [
- "M512 140c99.366 0 192.782 38.694 263.042 108.956s108.958 163.678 108.958 263.044-38.696 192.782-108.958 263.042-163.676 108.958-263.042 108.958-192.782-38.696-263.044-108.958-108.956-163.676-108.956-263.042 38.694-192.782 108.956-263.044 163.678-108.956 263.044-108.956zM512 64c-247.424 0-448 200.576-448 448s200.576 448 448 448 448-200.576 448-448-200.576-448-448-448v0zM320 384c0 35.346 28.654 64 64 64s64-28.654 64-64c0-35.346-28.654-64-64-64-35.346 0-64 28.654-64 64zM576 384c0 35.346 28.654 64 64 64s64-28.654 64-64c0-35.346-28.654-64-64-64-35.346 0-64 28.654-64 64zM512 656c-101.84 0-192.56-36.874-251.166-94.328 23.126 117.608 126.778 206.328 251.166 206.328 124.388 0 228.040-88.72 251.168-206.328-58.608 57.454-149.328 94.328-251.168 94.328z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57377,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 26,
- "order": 22,
- "prevSize": 32,
- "code": 57377,
- "name": "emoticons",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 21
- },
- {
- "icon": {
- "paths": [
- "M480 384l-192-192 128-128h-352v352l128-128 192 192zM640 480l192-192 128 128v-352h-352l128 128-192 192zM544 640l192 192-128 128h352v-352l-128 128-192-192zM384 544l-192 192-128-128v352h352l-128-128 192-192z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57379,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 27,
- "order": 23,
- "prevSize": 32,
- "code": 57379,
- "name": "fullscreen",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 22
- },
- {
- "icon": {
- "paths": [
- "M64 448h896v128h-896z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57372,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 28,
- "order": 24,
- "prevSize": 32,
- "code": 57372,
- "name": "hr",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 23
- },
- {
- "icon": {
- "paths": [
- "M64 768h512v128h-512v-128zM768 192h-220.558l-183.766 512h-132.288l183.762-512h-223.15v-128h576v128zM929.774 896l-129.774-129.774-129.774 129.774-62.226-62.226 129.774-129.774-129.774-129.774 62.226-62.226 129.774 129.774 129.774-129.774 62.226 62.226-129.774 129.774 129.774 129.774-62.226 62.226z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57373,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 29,
- "order": 25,
- "prevSize": 32,
- "code": 57373,
- "name": "removeformat",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 24
- },
- {
- "icon": {
- "paths": [
- "M256 128h512v128h-512v-128zM896 320h-768c-35.2 0-64 28.8-64 64v256c0 35.2 28.796 64 64 64h128v192h512v-192h128c35.2 0 64-28.8 64-64v-256c0-35.2-28.8-64-64-64zM704 832h-384v-256h384v256zM910.4 416c0 25.626-20.774 46.4-46.398 46.4s-46.402-20.774-46.402-46.4 20.778-46.4 46.402-46.4c25.626 0 46.398 20.774 46.398 46.4z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57378,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 30,
- "order": 26,
- "prevSize": 32,
- "code": 57378,
- "name": "print",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 25
- },
- {
- "icon": {
- "paths": [
- "M384 128c-123.712 0-224 100.288-224 224s100.288 224 224 224v320h128v-640h64v640h128v-640h128v-128h-448z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57390,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 31,
- "order": 27,
- "prevSize": 32,
- "code": 57390,
- "name": "visualchars",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 26
- },
- {
- "icon": {
- "paths": [
- "M448 128c-123.712 0-224 100.288-224 224s100.288 224 224 224v320h128v-640h64v640h128v-640h128v-128h-448zM64 896l224-192-224-192z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57391,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 32,
- "order": 28,
- "prevSize": 32,
- "code": 57391,
- "name": "ltr",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 27
- },
- {
- "icon": {
- "paths": [
- "M416 704l-192-192 192-192-64-64-256 256 256 256zM672 256l-64 64 192 192-192 192 64 64 256-256z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57367,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 38,
- "order": 29,
- "prevSize": 32,
- "code": 57367,
- "name": "code",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 28
- },
- {
- "icon": {
- "paths": [
- "M448 704h128v128h-128v-128zM704 256c35.346 0 64 28.654 64 64v166l-228 154h-92v-64l192-128v-64h-320v-128h384zM512 64c-119.666 0-232.166 46.6-316.784 131.216-84.614 84.618-131.216 197.118-131.216 316.784 0 119.664 46.602 232.168 131.216 316.784 84.618 84.616 197.118 131.216 316.784 131.216 119.664 0 232.168-46.6 316.784-131.216 84.616-84.616 131.216-197.12 131.216-316.784 0-119.666-46.6-232.166-131.216-316.784-84.616-84.616-197.12-131.216-316.784-131.216z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57366,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 39,
- "order": 30,
- "prevSize": 32,
- "code": 57366,
- "name": "help",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 29
- },
- {
- "icon": {
- "paths": [
- "M896 128h-768c-35.2 0-64 28.8-64 64v640c0 35.2 28.8 64 64 64h768c35.2 0 64-28.8 64-64v-640c0-35.2-28.8-64-64-64zM896 831.884c-0.012 0.014-0.030 0.028-0.042 0.042l-191.958-319.926-160 128-224-288-191.968 479.916c-0.010-0.010-0.022-0.022-0.032-0.032v-639.77c0.034-0.040 0.076-0.082 0.114-0.114h767.77c0.040 0.034 0.082 0.076 0.116 0.116v639.768zM640 352c0 53.019 42.981 96 96 96s96-42.981 96-96c0-53.019-42.981-96-96-96-53.019 0-96 42.981-96 96z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57364,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 40,
- "order": 31,
- "prevSize": 32,
- "code": 57364,
- "name": "image",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 30
- },
- {
- "icon": {
- "paths": [
- "M896 128h-768c-35.2 0-64 28.8-64 64v640c0 35.2 28.8 64 64 64h768c35.2 0 64-28.8 64-64v-640c0-35.2-28.8-64-64-64zM256 832h-128v-128h128v128zM256 576h-128v-128h128v128zM256 320h-128v-128h128v128zM704 832h-384v-640h384v640zM896 832h-128v-128h128v128zM896 576h-128v-128h128v128zM896 320h-128v-128h128v128zM384 320v384l288-192z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57365,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 41,
- "order": 32,
- "prevSize": 32,
- "code": 57365,
- "name": "media",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 31
- },
- {
- "icon": {
- "paths": [
- "M77.798 304.624l81.414 50.882c50.802-81.114 128.788-143.454 221.208-174.246l-30.366-91.094c-113.748 37.898-209.728 114.626-272.256 214.458zM673.946 90.166l-30.366 91.094c92.422 30.792 170.404 93.132 221.208 174.248l81.412-50.882c-62.526-99.834-158.506-176.562-272.254-214.46zM607.974 704.008c-4.808 0-9.692-1.090-14.286-3.386l-145.688-72.844v-211.778c0-17.672 14.328-32 32-32s32 14.328 32 32v172.222l110.31 55.156c15.806 7.902 22.214 27.124 14.31 42.932-5.604 11.214-16.908 17.696-28.646 17.698zM512 192c-212.078 0-384 171.922-384 384s171.922 384 384 384c212.078 0 384-171.922 384-384 0-212.078-171.922-384-384-384zM512 864c-159.058 0-288-128.942-288-288s128.942-288 288-288c159.058 0 288 128.942 288 288 0 159.058-128.942 288-288 288z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57368,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 42,
- "order": 33,
- "prevSize": 32,
- "code": 57368,
- "name": "insertdatetime",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 32
- },
- {
- "icon": {
- "paths": [
- "M64 455.746c45.318-49.92 97.162-92.36 153.272-125.124 90.332-52.744 192.246-80.622 294.728-80.622 102.48 0 204.396 27.878 294.726 80.624 56.112 32.764 107.956 75.204 153.274 125.124v-117.432c-33.010-28.118-68.124-53.14-104.868-74.594-105.006-61.314-223.658-93.722-343.132-93.722s-238.128 32.408-343.134 93.72c-36.742 21.454-71.856 46.478-104.866 74.596v117.43zM512 320c-183.196 0-345.838 100.556-448 256 102.162 155.448 264.804 256 448 256 183.196 0 345.838-100.552 448-256-102.162-155.444-264.804-256-448-256zM512 512c0 35.346-28.654 64-64 64s-64-28.654-64-64c0-35.348 28.654-64 64-64s64 28.652 64 64zM728.066 696.662c-67.434 39.374-140.128 59.338-216.066 59.338s-148.632-19.964-216.066-59.338c-51.554-30.104-98.616-71.31-138.114-120.662 39.498-49.35 86.56-90.558 138.116-120.66 13.276-7.752 26.758-14.74 40.426-20.982-10.512 23.742-16.362 50.008-16.362 77.642 0 106.040 85.962 192 192 192 106.040 0 192-85.96 192-192 0-27.634-5.85-53.9-16.36-77.642 13.668 6.244 27.15 13.23 40.426 20.
982 51.554 30.102 98.616 71.31 138.116 120.66-39.498 49.352-86.56 90.558-138.116 120.662z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57369,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 43,
- "order": 34,
- "prevSize": 32,
- "code": 57369,
- "name": "preview",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 33
- },
- {
- "icon": {
- "paths": [
- "M651.168 283.834c-24.612-81.962-28.876-91.834-107.168-91.834h-64c-79.618 0-82.664 10.152-108.418 96 0 0.002 0 0.002-0.002 0.004l-143.998 479.996h113.636l57.6-192h226.366l57.6 192h113.63l-145.246-484.166zM437.218 448l38.4-136c10.086-33.618 36.38-30 36.38-30s26.294-3.618 36.38 30h0.004l38.4 136h-149.564z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57370,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 44,
- "order": 35,
- "prevSize": 32,
- "code": 57370,
- "name": "forecolor",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 34
- },
- {
- "icon": {
- "paths": [
- "M576 64c247.424 0 448 200.576 448 448s-200.576 448-448 448v-96c94.024 0 182.418-36.614 248.902-103.098 66.484-66.484 103.098-154.878 103.098-248.902 0-94.022-36.614-182.418-103.098-248.902-66.484-66.484-154.878-103.098-248.902-103.098-94.022 0-182.418 36.614-248.902 103.098-51.14 51.138-84.582 115.246-97.306 184.902h186.208l-224 256-224-256h164.57c31.060-217.102 217.738-384 443.43-384zM768 448v128h-256v-320h128v192z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57384,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 45,
- "order": 36,
- "prevSize": 32,
- "code": 57384,
- "name": "restoredraft",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 35
- },
- {
- "icon": {
- "paths": [
- "M1024 592.458v-160.916l-159.144-15.914c-8.186-30.042-20.088-58.548-35.21-84.98l104.596-127.838-113.052-113.050-127.836 104.596c-26.434-15.124-54.942-27.026-84.982-35.208l-15.914-159.148h-160.916l-15.914 159.146c-30.042 8.186-58.548 20.086-84.98 35.208l-127.838-104.594-113.050 113.050 104.596 127.836c-15.124 26.432-27.026 54.94-35.21 84.98l-159.146 15.916v160.916l159.146 15.914c8.186 30.042 20.086 58.548 35.21 84.982l-104.596 127.836 113.048 113.048 127.838-104.596c26.432 15.124 54.94 27.028 84.98 35.21l15.916 159.148h160.916l15.914-159.144c30.042-8.186 58.548-20.088 84.982-35.21l127.836 104.596 113.048-113.048-104.596-127.836c15.124-26.434 27.028-54.942 35.21-84.98l159.148-15.92zM704 576l-128 128h-128l-128-128v-128l128-128h128l128 128v128z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57346,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 46,
- "order": 37,
- "prevSize": 32,
- "code": 57346,
- "name": "fullpage",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 36
- },
- {
- "icon": {
- "paths": [
- "M768 206v50h128v64h-192v-146l128-60v-50h-128v-64h192v146zM676 256h-136l-188 188-188-188h-136l256 256-256 256h136l188-188 188 188h136l-256-256z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57375,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 47,
- "order": 38,
- "prevSize": 32,
- "code": 57375,
- "name": "superscript",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 37
- },
- {
- "icon": {
- "paths": [
- "M768 910v50h128v64h-192v-146l128-60v-50h-128v-64h192v146zM676 256h-136l-188 188-188-188h-136l256 256-256 256h136l188-188 188 188h136l-256-256z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57374,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 48,
- "order": 39,
- "prevSize": 32,
- "code": 57374,
- "name": "subscript",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 38
- },
- {
- "icon": {
- "paths": [
- "M704 384v-160c0-17.6-14.4-32-32-32h-160v-64c0-35.2-28.8-64-64-64h-128c-35.204 0-64 28.8-64 64v64h-160c-17.602 0-32 14.4-32 32v512c0 17.6 14.398 32 32 32h224v192h576v-576h-192zM320 128.114c0.034-0.038 0.072-0.078 0.114-0.114h127.768c0.042 0.036 0.082 0.076 0.118 0.114l0 63.886h-128v-63.886zM192 320v-64h384v64h-384zM832 896h-448v-448h448v448zM448 512v128h32l32-64h64v192h-48v64h160v-64h-48v-192h64l32 64h32v-128z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "pastetext"
- ],
- "defaultCode": 57397,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 49,
- "order": 40,
- "prevSize": 32,
- "code": 57397,
- "name": "pastetext",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 39
- },
- {
- "icon": {
- "paths": [
- "M768 256h64v64h-64zM640 384h64v64h-64zM640 512h64v64h-64zM640 640h64v64h-64zM512 512h64v64h-64zM512 640h64v64h-64zM384 640h64v64h-64zM768 384h64v64h-64zM768 512h64v64h-64zM768 640h64v64h-64zM768 768h64v64h-64zM640 768h64v64h-64zM512 768h64v64h-64zM384 768h64v64h-64zM256 768h64v64h-64z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "resize",
- "dots"
- ],
- "defaultCode": 57394,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 50,
- "order": 41,
- "prevSize": 32,
- "code": 57394,
- "name": "resize",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 40
- },
- {
- "icon": {
- "paths": [
- "M928 128h-416l-32-64h-352l-64 128h896zM840.34 704h87.66l32-448h-896l64 640h356.080c-104.882-37.776-180.080-138.266-180.080-256 0-149.982 122.018-272 272-272 149.98 0 272 122.018 272 272 0 21.678-2.622 43.15-7.66 64zM874.996 849.75l-134.496-110.692c17.454-28.922 27.5-62.814 27.5-99.058 0-106.040-85.96-192-192-192s-192 85.96-192 192 85.96 192 192 192c36.244 0 70.138-10.046 99.058-27.5l110.692 134.496c22.962 26.678 62.118 28.14 87.006 3.252l5.492-5.492c24.888-24.888 23.426-64.044-3.252-87.006zM576 764c-68.484 0-124-55.516-124-124s55.516-124 124-124 124 55.516 124 124-55.516 124-124 124z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "browse"
- ],
- "defaultCode": 57396,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 51,
- "order": 42,
- "prevSize": 32,
- "code": 57396,
- "name": "browse",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 41
- },
- {
- "icon": {
- "paths": [
- "M864.408 670.132c-46.47-46.47-106.938-68.004-161.082-62.806l-63.326-63.326 192-192c0 0 128-128 0-256l-320 320-320-320c-128 128 0 256 0 256l192 192-63.326 63.326c-54.144-5.198-114.61 16.338-161.080 62.806-74.98 74.98-85.112 186.418-22.626 248.9 62.482 62.482 173.92 52.354 248.9-22.626 46.47-46.468 68.002-106.938 62.806-161.080l63.326-63.326 63.328 63.328c-5.196 54.144 16.336 114.61 62.806 161.078 74.978 74.98 186.418 85.112 248.898 22.626 62.488-62.482 52.356-173.918-22.624-248.9zM353.124 758.578c-2.212 24.332-15.020 49.826-35.14 69.946-22.212 22.214-51.080 35.476-77.218 35.476-10.524 0-25.298-2.228-35.916-12.848-21.406-21.404-17.376-73.132 22.626-113.136 22.212-22.214 51.080-35.476 77.218-35.476 10.524 0 25.298 2.228 35.916 12.848 13.112 13.11 13.47 32.688 12.514 43.19zM512 608c-35.346 0-64-28.654-64-64s28.654-64 64-64 64 28.654 64 64-28.654 64-64 64zM819.152 851.152c-10.62 10.62-25.392 12.848-35.916 12.848-26.138 0-55.006-13.262-77.218-35.476-20.122-20.12-32.928-45.614-3
5.138-69.946-0.958-10.502-0.6-30.080 12.514-43.192 10.618-10.622 25.39-12.848 35.916-12.848 26.136 0 55.006 13.262 77.216 35.474 40.004 40.008 44.032 91.736 22.626 113.14z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57351,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 14,
- "order": 43,
- "prevSize": 32,
- "code": 57351,
- "name": "cut",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 42
- },
- {
- "icon": {
- "paths": [
- "M64 192h896v128h-896zM64 576h896v128h-896zM64 384h896v128h-896zM64 768h896v128h-896z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57350,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 15,
- "order": 44,
- "prevSize": 32,
- "code": 57350,
- "name": "alignjustify",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 43
- },
- {
- "icon": {
- "paths": [
- "M64 192h896v128h-896zM64 576h896v128h-896zM256 384h512v128h-512zM256 768h512v128h-512z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57348,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 16,
- "order": 45,
- "prevSize": 32,
- "code": 57348,
- "name": "aligncenter",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 44
- },
- {
- "icon": {
- "paths": [
- "M64 192h896v128h-896zM64 576h896v128h-896zM384 384h576v128h-576zM384 768h576v128h-576z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57349,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 17,
- "order": 46,
- "prevSize": 32,
- "code": 57349,
- "name": "alignright",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 45
- },
- {
- "icon": {
- "paths": [
- "M64 192h896v128h-896zM64 576h896v128h-896zM64 384h576v128h-576zM64 768h576v128h-576z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57347,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 18,
- "order": 47,
- "prevSize": 32,
- "code": 57347,
- "name": "alignleft",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 46
- },
- {
- "icon": {
- "paths": [
- "M320 128c-123.712 0-224 100.288-224 224s100.288 224 224 224v320h128v-640h64v640h128v-640h128v-128h-448zM960 512l-224 192 224 192z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57392,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 33,
- "order": 48,
- "prevSize": 32,
- "code": 57392,
- "name": "rtl",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 47
- },
- {
- "icon": {
- "paths": [
- "M512 384h128v64h-128zM512 768h128v64h-128zM576 576h128v64h-128zM768 576v192h-64v64h128v-256zM384 576h128v64h-128zM320 768h128v64h-128zM320 384h128v64h-128zM192 192v256h64v-192h64v-64zM704 448h128v-256h-64v192h-64zM64 64v896h896v-896h-896zM896 896h-768v-768h768v768zM192 576v256h64v-192h64v-64zM576 192h128v64h-128zM384 192h128v64h-128z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57382,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 34,
- "order": 49,
- "prevSize": 32,
- "code": 57382,
- "name": "template",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 48
- },
- {
- "icon": {
- "paths": [
- "M816 64l16 384h-640l16-384h32l16 320h512l16-320h32zM208 960l-16-320h640l-16 320h-32l-16-256h-512l-16 256h-32zM64 512h128v64h-128zM256 512h128v64h-128zM448 512h128v64h-128zM640 512h128v64h-128zM832 512h128v64h-128z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57383,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 35,
- "order": 50,
- "prevSize": 32,
- "code": 57383,
- "name": "pagebreak",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 49
- },
- {
- "icon": {
- "paths": [
- "M960 128v-64h-192c-35.202 0-64 28.8-64 64v320c0 15.856 5.858 30.402 15.496 41.614l-303.496 260.386-142-148-82 70 224 288 416-448h128v-64h-192v-320h192zM256 512h64v-384c0-35.2-28.8-64-64-64h-128c-35.2 0-64 28.8-64 64v384h64v-192h128v192zM128 256v-128h128v128h-128zM640 448v-96c0-35.2-8.8-64-44-64 35.2 0 44-28.8 44-64v-96c0-35.2-28.8-64-64-64h-192v448h192c35.2 0 64-28.8 64-64zM448 128h128v128h-128v-128zM448 320h128v128h-128v-128z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57380,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 36,
- "order": 51,
- "prevSize": 32,
- "code": 57380,
- "name": "spellcheck",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 50
- },
- {
- "icon": {
- "paths": [
- "M448 512h-128v-128h128v-128h128v128h128v128h-128v128h-128v-128zM960 576v320h-896v-320h128v192h640v-192h128z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57381,
- "grid": 0
- },
- "attrs": [],
- "properties": {
- "id": 37,
- "order": 52,
- "prevSize": 32,
- "code": 57381,
- "name": "nonbreaking",
- "ligatures": ""
- },
- "setIdx": 0,
- "setId": 2,
- "iconIdx": 51
- },
- {
- "icon": {
- "paths": [
- "M256 352v-128c0-53.020 42.98-96 96-96h32v-128h-32c-123.712 0-224 100.288-224 224v128c0 53.020-42.98 96-96 96h-32v128h32c53.020 0 96 42.98 96 96v128c0 123.71 100.288 224 224 224h32v-128h-32c-53.020 0-96-42.98-96-96v-128c0-62.684-25.758-119.342-67.254-160 41.496-40.658 67.254-97.316 67.254-160z",
- "M1024 352v-128c0-53.020-42.98-96-96-96h-32v-128h32c123.71 0 224 100.288 224 224v128c0 53.020 42.98 96 96 96h32v128h-32c-53.020 0-96 42.98-96 96v128c0 123.71-100.29 224-224 224h-32v-128h32c53.020 0 96-42.98 96-96v-128c0-62.684 25.758-119.342 67.254-160-41.496-40.658-67.254-97.316-67.254-160z",
- "M768 320.882c0 70.692-57.308 128-128 128s-128-57.308-128-128c0-70.692 57.308-128 128-128s128 57.308 128 128z",
- "M640 511.118c-70.692 0-128 57.308-128 128 0 68.732 32 123.216 130.156 127.852-29.19 41.126-73.156 57.366-130.156 62.7v76c0 0 256 22.332 256-266.55-0.25-70.694-57.306-128.002-128-128.002z"
- ],
- "width": 1280,
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "code",
- "semicolon",
- "curly-braces"
- ],
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 1,
- "id": 0,
- "prevSize": 16,
- "code": 58883,
- "name": "codesample"
- },
- "setIdx": 1,
- "setId": 1,
- "iconIdx": 0
- }
- ],
- "height": 1024,
- "metadata": {
- "name": "tinymce-small"
- },
- "preferences": {
- "showGlyphs": true,
- "showQuickUse": true,
- "showQuickUse2": true,
- "showSVGs": true,
- "fontPref": {
- "prefix": "icon-",
- "metadata": {
- "fontFamily": "tinymce-small",
- "majorVersion": 1,
- "minorVersion": 0
- },
- "metrics": {
- "emSize": 1024,
- "baseline": 6.25,
- "whitespace": 50
- },
- "showMetrics": false,
- "showMetadata": false,
- "showVersion": false,
- "embed": false
- },
- "imagePref": {
- "prefix": "icon-",
- "png": true,
- "useClassSelector": true,
- "color": 4473924,
- "bgColor": 16777215
- },
- "historySize": 100,
- "showCodes": true
- }
-}
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymceskinslightgrayfontstinymcejson"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/src/wp-includes/js/tinymce/skins/lightgray/fonts/tinymce.json</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/skins/lightgray/fonts/tinymce.json 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/skins/lightgray/fonts/tinymce.json 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,3469 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-{
- "IcoMoonType": "selection",
- "icons": [
- {
- "icon": {
- "paths": [
- "M889.68 166.32c-93.608-102.216-228.154-166.32-377.68-166.32-282.77 0-512 229.23-512 512h96c0-229.75 186.25-416 416-416 123.020 0 233.542 53.418 309.696 138.306l-149.696 149.694h352v-352l-134.32 134.32z",
- "M928 512c0 229.75-186.25 416-416 416-123.020 0-233.542-53.418-309.694-138.306l149.694-149.694h-352v352l134.32-134.32c93.608 102.216 228.154 166.32 377.68 166.32 282.77 0 512-229.23 512-512h-96z"
- ],
- "attrs": [
- {},
- {}
- ],
- "isMulticolor": false,
- "isMulticolor2": false,
- "grid": 16,
- "tags": [
- "reload"
- ]
- },
- "attrs": [
- {},
- {}
- ],
- "properties": {
- "order": 647,
- "id": 120,
- "name": "reload",
- "prevSize": 32,
- "code": 59654
- },
- "setIdx": 0,
- "setId": 5,
- "iconIdx": 0
- },
- {
- "icon": {
- "paths": [
- "M0 64h128v128h-128v-128z",
- "M192 64h832v128h-832v-128z",
- "M0 448h128v128h-128v-128z",
- "M192 448h832v128h-832v-128z",
- "M0 832h128v128h-128v-128z",
- "M192 832h832v128h-832v-128z",
- "M192 256h128v128h-128v-128z",
- "M384 256h640v128h-640v-128z",
- "M192 640h128v128h-128v-128z",
- "M384 640h640v128h-640v-128z"
- ],
- "attrs": [
- {},
- {},
- {},
- {},
- {},
- {},
- {},
- {},
- {},
- {}
- ],
- "isMulticolor": false,
- "isMulticolor2": false,
- "tags": [
- "toc"
- ],
- "grid": 16
- },
- "attrs": [
- {},
- {},
- {},
- {},
- {},
- {},
- {},
- {},
- {},
- {}
- ],
- "properties": {
- "order": 646,
- "id": 1,
- "name": "toc",
- "prevSize": 32,
- "code": 59649
- },
- "setIdx": 0,
- "setId": 6,
- "iconIdx": 1
- },
- {
- "icon": {
- "paths": [
- "M576.234 289.27l242.712-81.432 203.584 606.784-242.712 81.432zM0 896h256v-704h-256v704zM64 320h128v64h-128v-64zM320 896h256v-704h-256v704zM384 320h128v64h-128v-64z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "books",
- "library",
- "archive"
- ],
- "defaultCode": 57458,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 523,
- "id": 1722,
- "prevSize": 32,
- "code": 59665,
- "name": "books",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 0
- },
- {
- "icon": {
- "paths": [
- "M0 416v192c0 17.672 14.328 32 32 32h960c17.672 0 32-14.328 32-32v-192c0-17.672-14.328-32-32-32h-960c-17.672 0-32 14.328-32 32z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "minus",
- "minimize",
- "subtract"
- ],
- "defaultCode": 58229,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 597,
- "id": 1723,
- "prevSize": 32,
- "code": 59705,
- "name": "minus",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 1
- },
- {
- "icon": {
- "paths": [
- "M992 384h-352v-352c0-17.672-14.328-32-32-32h-192c-17.672 0-32 14.328-32 32v352h-352c-17.672 0-32 14.328-32 32v192c0 17.672 14.328 32 32 32h352v352c0 17.672 14.328 32 32 32h192c17.672 0 32-14.328 32-32v-352h352c17.672 0 32-14.328 32-32v-192c0-17.672-14.328-32-32-32z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "plus",
- "add",
- "sum"
- ],
- "defaultCode": 58230,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 598,
- "id": 1724,
- "prevSize": 32,
- "code": 59706,
- "name": "plus",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 2
- },
- {
- "icon": {
- "paths": [
- "M521.6 44.8l-67.2 67.2-86.4-86.4-86.4 86.4 86.4 86.4-368 368 432 432 518.4-518.4-428.8-435.2zM435.2 825.6l-262.4-262.4 35.2-35.2 576-51.2-348.8 348.8zM953.6 550.4c-6.4 6.4-16 16-28.8 32-28.8 32-41.6 64-41.6 89.6v0 0 0 0 0 0 0c0 16 6.4 35.2 22.4 48 12.8 12.8 32 22.4 48 22.4s35.2-6.4 48-22.4 22.4-32 22.4-48v0 0 0 0 0 0 0c0-25.6-12.8-54.4-41.6-89.6-9.6-16-22.4-25.6-28.8-32v0z"
- ],
- "attrs": [
- {}
- ],
- "isMulticolor": false,
- "tags": [
- "fill"
- ],
- "grid": 16
- },
- "attrs": [
- {}
- ],
- "properties": {
- "order": 599,
- "id": 1695,
- "prevSize": 32,
- "code": 59650,
- "name": "fill"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 3
- },
- {
- "icon": {
- "paths": [
- "M0 694.4h1024v128h-1024v-128z",
- "M0 928h1024v64h-1024v-64z",
- "M0 393.6h1024v192h-1024v-192z",
- "M0 32h1024v256h-1024v-256z"
- ],
- "attrs": [
- {},
- {},
- {},
- {}
- ],
- "isMulticolor": false,
- "tags": [
- "borderwidth"
- ],
- "grid": 16
- },
- "attrs": [
- {},
- {},
- {},
- {}
- ],
- "properties": {
- "order": 524,
- "id": 1696,
- "prevSize": 32,
- "code": 59651,
- "name": "borderwidth"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 4
- },
- {
- "icon": {
- "paths": [
- "M739.2 332.8l-502.4 502.4h-185.6v-185.6l502.4-502.4 185.6 185.6zM803.2 272l-185.6-185.6 67.2-67.2c22.4-22.4 54.4-22.4 76.8 0l108.8 108.8c22.4 22.4 22.4 54.4 0 76.8l-67.2 67.2zM41.6 912h940.8v112h-940.8v-112z"
- ],
- "attrs": [
- {}
- ],
- "isMulticolor": false,
- "tags": [
- "line"
- ],
- "grid": 16
- },
- "attrs": [
- {}
- ],
- "properties": {
- "order": 525,
- "id": 1697,
- "prevSize": 32,
- "code": 59652,
- "name": "line"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 5
- },
- {
- "icon": {
- "paths": [
- "M0 480h1024v64h-1024v-64z",
- "M304 48v339.2h-67.2v-272h-67.2v-67.2z",
- "M444.8 265.6v54.4h134.4v67.2h-201.6v-153.6l134.4-64v-54.4h-134.4v-67.2h201.6v153.6z",
- "M854.4 48v339.2h-204.8v-67.2h137.6v-67.2h-137.6v-70.4h137.6v-67.2h-137.6v-67.2z",
- "M115.2 793.6c3.2-57.6 38.4-83.2 108.8-83.2 38.4 0 67.2 9.6 86.4 25.6s25.6 35.2 25.6 70.4v112c0 25.6 0 28.8 9.6 41.6h-73.6c-3.2-9.6-3.2-9.6-6.4-19.2-22.4 19.2-41.6 25.6-70.4 25.6-54.4 0-89.6-32-89.6-76.8s28.8-70.4 99.2-80l38.4-6.4c16-3.2 22.4-6.4 22.4-16 0-12.8-12.8-22.4-38.4-22.4s-41.6 9.6-44.8 28.8h-67.2zM262.4 844.8c-6.4 3.2-12.8 6.4-25.6 6.4l-25.6 6.4c-25.6 6.4-38.4 16-38.4 28.8 0 16 12.8 25.6 35.2 25.6s41.6-9.6 54.4-32v-35.2z",
- "M390.4 624h73.6v112c22.4-16 41.6-22.4 67.2-22.4 64 0 105.6 51.2 105.6 124.8 0 76.8-44.8 134.4-108.8 134.4-32 0-48-9.6-67.2-35.2v28.8h-70.4v-342.4zM460.8 838.4c0 41.6 22.4 70.4 51.2 70.4s51.2-28.8 51.2-70.4c0-44.8-19.2-70.4-51.2-70.4-28.8 0-51.2 28.8-51.2 70.4z",
- "M851.2 806.4c-3.2-22.4-19.2-35.2-44.8-35.2-32 0-51.2 25.6-51.2 70.4 0 48 19.2 73.6 51.2 73.6 25.6 0 41.6-12.8 44.8-41.6l70.4 3.2c-9.6 60.8-54.4 96-118.4 96-73.6 0-121.6-51.2-121.6-128 0-80 48-131.2 124.8-131.2 64 0 108.8 35.2 112 96h-67.2z"
- ],
- "attrs": [
- {},
- {},
- {},
- {},
- {},
- {},
- {}
- ],
- "isMulticolor": false,
- "tags": [
- "count"
- ],
- "grid": 16
- },
- "attrs": [
- {},
- {},
- {},
- {},
- {},
- {},
- {}
- ],
- "properties": {
- "order": 526,
- "id": 1698,
- "prevSize": 32,
- "code": 59653,
- "name": "count"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 6
- },
- {
- "icon": {
- "paths": [
- "M553.6 656l-118.4-118.4c80-89.6 137.6-195.2 172.8-304h137.6v-92.8h-326.4v-92.8h-92.8v92.8h-326.4v92.8h518.4c-32 89.6-80 176-147.2 249.6-44.8-48-80-99.2-108.8-156.8h-92.8c35.2 76.8 80 147.2 137.6 211.2l-236.8 233.6 67.2 67.2 233.6-233.6 144 144c3.2 0 38.4-92.8 38.4-92.8zM816 419.2h-92.8l-208 560h92.8l51.2-140.8h220.8l51.2 140.8h92.8l-208-560zM691.2 745.6l76.8-201.6 76.8 201.6h-153.6z"
- ],
- "attrs": [
- {}
- ],
- "isMulticolor": false,
- "tags": [
- "translate"
- ],
- "grid": 16
- },
- "attrs": [
- {}
- ],
- "properties": {
- "order": 527,
- "id": 1699,
- "prevSize": 32,
- "code": 59655,
- "name": "translate"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 7
- },
- {
- "icon": {
- "paths": [
- "M576 64h128v128h-128v-128z",
- "M576 320h128v128h-128v-128z",
- "M320 320h128v128h-128v-128z",
- "M576 576h128v128h-128v-128z",
- "M320 576h128v128h-128v-128z",
- "M320 832h128v128h-128v-128z",
- "M576 832h128v128h-128v-128z",
- "M320 64h128v128h-128v-128z"
- ],
- "attrs": [
- {
- "opacity": 1,
- "visibility": false
- },
- {
- "opacity": 1,
- "visibility": false
- },
- {
- "opacity": 1,
- "visibility": false
- },
- {
- "opacity": 1,
- "visibility": false
- },
- {
- "opacity": 1,
- "visibility": false
- },
- {
- "opacity": 1,
- "visibility": false
- },
- {
- "opacity": 1,
- "visibility": false
- },
- {
- "opacity": 1,
- "visibility": false
- },
- {
- "opacity": 1,
- "visibility": false
- }
- ],
- "isMulticolor": false,
- "tags": [
- "drag"
- ],
- "grid": 16
- },
- "attrs": [
- {
- "opacity": 1,
- "visibility": false
- },
- {
- "opacity": 1,
- "visibility": false
- },
- {
- "opacity": 1,
- "visibility": false
- },
- {
- "opacity": 1,
- "visibility": false
- },
- {
- "opacity": 1,
- "visibility": false
- },
- {
- "opacity": 1,
- "visibility": false
- },
- {
- "opacity": 1,
- "visibility": false
- },
- {
- "opacity": 1,
- "visibility": false
- },
- {
- "opacity": 1,
- "visibility": false
- }
- ],
- "properties": {
- "order": 528,
- "id": 1700,
- "prevSize": 32,
- "code": 59656,
- "name": "drag",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 8
- },
- {
- "icon": {
- "paths": [
- "M1024 590.444l-512-397.426-512 397.428v-162.038l512-397.426 512 397.428zM896 576v384h-256v-256h-256v256h-256v-384l384-288z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "home"
- ],
- "defaultCode": 57345,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 529,
- "id": 1701,
- "prevSize": 32,
- "code": 59659,
- "name": "home",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 9
- },
- {
- "icon": {
- "paths": [
- "M839.432 199.43c27.492 27.492 50.554 78.672 55.552 120.57h-318.984v-318.984c41.898 4.998 93.076 28.060 120.568 55.552l142.864 142.862zM512 384v-384h-368c-44 0-80 36-80 80v864c0 44 36 80 80 80h672c44 0 80-36 80-80v-560h-384zM576 768v192h-192v-192h-160l256-256 256 256h-160z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "upload"
- ],
- "defaultCode": 57474,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 530,
- "id": 1702,
- "prevSize": 32,
- "code": 59668,
- "name": "upload",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 10
- },
- {
- "icon": {
- "paths": [
- "M928 64h-832c-52.8 0-96 43.2-96 96v512c0 52.8 43.2 96 96 96h160v256l307.2-256h364.8c52.8 0 96-43.2 96-96v-512c0-52.8-43.2-96-96-96zM896 640h-379.142l-196.858 174.714v-174.714h-192v-448h768v448z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "bubble"
- ],
- "defaultCode": 57703,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 600,
- "id": 1703,
- "prevSize": 32,
- "code": 59676,
- "name": "bubble",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 11
- },
- {
- "icon": {
- "paths": [
- "M622.826 702.736c-22.11-3.518-22.614-64.314-22.614-64.314s64.968-64.316 79.128-150.802c38.090 0 61.618-91.946 23.522-124.296 1.59-34.054 48.96-267.324-190.862-267.324-239.822 0-192.45 233.27-190.864 267.324-38.094 32.35-14.57 124.296 23.522 124.296 14.158 86.486 79.128 150.802 79.128 150.802s-0.504 60.796-22.614 64.314c-71.22 11.332-337.172 128.634-337.172 257.264h896c0-128.63-265.952-245.932-337.174-257.264z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "user"
- ],
- "defaultCode": 57733,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 601,
- "id": 1704,
- "prevSize": 32,
- "code": 59677,
- "name": "user",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 12
- },
- {
- "icon": {
- "paths": [
- "M592 448h-16v-192c0-105.87-86.13-192-192-192h-128c-105.87 0-192 86.13-192 192v192h-16c-26.4 0-48 21.6-48 48v480c0 26.4 21.6 48 48 48h544c26.4 0 48-21.6 48-48v-480c0-26.4-21.6-48-48-48zM192 256c0-35.29 28.71-64 64-64h128c35.29 0 64 28.71 64 64v192h-256v-192z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "lock"
- ],
- "defaultCode": 57811,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 602,
- "id": 1705,
- "prevSize": 32,
- "code": 59686,
- "name": "lock"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 13
- },
- {
- "icon": {
- "paths": [
- "M768 64c105.87 0 192 86.13 192 192v192h-128v-192c0-35.29-28.71-64-64-64h-128c-35.29 0-64 28.71-64 64v192h16c26.4 0 48 21.6 48 48v480c0 26.4-21.6 48-48 48h-544c-26.4 0-48-21.6-48-48v-480c0-26.4 21.6-48 48-48h400v-192c0-105.87 86.13-192 192-192h128z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "unlock"
- ],
- "defaultCode": 57812,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 603,
- "id": 1706,
- "prevSize": 32,
- "code": 59687,
- "name": "unlock"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 14
- },
- {
- "icon": {
- "paths": [
- "M448 128v-16c0-26.4-21.6-48-48-48h-160c-26.4 0-48 21.6-48 48v16h-192v128h192v16c0 26.4 21.6 48 48 48h160c26.4 0 48-21.6 48-48v-16h576v-128h-576zM256 256v-128h128v128h-128zM832 432c0-26.4-21.6-48-48-48h-160c-26.4 0-48 21.6-48 48v16h-576v128h576v16c0 26.4 21.6 48 48 48h160c26.4 0 48-21.6 48-48v-16h192v-128h-192v-16zM640 576v-128h128v128h-128zM448 752c0-26.4-21.6-48-48-48h-160c-26.4 0-48 21.6-48 48v16h-192v128h192v16c0 26.4 21.6 48 48 48h160c26.4 0 48-21.6 48-48v-16h576v-128h-576v-16zM256 896v-128h128v128h-128z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "settings"
- ],
- "defaultCode": 57819,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 604,
- "id": 1707,
- "prevSize": 32,
- "code": 59688,
- "name": "settings",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 15
- },
- {
- "icon": {
- "paths": [
- "M192 1024h640l64-704h-768zM640 128v-128h-256v128h-320v192l64-64h768l64 64v-192h-320zM576 128h-128v-64h128v64z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "remove2"
- ],
- "defaultCode": 57935,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 605,
- "id": 1708,
- "prevSize": 32,
- "code": 59690,
- "name": "remove2",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 16
- },
- {
- "icon": {
- "paths": [
- "M384 64h256v256h-256zM384 384h256v256h-256zM384 704h256v256h-256z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "menu"
- ],
- "defaultCode": 58025,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 606,
- "id": 1709,
- "prevSize": 32,
- "code": 59693,
- "name": "menu",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 17
- },
- {
- "icon": {
- "paths": [
- "M1009.956 915.76l-437.074-871.112c-16.742-29.766-38.812-44.648-60.882-44.648s-44.14 14.882-60.884 44.648l-437.074 871.112c-33.486 59.532-5 108.24 63.304 108.24h869.308c68.302 0 96.792-48.708 63.302-108.24zM512 896c-35.346 0-64-28.654-64-64 0-35.348 28.654-64 64-64 35.348 0 64 28.652 64 64 0 35.346-28.652 64-64 64zM556 704h-88l-20-256c0-35.346 28.654-64 64-64s64 28.654 64 64l-20 256z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "warning"
- ],
- "defaultCode": 58198,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 531,
- "id": 1710,
- "prevSize": 32,
- "code": 59696,
- "name": "warning"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 18
- },
- {
- "icon": {
- "paths": [
- "M448 704h128v128h-128zM704 256c35.346 0 64 28.654 64 64v192l-192 128h-128v-64l192-128v-64h-320v-128h384zM512 96c-111.118 0-215.584 43.272-294.156 121.844s-121.844 183.038-121.844 294.156c0 111.118 43.272 215.584 121.844 294.156 78.572 78.572 183.038 121.844 294.156 121.844 111.118 0 215.584-43.272 294.156-121.844 78.572-78.572 121.844-183.038 121.844-294.156 0-111.118-43.272-215.584-121.844-294.156-78.572-78.572-183.038-121.844-294.156-121.844zM512 0v0c282.77 0 512 229.23 512 512s-229.23 512-512 512c-282.77 0-512-229.23-512-512 0-282.77 229.23-512 512-512z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "question"
- ],
- "defaultCode": 58201,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 532,
- "id": 1711,
- "prevSize": 32,
- "code": 59697,
- "name": "question",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 19
- },
- {
- "icon": {
- "paths": [
- "M512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512 512-229.23 512-512-229.23-512-512-512zM512 896c-212.078 0-384-171.922-384-384s171.922-384 384-384c212.078 0 384 171.922 384 384 0 212.078-171.922 384-384 384zM768 576h-192v192h-128v-192h-192v-128h192v-192h128v192h192z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "pluscircle"
- ],
- "defaultCode": 58206,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 533,
- "id": 1712,
- "prevSize": 32,
- "code": 59698,
- "name": "pluscircle",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 20
- },
- {
- "icon": {
- "paths": [
- "M512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512 512-229.23 512-512-229.23-512-512-512zM448 192h128v128h-128v-128zM640 832h-256v-64h64v-256h-64v-64h192v320h64v64z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "info"
- ],
- "defaultCode": 58211,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 534,
- "id": 1713,
- "prevSize": 32,
- "code": 59699,
- "name": "info"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 21
- },
- {
- "icon": {
- "paths": [
- "M1024 736 736 0h-448l-288 288v448l288 288h448l288-288v-448l-288-288zM576 832h-128v-128h128v128zM576 576h-128v-384h128v384z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "notice"
- ],
- "defaultCode": 58218,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 535,
- "id": 1714,
- "prevSize": 32,
- "code": 59700,
- "name": "notice"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 22
- },
- {
- "icon": {
- "paths": [
- "M0 640l192 192 320-320 320 320 192-192-511.998-512z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "arrowup"
- ],
- "defaultCode": 58288,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 536,
- "id": 1715,
- "prevSize": 32,
- "code": 59707,
- "name": "arrowup",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 23
- },
- {
- "icon": {
- "paths": [
- "M384 0l-192 192 320 320-320 320 192 192 512-512z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "arrowright"
- ],
- "defaultCode": 58289,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 537,
- "id": 1716,
- "prevSize": 32,
- "code": 59708,
- "name": "arrowright",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 24
- },
- {
- "icon": {
- "paths": [
- "M1024 384l-192-192-320 320-320-320-192 192 512 511.998z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "arrowdown"
- ],
- "defaultCode": 58290,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 538,
- "id": 1717,
- "prevSize": 32,
- "code": 59709,
- "name": "arrowdown",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 25
- },
- {
- "icon": {
- "paths": [
- "M768 640l-256-256-256 256z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "arrowup2"
- ],
- "defaultCode": 58292,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 539,
- "id": 1718,
- "prevSize": 32,
- "code": 59711,
- "name": "arrowup2",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 26
- },
- {
- "icon": {
- "paths": [
- "M256 384l256 256 256-256z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "arrowdown2"
- ],
- "defaultCode": 58294,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 540,
- "id": 1719,
- "prevSize": 32,
- "code": 59712,
- "name": "arrowdown2",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 27
- },
- {
- "icon": {
- "paths": [
- "M256 256l256 256 256-256zM255.996 575.996l256 256 256-256z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "menu2"
- ],
- "defaultCode": 58393,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 541,
- "id": 1720,
- "prevSize": 32,
- "code": 59713,
- "name": "menu2",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 28
- },
- {
- "icon": {
- "paths": [
- "M704 576l128-128v512h-768v-768h512l-128 128h-256v512h512zM960 64v352l-130.744-130.744-354.746 354.744h-90.51v-90.512l354.744-354.744-130.744-130.744z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "newtab"
- ],
- "defaultCode": 58492,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 607,
- "id": 1721,
- "prevSize": 32,
- "code": 59745,
- "name": "newtab",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 29
- },
- {
- "icon": {
- "paths": [
- "M960 256v-64l-448 128-448-128v64l320 128v256l-128 448h64l192-448 192 448h64l-128-448v-256zM416 160q0-40 28-68t68-28 68 28 28 68-28 68-68 28-68-28-28-68z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "grid": 16,
- "tags": [
- "a11y"
- ]
- },
- "attrs": [],
- "properties": {
- "order": 608,
- "id": 1694,
- "prevSize": 32,
- "code": 59648,
- "name": "a11y"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 30
- },
- {
- "icon": {
- "paths": [
- "M892.8 982.4l-89.6-89.6c-70.4 80-172.8 131.2-288 131.2-208 0-380.8-166.4-384-377.6 0 0 0 0 0 0 0-3.2 0-3.2 0-6.4s0-3.2 0-6.4v0c0 0 0 0 0-3.2 0 0 0-3.2 0-3.2 3.2-105.6 48-211.2 105.6-304l-192-192 44.8-44.8 182.4 182.4c0 0 0 0 0 0l569.6 569.6c0 0 0 0 0 0l99.2 99.2-48 44.8zM896 633.6c0 0 0 0 0 0 0-3.2 0-6.4 0-6.4-9.6-316.8-384-627.2-384-627.2s-108.8 89.6-208 220.8l70.4 70.4c6.4-9.6 16-22.4 22.4-32 41.6-51.2 83.2-96 115.2-128v0c32 32 73.6 76.8 115.2 128 108.8 137.6 169.6 265.6 172.8 371.2 0 0 0 3.2 0 3.2v0 0c0 3.2 0 3.2 0 6.4s0 3.2 0 3.2v0 0c0 22.4-3.2 41.6-9.6 64l76.8 76.8c16-41.6 28.8-89.6 28.8-137.6 0 0 0 0 0 0 0-3.2 0-3.2 0-6.4s-0-3.2-0-6.4z"
- ],
- "attrs": [
- {}
- ],
- "isMulticolor": false,
- "tags": [
- "invert"
- ],
- "grid": 16,
- "defaultCode": 58882
- },
- "attrs": [
- {}
- ],
- "properties": {
- "order": 609,
- "id": 0,
- "prevSize": 32,
- "code": 58882,
- "name": "invert"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 31
- },
- {
- "icon": {
- "paths": [
- "M928 128h-416l-32-64h-352l-64 128h896zM904.34 704h74.86l44.8-448h-1024l64 640h484.080c-104.882-37.776-180.080-138.266-180.080-256 0-149.982 122.018-272 272-272 149.98 0 272 122.018 272 272 0 21.678-2.622 43.15-7.66 64zM1002.996 913.75l-198.496-174.692c17.454-28.92 27.5-62.814 27.5-99.058 0-106.040-85.96-192-192-192s-192 85.96-192 192 85.96 192 192 192c36.244 0 70.138-10.046 99.058-27.5l174.692 198.496c22.962 26.678 62.118 28.14 87.006 3.252l5.492-5.492c24.888-24.888 23.426-64.044-3.252-87.006zM640 764c-68.484 0-124-55.516-124-124s55.516-124 124-124 124 55.516 124 124-55.516 124-124 124z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57396,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 0,
- "order": 610,
- "prevSize": 32,
- "code": 57396,
- "name": "browse",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 32
- },
- {
- "icon": {
- "paths": [
- "M768 256h64v64h-64zM640 384h64v64h-64zM640 512h64v64h-64zM640 640h64v64h-64zM512 512h64v64h-64zM512 640h64v64h-64zM384 640h64v64h-64zM768 384h64v64h-64zM768 512h64v64h-64zM768 640h64v64h-64zM768 768h64v64h-64zM640 768h64v64h-64zM512 768h64v64h-64zM384 768h64v64h-64zM256 768h64v64h-64z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "resize",
- "dots"
- ],
- "defaultCode": 57394,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 1,
- "order": 611,
- "prevSize": 32,
- "code": 57394,
- "name": "resize",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 33
- },
- {
- "icon": {
- "paths": [
- "M832 256h-192v-64l-192-192h-448v768h384v256h640v-576l-192-192zM832 346.51l101.49 101.49h-101.49v-101.49zM448 90.51l101.49 101.49h-101.49v-101.49zM64 64h320v192h192v448h-512v-640zM960 960h-512v-192h192v-448h128v192h192v448z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "copy"
- ],
- "defaultCode": 57393,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 2,
- "order": 612,
- "prevSize": 32,
- "code": 57393,
- "name": "copy",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 34
- },
- {
- "icon": {
- "paths": [
- "M256 64h512v128h-128v768h-128v-768h-128v768h-128v-448c-123.712 0-224-100.288-224-224s100.288-224 224-224zM960 896l-256-224 256-224z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "rtl"
- ],
- "defaultCode": 57392,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 3,
- "order": 613,
- "prevSize": 32,
- "code": 57392,
- "name": "rtl",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 35
- },
- {
- "icon": {
- "paths": [
- "M448 64h512v128h-128v768h-128v-768h-128v768h-128v-448c-123.712 0-224-100.288-224-224s100.288-224 224-224zM64 448l256 224-256 224z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "ltr"
- ],
- "defaultCode": 57391,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 4,
- "order": 542,
- "prevSize": 32,
- "code": 57391,
- "name": "ltr",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 36
- },
- {
- "icon": {
- "paths": [
- "M384 64h512v128h-128v768h-128v-768h-128v768h-128v-448c-123.712 0-224-100.288-224-224s100.288-224 224-224z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "visualchars"
- ],
- "defaultCode": 57390,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 5,
- "order": 543,
- "prevSize": 32,
- "code": 57390,
- "name": "visualchars",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 37
- },
- {
- "icon": {
- "paths": [
- "M731.42 517.036c63.92 47.938 100.58 116.086 100.58 186.964s-36.66 139.026-100.58 186.964c-59.358 44.518-137.284 69.036-219.42 69.036-82.138 0-160.062-24.518-219.42-69.036-63.92-47.938-100.58-116.086-100.58-186.964h128c0 69.382 87.926 128 192 128 104.074 0 192-58.618 192-128 0-69.382-87.926-128-192-128-82.138 0-160.062-24.518-219.42-69.036-63.92-47.94-100.58-116.086-100.58-186.964 0-70.878 36.66-139.024 100.58-186.964 59.358-44.518 137.282-69.036 219.42-69.036 82.136 0 160.062 24.518 219.42 69.036 63.92 47.94 100.58 116.086 100.58 186.964h-128c0-69.382-87.926-128-192-128-104.074 0-192 58.618-192 128 0 69.382 87.926 128 192 128 82.136 0 160.062 24.518 219.42 69.036zM0 512h1024v64h-1024z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "strikethrough"
- ],
- "defaultCode": 57389,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 6,
- "order": 544,
- "prevSize": 32,
- "code": 57389,
- "name": "strikethrough",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 38
- },
- {
- "icon": {
- "paths": [
- "M704 64h128v416c0 159.058-143.268 288-320 288-176.73 0-320-128.942-320-288v-416h128v416c0 40.166 18.238 78.704 51.354 108.506 36.896 33.204 86.846 51.494 140.646 51.494 53.8 0 103.75-18.29 140.646-51.494 33.116-29.802 51.354-68.34 51.354-108.506v-416zM192 832h640v128h-640z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "underline"
- ],
- "defaultCode": 57388,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 7,
- "order": 545,
- "prevSize": 32,
- "code": 57388,
- "name": "underline",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 39
- },
- {
- "icon": {
- "paths": [
- "M896 64v64h-128l-320 768h128v64h-448v-64h128l320-768h-128v-64z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "italic"
- ],
- "defaultCode": 57387,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 8,
- "order": 546,
- "prevSize": 32,
- "code": 57387,
- "name": "italic",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 40
- },
- {
- "icon": {
- "paths": [
- "M707.88 484.652c37.498-44.542 60.12-102.008 60.12-164.652 0-141.16-114.842-256-256-256h-320v896h384c141.158 0 256-114.842 256-256 0-92.956-49.798-174.496-124.12-219.348zM384 192h101.5c55.968 0 101.5 57.42 101.5 128s-45.532 128-101.5 128h-101.5v-256zM543 832h-159v-256h159c58.45 0 106 57.42 106 128s-47.55 128-106 128z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "bold0"
- ],
- "defaultCode": 57386,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 9,
- "order": 547,
- "prevSize": 32,
- "code": 57386,
- "name": "bold",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 41
- },
- {
- "icon": {
- "paths": [
- "M576 64c247.424 0 448 200.576 448 448s-200.576 448-448 448v-96c94.024 0 182.418-36.614 248.902-103.098 66.484-66.484 103.098-154.878 103.098-248.902 0-94.022-36.614-182.418-103.098-248.902-66.484-66.484-154.878-103.098-248.902-103.098-94.022 0-182.418 36.614-248.902 103.098-51.14 51.138-84.582 115.246-97.306 184.902h186.208l-224 256-224-256h164.57c31.060-217.102 217.738-384 443.43-384zM768 448v128h-256v-320h128v192z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "restoredraft"
- ],
- "defaultCode": 57384,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 11,
- "order": 548,
- "prevSize": 32,
- "code": 57384,
- "name": "restoredraft",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 42
- },
- {
- "icon": {
- "paths": [
- "M0 512h128v64h-128zM192 512h192v64h-192zM448 512h128v64h-128zM640 512h192v64h-192zM896 512h128v64h-128zM880 0l16 448h-768l16-448h32l16 384h640l16-384zM144 1024l-16-384h768l-16 384h-32l-16-320h-640l-16 320z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "pagebreak"
- ],
- "defaultCode": 57383,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 12,
- "order": 549,
- "prevSize": 32,
- "code": 57383,
- "name": "pagebreak",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 43
- },
- {
- "icon": {
- "paths": [
- "M384 192h128v64h-128zM576 192h128v64h-128zM896 192v256h-192v-64h128v-128h-64v-64zM320 384h128v64h-128zM512 384h128v64h-128zM192 256v128h64v64h-128v-256h192v64zM384 576h128v64h-128zM576 576h128v64h-128zM896 576v256h-192v-64h128v-128h-64v-64zM320 768h128v64h-128zM512 768h128v64h-128zM192 640v128h64v64h-128v-256h192v64zM960 64h-896v896h896v-896zM1024 0v0 1024h-1024v-1024h1024z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "template"
- ],
- "defaultCode": 57382,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 13,
- "order": 550,
- "prevSize": 32,
- "code": 57382,
- "name": "template",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 44
- },
- {
- "icon": {
- "paths": [
- "M448 576h-192v-128h192v-192h128v192h192v128h-192v192h-128zM1024 640v384h-1024v-384h128v256h768v-256z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "nonbreaking"
- ],
- "defaultCode": 57381,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 14,
- "order": 551,
- "prevSize": 32,
- "code": 57381,
- "name": "nonbreaking",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 45
- },
- {
- "icon": {
- "paths": [
- "M128 256h128v192h64v-384c0-35.2-28.8-64-64-64h-128c-35.2 0-64 28.8-64 64v384h64v-192zM128 64h128v128h-128v-128zM960 64v-64h-192c-35.202 0-64 28.8-64 64v320c0 35.2 28.798 64 64 64h192v-64h-192v-320h192zM640 160v-96c0-35.2-28.8-64-64-64h-192v448h192c35.2 0 64-28.8 64-64v-96c0-35.2-8.8-64-44-64 35.2 0 44-28.8 44-64zM576 384h-128v-128h128v128zM576 192h-128v-128h128v128zM832 576l-416 448-224-288 82-70 142 148 352-302z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "spellchecker"
- ],
- "defaultCode": 57380,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 15,
- "order": 552,
- "prevSize": 32,
- "code": 57380,
- "name": "spellchecker",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 46
- },
- {
- "icon": {
- "paths": [
- "M704 896h256l64-128v256h-384v-214.214c131.112-56.484 224-197.162 224-361.786 0-214.432-157.598-382.266-352-382.266-194.406 0-352 167.832-352 382.266 0 164.624 92.886 305.302 224 361.786v214.214h-384v-256l64 128h256v-32.59c-187.63-66.46-320-227.402-320-415.41 0-247.424 229.23-448 512-448 282.77 0 512 200.576 512 448 0 188.008-132.37 348.95-320 415.41v32.59z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "charmap"
- ],
- "defaultCode": 57376,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 19,
- "order": 614,
- "prevSize": 32,
- "code": 57376,
- "name": "charmap",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 47
- },
- {
- "icon": {
- "paths": [
- "M768 206v50h128v64h-192v-146l128-60v-50h-128v-64h192v146zM676 256h-136l-188 188-188-188h-136l256 256-256 256h136l188-188 188 188h136l-256-256z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "sup"
- ],
- "defaultCode": 57375,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 20,
- "order": 615,
- "prevSize": 32,
- "code": 57375,
- "name": "sup",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 48
- },
- {
- "icon": {
- "paths": [
- "M768 910v50h128v64h-192v-146l128-60v-50h-128v-64h192v146zM676 256h-136l-188 188-188-188h-136l256 256-256 256h136l188-188 188 188h136l-256-256z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "sub"
- ],
- "defaultCode": 57374,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 21,
- "order": 616,
- "prevSize": 32,
- "code": 57374,
- "name": "sub",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 49
- },
- {
- "icon": {
- "paths": [
- "M0 896h576v128h-576zM192 0h704v128h-704zM277.388 832l204.688-784.164 123.85 32.328-196.25 751.836zM929.774 1024l-129.774-129.774-129.774 129.774-62.226-62.226 129.774-129.774-129.774-129.774 62.226-62.226 129.774 129.774 129.774-129.774 62.226 62.226-129.774 129.774 129.774 129.774z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "removeformat"
- ],
- "defaultCode": 57373,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 22,
- "order": 617,
- "prevSize": 32,
- "code": 57373,
- "name": "removeformat",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 50
- },
- {
- "icon": {
- "paths": [
- "M0 448h1024v128h-1024z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "hr"
- ],
- "defaultCode": 57372,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 23,
- "order": 618,
- "prevSize": 32,
- "code": 57372,
- "name": "hr",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 51
- },
- {
- "icon": {
- "paths": [
- "M0 64v896h1024v-896h-1024zM384 640v-192h256v192h-256zM640 704v192h-256v-192h256zM640 192v192h-256v-192h256zM320 192v192h-256v-192h256zM64 448h256v192h-256v-192zM704 448h256v192h-256v-192zM704 384v-192h256v192h-256zM64 704h256v192h-256v-192zM704 896v-192h256v192h-256z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "table"
- ],
- "defaultCode": 57371,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 24,
- "order": 619,
- "prevSize": 32,
- "code": 57371,
- "name": "table",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 52
- },
- {
- "icon": {
- "paths": [
- "M322.018 832l57.6-192h264.764l57.6 192h113.632l-191.996-640h-223.236l-192 640h113.636zM475.618 320h72.764l57.6 192h-187.964l57.6-192z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "forecolor"
- ],
- "defaultCode": 57370,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 25,
- "order": 620,
- "prevSize": 32,
- "code": 57370,
- "name": "forecolor",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 53
- },
- {
- "icon": {
- "paths": [
- "M512 320c-209.368 0-395.244 100.556-512 256 116.756 155.446 302.632 256 512 256 209.368 0 395.244-100.554 512-256-116.756-155.444-302.632-256-512-256zM448 448c35.346 0 64 28.654 64 64s-28.654 64-64 64-64-28.654-64-64 28.654-64 64-64zM773.616 705.296c-39.648 20.258-81.652 35.862-124.846 46.376-44.488 10.836-90.502 16.328-136.77 16.328-46.266 0-92.282-5.492-136.768-16.324-43.194-10.518-85.198-26.122-124.846-46.376-63.020-32.202-120.222-76.41-167.64-129.298 47.418-52.888 104.62-97.1 167.64-129.298 32.336-16.522 66.242-29.946 101.082-40.040-19.888 30.242-31.468 66.434-31.468 105.336 0 106.040 85.962 192 192 192 106.038 0 192-85.96 192-192 0-38.902-11.582-75.094-31.466-105.34 34.838 10.096 68.744 23.52 101.082 40.042 63.022 32.198 120.218 76.408 167.638 129.298-47.42 52.886-104.618 97.1-167.638 129.296zM860.918 243.722c-108.72-55.554-226.112-83.722-348.918-83.722-122.806 0-240.198 28.168-348.918 83.722-58.772 30.032-113.732 67.904-163.082 112.076v109.206c55.338-58.566 120.694-
107.754 192.194-144.29 99.62-50.904 207.218-76.714 319.806-76.714s220.186 25.81 319.804 76.716c71.502 36.536 136.858 85.724 192.196 144.29v-109.206c-49.35-44.174-104.308-82.046-163.082-112.078z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "preview"
- ],
- "defaultCode": 57369,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 26,
- "order": 553,
- "prevSize": 32,
- "code": 57369,
- "name": "preview",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 54
- },
- {
- "icon": {
- "paths": [
- "M512 192c-212.076 0-384 171.922-384 384s171.922 384 384 384c212.074 0 384-171.922 384-384s-171.926-384-384-384zM715.644 779.646c-54.392 54.396-126.716 84.354-203.644 84.354s-149.25-29.958-203.646-84.354c-54.396-54.394-84.354-126.718-84.354-203.646s29.958-149.25 84.354-203.646c54.396-54.396 126.718-84.354 203.646-84.354s149.252 29.958 203.642 84.354c54.402 54.396 84.358 126.718 84.358 203.646s-29.958 149.252-84.356 203.646zM325.93 203.862l-42.94-85.878c-98.874 49.536-179.47 130.132-229.006 229.008l85.876 42.94c40.248-80.336 105.732-145.822 186.070-186.070zM884.134 389.93l85.878-42.938c-49.532-98.876-130.126-179.472-229.004-229.008l-42.944 85.878c80.338 40.248 145.824 105.732 186.070 186.068zM512 384h-64v192c0 10.11 4.7 19.11 12.022 24.972l-0.012 0.016 160 128 39.976-49.976-147.986-118.39v-176.622z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "inserttime"
- ],
- "defaultCode": 57368,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 27,
- "order": 554,
- "prevSize": 32,
- "code": 57368,
- "name": "inserttime",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 55
- },
- {
- "icon": {
- "paths": [
- "M320 256l-256 256 256 256h128l-256-256 256-256zM704 256h-128l256 256-256 256h128l256-256z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "code"
- ],
- "defaultCode": 57367,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 28,
- "order": 555,
- "prevSize": 32,
- "code": 57367,
- "name": "code",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 56
- },
- {
- "icon": {
- "paths": [
- "M448 704h128v128h-128zM704 256c35.346 0 64 28.654 64 64v192l-192 128h-128v-64l192-128v-64h-320v-128h384zM512 96c-111.118 0-215.584 43.272-294.156 121.844s-121.844 183.038-121.844 294.156c0 111.118 43.272 215.584 121.844 294.156 78.572 78.572 183.038 121.844 294.156 121.844 111.118 0 215.584-43.272 294.156-121.844 78.572-78.572 121.844-183.038 121.844-294.156 0-111.118-43.272-215.584-121.844-294.156-78.572-78.572-183.038-121.844-294.156-121.844zM512 0v0c282.77 0 512 229.23 512 512s-229.23 512-512 512c-282.77 0-512-229.23-512-512 0-282.77 229.23-512 512-512z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "help"
- ],
- "defaultCode": 57366,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 29,
- "order": 556,
- "prevSize": 32,
- "code": 57366,
- "name": "help",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 57
- },
- {
- "icon": {
- "paths": [
- "M0 128v768h1024v-768h-1024zM192 832h-128v-128h128v128zM192 576h-128v-128h128v128zM192 320h-128v-128h128v128zM768 832h-512v-640h512v640zM960 832h-128v-128h128v128zM960 576h-128v-128h128v128zM960 320h-128v-128h128v128zM384 320v384l256-192z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "media"
- ],
- "defaultCode": 57365,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 30,
- "order": 557,
- "prevSize": 32,
- "code": 57365,
- "name": "media",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 58
- },
- {
- "icon": {
- "paths": [
- "M0 128v832h1024v-832h-1024zM960 896h-896v-704h896v704zM704 352c0-53.019 42.981-96 96-96s96 42.981 96 96c0 53.019-42.981 96-96 96-53.019 0-96-42.981-96-96zM896 832h-768l192-512 256 320 128-96z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "image"
- ],
- "defaultCode": 57364,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 31,
- "order": 558,
- "prevSize": 32,
- "code": 57364,
- "name": "image",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 59
- },
- {
- "icon": {
- "paths": [
- "M192 0v1024l320-320 320 320v-1024h-640zM768 869.49l-256-256-256 256v-805.49h512v805.49z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "anchor"
- ],
- "defaultCode": 57363,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 32,
- "order": 559,
- "prevSize": 32,
- "code": 57363,
- "name": "anchor",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 60
- },
- {
- "icon": {
- "paths": [
- "M476.888 675.114c4.56 9.048 6.99 19.158 6.99 29.696 0 17.616-6.744 34.058-18.992 46.308l-163.38 163.38c-12.248 12.248-28.696 18.992-46.308 18.992s-34.060-6.744-46.308-18.992l-99.38-99.38c-12.248-12.25-18.992-28.696-18.992-46.308s6.744-34.060 18.992-46.308l163.38-163.382c12.248-12.246 28.696-18.992 46.308-18.992 10.538 0 20.644 2.43 29.696 6.988l65.338-65.336c-27.87-21.41-61.44-32.16-95.034-32.16-39.986 0-79.972 15.166-110.308 45.502l-163.38 163.382c-60.67 60.67-60.67 159.95 0 220.618l99.38 99.382c30.334 30.332 70.32 45.5 110.306 45.5 39.988 0 79.974-15.168 110.308-45.502l163.38-163.38c55.82-55.82 60.238-144.298 13.344-205.346l-65.34 65.338zM978.496 144.884l-99.38-99.382c-30.334-30.336-70.32-45.502-110.308-45.502-39.986 0-79.97 15.166-110.306 45.502l-163.382 163.382c-55.82 55.82-60.238 144.298-13.342 205.342l65.338-65.34c-4.558-9.050-6.988-19.16-6.988-29.694 0-17.616 6.744-34.060 18.992-46.308l163.382-163.382c12.246-12.248 28.694-18.994 46.306-18.994 17.616 0 34.060 6.746
46.308 18.994l99.38 99.382c12.248 12.248 18.992 28.694 18.992 46.308s-6.744 34.060-18.992 46.308l-163.38 163.382c-12.248 12.248-28.694 18.992-46.308 18.992-10.536 0-20.644-2.43-29.696-6.99l-65.338 65.338c27.872 21.41 61.44 32.16 95.034 32.16 39.988 0 79.974-15.168 110.308-45.504l163.38-163.38c60.672-60.666 60.672-159.944 0-220.614zM233.368 278.624l-191.994-191.994 45.256-45.256 191.994 191.994zM384 0h64v192h-64zM0 384h192v64h-192zM790.632 745.376l191.996 191.996-45.256 45.256-191.996-191.996zM576 832h64v192h-64zM832 576h192v64h-192z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "unlink"
- ],
- "defaultCode": 57362,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 33,
- "order": 560,
- "prevSize": 32,
- "code": 57362,
- "name": "unlink",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 61
- },
- {
- "icon": {
- "paths": [
- "M320 704c17.6 17.6 47.274 16.726 65.942-1.942l316.118-316.116c18.668-18.668 19.54-48.342 1.94-65.942s-47.274-16.726-65.942 1.942l-316.116 316.116c-18.668 18.668-19.542 48.342-1.942 65.942zM476.888 675.112c4.56 9.050 6.99 19.16 6.99 29.696 0 17.616-6.744 34.060-18.992 46.308l-163.382 163.382c-12.248 12.248-28.694 18.992-46.308 18.992s-34.060-6.744-46.308-18.992l-99.382-99.382c-12.248-12.248-18.992-28.694-18.992-46.308s6.744-34.060 18.992-46.308l163.382-163.382c12.248-12.248 28.694-18.994 46.308-18.994 10.536 0 20.644 2.43 29.696 6.99l65.338-65.338c-27.87-21.41-61.44-32.16-95.034-32.16-39.986 0-79.972 15.166-110.308 45.502l-163.382 163.382c-60.67 60.67-60.67 159.948 0 220.618l99.382 99.382c30.334 30.332 70.32 45.5 110.306 45.5 39.988 0 79.974-15.168 110.308-45.502l163.382-163.382c55.82-55.82 60.238-144.298 13.344-205.344l-65.34 65.34zM978.498 144.884l-99.382-99.382c-30.334-30.336-70.32-45.502-110.308-45.502-39.986 0-79.972 15.166-110.308 45.502l-163.382 163.382c-55.82 55.82
-60.238 144.298-13.342 205.342l65.338-65.34c-4.558-9.050-6.988-19.16-6.988-29.694 0-17.616 6.744-34.060 18.992-46.308l163.382-163.382c12.248-12.248 28.694-18.994 46.308-18.994s34.060 6.746 46.308 18.994l99.382 99.382c12.248 12.248 18.992 28.694 18.992 46.308s-6.744 34.060-18.992 46.308l-163.382 163.382c-12.248 12.248-28.694 18.992-46.308 18.992-10.536 0-20.644-2.43-29.696-6.99l-65.338 65.338c27.872 21.41 61.44 32.16 95.034 32.16 39.988 0 79.974-15.168 110.308-45.502l163.382-163.382c60.67-60.666 60.67-159.944 0-220.614z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "link"
- ],
- "defaultCode": 57361,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 34,
- "order": 561,
- "prevSize": 32,
- "code": 57361,
- "name": "link",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 62
- },
- {
- "icon": {
- "paths": [
- "M0 64h1024v128h-1024zM384 256h640v128h-640zM384 448h640v128h-640zM384 640h640v128h-640zM0 832h1024v128h-1024zM256 320v384l-256-192z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "outdent"
- ],
- "defaultCode": 57357,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 38,
- "order": 562,
- "prevSize": 32,
- "code": 57357,
- "name": "outdent",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 63
- },
- {
- "icon": {
- "paths": [
- "M0 64h1024v128h-1024zM384 256h640v128h-640zM384 448h640v128h-640zM384 640h640v128h-640zM0 832h1024v128h-1024zM0 704v-384l256 192z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "indent"
- ],
- "defaultCode": 57356,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 39,
- "order": 563,
- "prevSize": 32,
- "code": 57356,
- "name": "indent",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 64
- },
- {
- "icon": {
- "paths": [
- "M384 832h640v128h-640zM384 448h640v128h-640zM384 64h640v128h-640zM192 0v256h-64v-192h-64v-64zM128 526v50h128v64h-192v-146l128-60v-50h-128v-64h192v146zM256 704v320h-192v-64h128v-64h-128v-64h128v-64h-128v-64z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "numlist"
- ],
- "defaultCode": 57355,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 40,
- "order": 621,
- "prevSize": 32,
- "code": 57355,
- "name": "numlist",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 65
- },
- {
- "icon": {
- "paths": [
- "M384 64h640v128h-640v-128zM384 448h640v128h-640v-128zM384 832h640v128h-640v-128zM0 128c0-70.692 57.308-128 128-128 70.692 0 128 57.308 128 128 0 70.692-57.308 128-128 128-70.692 0-128-57.308-128-128zM0 512c0-70.692 57.308-128 128-128 70.692 0 128 57.308 128 128 0 70.692-57.308 128-128 128-70.692 0-128-57.308-128-128zM0 896c0-70.692 57.308-128 128-128 70.692 0 128 57.308 128 128 0 70.692-57.308 128-128 128-70.692 0-128-57.308-128-128z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "bullist"
- ],
- "defaultCode": 57354,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 41,
- "order": 622,
- "prevSize": 32,
- "code": 57354,
- "name": "bullist",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 66
- },
- {
- "icon": {
- "paths": [
- "M64 0h384v64h-384zM576 0h384v64h-384zM952 320h-56v-256h-256v256h-256v-256h-256v256h-56c-39.6 0-72 32.4-72 72v560c0 39.6 32.4 72 72 72h304c39.6 0 72-32.4 72-72v-376h128v376c0 39.6 32.4 72 72 72h304c39.6 0 72-32.4 72-72v-560c0-39.6-32.4-72-72-72zM348 960h-248c-19.8 0-36-14.4-36-32s16.2-32 36-32h248c19.8 0 36 14.4 36 32s-16.2 32-36 32zM544 512h-64c-17.6 0-32-14.4-32-32s14.4-32 32-32h64c17.6 0 32 14.4 32 32s-14.4 32-32 32zM924 960h-248c-19.8 0-36-14.4-36-32s16.2-32 36-32h248c19.8 0 36 14.4 36 32s-16.2 32-36 32z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "searchreplace"
- ],
- "defaultCode": 57353,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 42,
- "order": 623,
- "prevSize": 32,
- "code": 57353,
- "name": "searchreplace",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 67
- },
- {
- "icon": {
- "paths": [
- "M832 320v-160c0-17.6-14.4-32-32-32h-224v-64c0-35.2-28.8-64-64-64h-128c-35.204 0-64 28.8-64 64v64h-224c-17.602 0-32 14.4-32 32v640c0 17.6 14.398 32 32 32h288v192h448l192-192v-512h-192zM384 64.114c0.034-0.038 0.072-0.078 0.114-0.114h127.768c0.042 0.036 0.082 0.076 0.118 0.114l0 63.886h-128v-63.886zM192 256v-64h512v64h-512zM832 933.49v-101.49h101.49l-101.49 101.49zM960 768h-192v192h-320v-576h512v384z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "paste"
- ],
- "defaultCode": 57352,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 43,
- "order": 624,
- "prevSize": 32,
- "code": 57352,
- "name": "paste",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 68
- },
- {
- "icon": {
- "paths": [
- "M890.774 709.154c-45.654-45.556-103.728-69.072-157.946-69.072h-29.112l-63.904-64.008 255.62-256.038c63.904-64.010 63.904-192.028 0-256.038l-383.43 384.056-383.432-384.054c-63.904 64.008-63.904 192.028 0 256.038l255.622 256.034-63.906 64.008h-29.114c-54.22 0-112.292 23.518-157.948 69.076-81.622 81.442-92.65 202.484-24.63 270.35 29.97 29.902 70.288 44.494 112.996 44.494 54.216 0 112.29-23.514 157.946-69.072 53.584-53.464 76.742-124 67.084-185.348l65.384-65.488 65.376 65.488c-9.656 61.348 13.506 131.882 67.084 185.348 45.662 45.558 103.732 69.072 157.948 69.072 42.708 0 83.024-14.592 112.994-44.496 68.020-67.866 56.988-188.908-24.632-270.35zM353.024 845.538c-7.698 17.882-19.010 34.346-33.626 48.926-14.636 14.604-31.172 25.918-49.148 33.624-16.132 6.916-32.96 10.568-48.662 10.568-15.146 0-36.612-3.402-52.862-19.612-16.136-16.104-19.52-37.318-19.52-52.288 0-15.542 3.642-32.21 10.526-48.212 7.7-17.884 19.014-34.346 33.626-48.926 14.634-14.606 31.172-25.914 49.15-33.624 16.134-6
.914 32.96-10.568 48.664-10.568 15.146 0 36.612 3.4 52.858 19.614 16.134 16.098 19.522 37.316 19.522 52.284 0.002 15.542-3.638 32.216-10.528 48.214zM512.004 666.596c-49.914 0-90.376-40.532-90.376-90.526 0-49.992 40.462-90.52 90.376-90.52s90.372 40.528 90.372 90.52c0 49.998-40.46 90.526-90.372 90.526zM855.272 919.042c-16.248 16.208-37.712 19.612-52.86 19.612-15.704 0-32.53-3.652-48.666-10.568-17.972-7.706-34.508-19.020-49.142-33.624-14.614-14.58-25.926-31.042-33.626-48.926-6.886-15.998-10.526-32.672-10.526-48.212 0-14.966 3.384-36.188 19.52-52.286 16.246-16.208 37.712-19.614 52.86-19.614 15.7 0 32.53 3.654 48.66 10.568 17.978 7.708 34.516 19.018 49.15 33.624 14.61 14.58 25.924 31.042 33.626 48.926 6.884 15.998 10.526 32.67 10.526 48.212-0.002 14.97-3.39 36.186-19.522 52.288z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "cut"
- ],
- "defaultCode": 57351,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 44,
- "order": 625,
- "prevSize": 32,
- "code": 57351,
- "name": "cut",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 69
- },
- {
- "icon": {
- "paths": [
- "M0 64h1024v128h-1024zM0 256h1024v128h-1024zM0 448h1024v128h-1024zM0 640h1024v128h-1024zM0 832h1024v128h-1024z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "alignjustify"
- ],
- "defaultCode": 57350,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 45,
- "order": 626,
- "prevSize": 32,
- "code": 57350,
- "name": "alignjustify",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 70
- },
- {
- "icon": {
- "paths": [
- "M0 64h1024v128h-1024zM384 256h640v128h-640zM384 640h640v128h-640zM0 448h1024v128h-1024zM0 832h1024v128h-1024z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "alignright"
- ],
- "defaultCode": 57349,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 46,
- "order": 627,
- "prevSize": 32,
- "code": 57349,
- "name": "alignright",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 71
- },
- {
- "icon": {
- "paths": [
- "M0 64h1024v128h-1024zM192 256h640v128h-640zM192 640h640v128h-640zM0 448h1024v128h-1024zM0 832h1024v128h-1024z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "aligncenter"
- ],
- "defaultCode": 57348,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 47,
- "order": 564,
- "prevSize": 32,
- "code": 57348,
- "name": "aligncenter",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 72
- },
- {
- "icon": {
- "paths": [
- "M0 64h1024v128h-1024zM0 256h640v128h-640zM0 640h640v128h-640zM0 448h1024v128h-1024zM0 832h1024v128h-1024z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "alignleft"
- ],
- "defaultCode": 57347,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 48,
- "order": 565,
- "prevSize": 32,
- "code": 57347,
- "name": "alignleft",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 73
- },
- {
- "icon": {
- "paths": [
- "M1024 592.458v-160.916l-159.144-15.914c-8.186-30.042-20.088-58.548-35.21-84.98l104.596-127.838-113.052-113.050-127.836 104.596c-26.434-15.124-54.942-27.026-84.982-35.208l-15.914-159.148h-160.916l-15.914 159.146c-30.042 8.186-58.548 20.086-84.98 35.208l-127.838-104.594-113.050 113.050 104.596 127.836c-15.124 26.432-27.026 54.94-35.21 84.98l-159.146 15.916v160.916l159.146 15.914c8.186 30.042 20.086 58.548 35.21 84.982l-104.596 127.836 113.048 113.048 127.838-104.596c26.432 15.124 54.94 27.028 84.98 35.21l15.916 159.148h160.916l15.914-159.144c30.042-8.186 58.548-20.088 84.982-35.21l127.836 104.596 113.048-113.048-104.596-127.836c15.124-26.434 27.028-54.942 35.21-84.98l159.148-15.92zM704 576l-128 128h-128l-128-128v-128l128-128h128l128 128v128z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "fullpage"
- ],
- "defaultCode": 57346,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 49,
- "order": 566,
- "prevSize": 32,
- "code": 57346,
- "name": "fullpage",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 74
- },
- {
- "icon": {
- "paths": [
- "M903.432 199.43l-142.864-142.862c-31.112-31.112-92.568-56.568-136.568-56.568h-480c-44 0-80 36-80 80v864c0 44 36 80 80 80h736c44 0 80-36 80-80v-608c0-44-25.456-105.458-56.568-136.57zM858.178 244.686c3.13 3.13 6.25 6.974 9.28 11.314h-163.458v-163.456c4.34 3.030 8.184 6.15 11.314 9.28l142.864 142.862zM896 944c0 8.672-7.328 16-16 16h-736c-8.672 0-16-7.328-16-16v-864c0-8.672 7.328-16 16-16h480c4.832 0 10.254 0.61 16 1.704v254.296h254.296c1.094 5.746 1.704 11.166 1.704 16v608z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "newdocument"
- ],
- "defaultCode": 57345,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 50,
- "order": 567,
- "prevSize": 32,
- "code": 57345,
- "name": "newdocument",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 75
- },
- {
- "icon": {
- "paths": [
- "M896 0h-896v1024h1024v-896l-128-128zM512 128h128v256h-128v-256zM896 896h-768v-768h64v320h576v-320h74.978l53.022 53.018v714.982z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "save"
- ],
- "defaultCode": 57344,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 51,
- "order": 568,
- "prevSize": 32,
- "code": 57344,
- "name": "save",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 76
- },
- {
- "icon": {
- "paths": [
- "M128 544l288 288 480-480-128-128-352 352-160-160z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "defaultCode": 57395,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 52,
- "order": 569,
- "prevSize": 32,
- "code": 57395,
- "name": "checkbox",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 77
- },
- {
- "icon": {
- "paths": [
- "M512 512v128h32l32-64h64v256h-48v64h224v-64h-48v-256h64l32 64h32v-128zM832 320v-160c0-17.6-14.4-32-32-32h-224v-64c0-35.2-28.8-64-64-64h-128c-35.204 0-64 28.8-64 64v64h-224c-17.602 0-32 14.4-32 32v640c0 17.6 14.398 32 32 32h288v192h640v-704h-192zM384 64.114c0.034-0.038 0.072-0.078 0.114-0.114h127.768c0.042 0.036 0.082 0.076 0.118 0.114l0 63.886h-128v-63.886zM192 256v-64h512v64h-512zM960 960h-512v-576h512v576z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "pastetext"
- ],
- "defaultCode": 57397,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 53,
- "order": 570,
- "prevSize": 32,
- "code": 57397,
- "name": "pastetext",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 78
- },
- {
- "icon": {
- "paths": [
- "M1024 0v384l-138.26-138.26-212 212-107.48-107.48 212-212-138.26-138.26zM245.74 138.26l212 212-107.48 107.48-212-212-138.26 138.26v-384h384zM885.74 778.26l138.26-138.26v384h-384l138.26-138.26-212-212 107.48-107.48zM457.74 673.74l-212 212 138.26 138.26h-384v-384l138.26 138.26 212-212z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "fullscreen"
- ],
- "defaultCode": 57379,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 16,
- "order": 571,
- "prevSize": 32,
- "code": 57379,
- "name": "fullscreen",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 79
- },
- {
- "icon": {
- "paths": [
- "M256 64h512v128h-512zM960 256h-896c-35.2 0-64 28.8-64 64v320c0 35.2 28.796 64 64 64h192v256h512v-256h192c35.2 0 64-28.8 64-64v-320c0-35.2-28.8-64-64-64zM704 896h-384v-320h384v320zM974.4 352c0 25.626-20.774 46.4-46.398 46.4-25.626 0-46.402-20.774-46.402-46.4s20.776-46.4 46.402-46.4c25.626 0 46.398 20.774 46.398 46.4z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "print"
- ],
- "defaultCode": 57378,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 17,
- "order": 572,
- "prevSize": 32,
- "code": 57378,
- "name": "print",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 80
- },
- {
- "icon": {
- "paths": [
- "M512 0c-282.77 0-512 229.228-512 512 0 282.77 229.228 512 512 512 282.77 0 512-229.23 512-512 0-282.772-229.23-512-512-512zM512 944c-238.586 0-432-193.412-432-432 0-238.586 193.414-432 432-432 238.59 0 432 193.414 432 432 0 238.588-193.41 432-432 432zM384 320c0 35.346-28.654 64-64 64s-64-28.654-64-64 28.654-64 64-64 64 28.654 64 64zM768 320c0 35.346-28.652 64-64 64s-64-28.654-64-64 28.652-64 64-64 64 28.654 64 64zM512 652c141.074 0 262.688-57.532 318.462-123.192-20.872 171.22-156.288 303.192-318.462 303.192-162.118 0-297.498-132.026-318.444-303.168 55.786 65.646 177.386 123.168 318.444 123.168z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "emoticons"
- ],
- "defaultCode": 57377,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 18,
- "order": 573,
- "prevSize": 32,
- "code": 57377,
- "name": "emoticons",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 81
- },
- {
- "icon": {
- "paths": [
- "M225 448c123.712 0 224 100.29 224 224 0 123.712-100.288 224-224 224-123.712 0-224-100.288-224-224l-1-32c0-247.424 200.576-448 448-448v128c-85.474 0-165.834 33.286-226.274 93.726-11.634 11.636-22.252 24.016-31.83 37.020 11.438-1.8 23.16-2.746 35.104-2.746zM801 448c123.71 0 224 100.29 224 224 0 123.712-100.29 224-224 224-123.71 0-224-100.288-224-224l-1-32c0-247.424 200.576-448 448-448v128c-85.474 0-165.834 33.286-226.274 93.726-11.636 11.636-22.254 24.016-31.832 37.020 11.44-1.8 23.16-2.746 35.106-2.746z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "blockquote"
- ],
- "defaultCode": 57358,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 37,
- "order": 574,
- "prevSize": 32,
- "code": 57358,
- "name": "blockquote",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 82
- },
- {
- "icon": {
- "paths": [
- "M761.862 1024c113.726-206.032 132.888-520.306-313.862-509.824v253.824l-384-384 384-384v248.372c534.962-13.942 594.57 472.214 313.862 775.628z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "undo"
- ],
- "defaultCode": 57359,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 36,
- "order": 628,
- "prevSize": 32,
- "code": 57359,
- "name": "undo",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 83
- },
- {
- "icon": {
- "paths": [
- "M576 248.372v-248.372l384 384-384 384v-253.824c-446.75-10.482-427.588 303.792-313.86 509.824-280.712-303.414-221.1-789.57 313.86-775.628z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "redo"
- ],
- "defaultCode": 57360,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 35,
- "order": 629,
- "prevSize": 32,
- "code": 57360,
- "name": "redo",
- "ligatures": ""
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 84
- },
- {
- "icon": {
- "paths": [
- "M199.995 381.998v-104.002c0-43.078 34.923-78.001 78.001-78.001h26v-104.002h-26c-100.518 0-182.003 81.485-182.003 182.003v104.002c0 43.078-34.923 78.001-78.001 78.001h-26v104.002h26c43.078 0 78.001 34.923 78.001 78.001v104.002c0 100.515 81.485 182.003 182.003 182.003h26v-104.002h-26c-43.078 0-78.001-34.923-78.001-78.001v-104.002c0-50.931-20.928-96.966-54.646-130.002 33.716-33.036 54.646-79.072 54.646-130.002z",
- "M824.005 381.998v-104.002c0-43.078-34.923-78.001-78.001-78.001h-26v-104.002h26c100.515 0 182.003 81.485 182.003 182.003v104.002c0 43.078 34.923 78.001 78.001 78.001h26v104.002h-26c-43.078 0-78.001 34.923-78.001 78.001v104.002c0 100.515-81.488 182.003-182.003 182.003h-26v-104.002h26c43.078 0 78.001-34.923 78.001-78.001v-104.002c0-50.931 20.928-96.966 54.646-130.002-33.716-33.036-54.646-79.072-54.646-130.002z",
- "M616.002 356.715c0 57.439-46.562 104.002-104.002 104.002s-104.002-46.562-104.002-104.002c0-57.439 46.562-104.002 104.002-104.002s104.002 46.562 104.002 104.002z",
- "M512 511.283c-57.439 0-104.002 46.562-104.002 104.002 0 55.845 26 100.115 105.752 103.88-23.719 33.417-59.441 46.612-105.752 50.944v61.751c0 0 208.003 18.144 208.003-216.577-0.202-57.441-46.56-104.004-104.002-104.004z"
- ],
- "width": 1024,
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "code",
- "semicolon",
- "curly-braces"
- ],
- "grid": 16,
- "defaultCode": 58883
- },
- "attrs": [],
- "properties": {
- "order": 630,
- "id": 1,
- "prevSize": 32,
- "code": 58883,
- "name": "codesample"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 85
- },
- {
- "icon": {
- "paths": [
- "M864.626 473.162c-65.754-183.44-205.11-348.15-352.626-473.162-147.516 125.012-286.87 289.722-352.626 473.162-40.664 113.436-44.682 236.562 12.584 345.4 65.846 125.14 198.632 205.438 340.042 205.438s274.196-80.298 340.040-205.44c57.27-108.838 53.25-231.962 12.586-345.398zM738.764 758.956c-43.802 83.252-132.812 137.044-226.764 137.044-55.12 0-108.524-18.536-152.112-50.652 13.242 1.724 26.632 2.652 40.112 2.652 117.426 0 228.668-67.214 283.402-171.242 44.878-85.292 40.978-173.848 23.882-244.338 14.558 28.15 26.906 56.198 36.848 83.932 22.606 63.062 40.024 156.34-5.368 242.604z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "drop"
- ],
- "defaultCode": 57381,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 87,
- "order": 631,
- "prevSize": 32,
- "code": 59701,
- "ligatures": "droplet, color9",
- "name": "drop"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 86
- },
- {
- "icon": {
- "paths": [
- "M768 128h-512l-256 256 512 576 512-576-256-256zM512 778.666v-2.666h-2.37l-14.222-16h16.592v-16h-30.814l-14.222-16h45.036v-16h-59.258l-14.222-16h73.48v-16h-87.704l-14.222-16h101.926v-16h-116.148l-14.222-16h130.37v-16h-144.592l-14.222-16h158.814v-16h-173.038l-14.222-16h187.26v-16h-201.482l-14.222-16h215.704v-16h-229.926l-14.222-16h244.148v-16h-258.372l-14.222-16h272.594v-16h-286.816l-14.222-16h301.038v-16h-315.26l-14.222-16h329.482v-16h-343.706l-7.344-8.262 139.072-139.072h211.978v3.334h215.314l16 16h-231.314v16h247.314l16 16h-263.314v16h279.314l16 16h-295.314v16h311.314l16 16h-327.314v16h343.312l7.738 7.738-351.050 394.928z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "diamond",
- "gem",
- "jewelry",
- "dualtone"
- ],
- "defaultCode": 57889,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 635,
- "order": 632,
- "prevSize": 32,
- "code": 60327,
- "ligatures": "diamond2, gem2",
- "name": "sharpen"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 87
- },
- {
- "icon": {
- "paths": [
- "M512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512 512-229.23 512-512-229.23-512-512-512zM128 512c0-212.078 171.922-384 384-384v768c-212.078 0-384-171.922-384-384z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "contrast"
- ],
- "defaultCode": 58104,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 854,
- "order": 633,
- "prevSize": 32,
- "code": 60628,
- "ligatures": "contrast",
- "name": "contrast"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 88
- },
- {
- "icon": {
- "paths": [
- "M893.254 221.254l-90.508-90.508-290.746 290.744-290.746-290.744-90.508 90.506 290.746 290.748-290.746 290.746 90.508 90.508 290.746-290.746 290.746 290.746 90.508-90.51-290.744-290.744z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "remove"
- ],
- "defaultCode": 60778,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 24,
- "order": 634,
- "prevSize": 32,
- "code": 60778,
- "ligatures": "cross2, cancel3",
- "name": "remove22"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 89
- },
- {
- "icon": {
- "paths": [
- "M0 64v384c0 35.346 28.654 64 64 64s64-28.654 64-64v-229.488l677.488 677.488h-229.488c-35.346 0-64 28.652-64 64 0 35.346 28.654 64 64 64h384c35.346 0 64-28.654 64-64v-384c0-35.348-28.654-64-64-64s-64 28.652-64 64v229.488l-677.488-677.488h229.488c35.346 0 64-28.654 64-64s-28.652-64-64-64h-384c-35.346 0-64 28.654-64 64z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "resize2"
- ],
- "defaultCode": 58329,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 1097,
- "order": 575,
- "prevSize": 32,
- "code": 60921,
- "ligatures": "arrow-resize2, diagonal2",
- "name": "resize2"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 90
- },
- {
- "icon": {
- "paths": [
- "M483.2 640l-147.2-336c-9.6-25.6-19.2-44.8-25.6-54.4s-16-12.8-25.6-12.8c-16 0-25.6 3.2-28.8 3.2v-70.4c9.6-6.4 25.6-6.4 38.4-9.6 32 0 57.6 6.4 73.6 22.4 6.4 6.4 12.8 16 19.2 25.6 6.4 12.8 12.8 25.6 16 41.6l121.6 291.2 150.4-371.2h92.8l-198.4 470.4v224h-86.4v-224z",
- "M0 0v1024h1024v-1024h-1024zM960 960h-896v-896h896v896z"
- ],
- "attrs": [
- {},
- {}
- ],
- "isMulticolor": false,
- "tags": [
- "gamma2"
- ],
- "grid": 16,
- "defaultCode": 58880
- },
- "attrs": [
- {},
- {}
- ],
- "properties": {
- "order": 576,
- "id": 1,
- "prevSize": 32,
- "code": 58880,
- "name": "gamma"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 91
- },
- {
- "icon": {
- "paths": [
- "M627.2 880h-579.2v-396.8h579.2v396.8zM553.6 553.6h-435.2v256h435.2v-256z",
- "M259.2 227.2c176-176 457.6-176 633.6 0s176 457.6 0 633.6c-121.6 121.6-297.6 160-454.4 108.8 121.6 28.8 262.4-9.6 361.6-108.8 150.4-150.4 160-384 22.4-521.6-121.6-121.6-320-128-470.4-19.2l86.4 86.4-294.4 22.4 22.4-294.4 92.8 92.8z"
- ],
- "attrs": [
- {},
- {}
- ],
- "isMulticolor": false,
- "tags": [
- "orientation"
- ],
- "grid": 16,
- "defaultCode": 58881
- },
- "attrs": [
- {},
- {}
- ],
- "properties": {
- "order": 577,
- "id": 0,
- "prevSize": 32,
- "code": 58881,
- "name": "orientation"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 92
- },
- {
- "icon": {
- "paths": [
- "M768 544v352h-640v-640h352l128-128h-512c-52.8 0-96 43.2-96 96v704c0 52.8 43.2 96 96 96h704c52.798 0 96-43.2 96-96v-512l-128 128z",
- "M864 0l-608 608v160h160l608-608c0-96-64-160-160-160zM416 640l-48-48 480-480 48 48-480 480z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "pencil",
- "write",
- "edit"
- ],
- "defaultCode": 57361,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 68,
- "order": 578,
- "prevSize": 32,
- "code": 59669,
- "ligatures": "pencil7, write7",
- "name": "editimage"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 93
- },
- {
- "icon": {
- "paths": [
- "M607.998 128.014c-212.070 0-383.986 171.916-383.986 383.986h-191.994l246.848 246.848 246.848-246.848h-191.994c0-151.478 122.798-274.276 274.276-274.276 151.48 0 274.276 122.798 274.276 274.276 0 151.48-122.796 274.276-274.276 274.276v109.71c212.070 0 383.986-171.916 383.986-383.986s-171.916-383.986-383.986-383.986z"
- ],
- "width": 1024,
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "rotate-ccw",
- "ccw",
- "arrow"
- ],
- "defaultCode": 60072,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 22,
- "order": 579,
- "prevSize": 32,
- "code": 60072,
- "ligatures": "rotate-ccw3, ccw4",
- "name": "rotateleft"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 94
- },
- {
- "icon": {
- "paths": [
- "M416.002 128.014c212.070 0 383.986 171.916 383.986 383.986h191.994l-246.848 246.848-246.848-246.848h191.994c0-151.478-122.798-274.276-274.276-274.276-151.48 0-274.276 122.798-274.276 274.276 0 151.48 122.796 274.276 274.276 274.276v109.71c-212.070 0-383.986-171.916-383.986-383.986s171.916-383.986 383.986-383.986z"
- ],
- "width": 1024,
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "rotate-cw",
- "cw",
- "arrow"
- ],
- "defaultCode": 60073,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 580,
- "id": 1679,
- "prevSize": 32,
- "code": 60073,
- "ligatures": "rotate-cw3, cw4",
- "name": "rotateright"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 95
- },
- {
- "icon": {
- "paths": [
- "M0 384h1024v-384zM1024 960v-384h-1024z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "flip-vertical",
- "mirror"
- ],
- "defaultCode": 57663,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 403,
- "order": 581,
- "prevSize": 32,
- "code": 60074,
- "ligatures": "flip-vertical, mirror",
- "name": "flipv"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 96
- },
- {
- "icon": {
- "paths": [
- "M576 0v1024h384zM0 1024h384v-1024z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "flip-horizontal",
- "mirror"
- ],
- "defaultCode": 57664,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 405,
- "order": 582,
- "prevSize": 32,
- "code": 60076,
- "ligatures": "flip-horizontal, mirror3",
- "name": "fliph"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 97
- },
- {
- "icon": {
- "paths": [
- "M992.262 871.396l-242.552-206.294c-25.074-22.566-51.89-32.926-73.552-31.926 57.256-67.068 91.842-154.078 91.842-249.176 0-212.078-171.922-384-384-384-212.076 0-384 171.922-384 384 0 212.078 171.922 384 384 384 95.098 0 182.108-34.586 249.176-91.844-1 21.662 9.36 48.478 31.926 73.552l206.294 242.552c35.322 39.246 93.022 42.554 128.22 7.356s31.892-92.898-7.354-128.22zM384 640c-141.384 0-256-114.616-256-256s114.616-256 256-256 256 114.616 256 256-114.614 256-256 256zM448 192h-128v128h-128v128h128v128h128v-128h128v-128h-128z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "zoom-in",
- "magnifier",
- "magnifier-plus",
- "enlarge"
- ],
- "defaultCode": 57788,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 534,
- "order": 583,
- "prevSize": 32,
- "code": 60213,
- "ligatures": "zoom-in3, magnifier9",
- "name": "zoomin"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 98
- },
- {
- "icon": {
- "paths": [
- "M992.262 871.396l-242.552-206.294c-25.074-22.566-51.89-32.926-73.552-31.926 57.256-67.068 91.842-154.078 91.842-249.176 0-212.078-171.922-384-384-384-212.076 0-384 171.922-384 384 0 212.078 171.922 384 384 384 95.098 0 182.108-34.586 249.176-91.844-1 21.662 9.36 48.478 31.926 73.552l206.294 242.552c35.322 39.246 93.022 42.554 128.22 7.356s31.892-92.898-7.354-128.22zM384 640c-141.384 0-256-114.616-256-256s114.616-256 256-256 256 114.616 256 256-114.614 256-256 256zM192 320h384v128h-384z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "zoom-out",
- "magnifier",
- "magnifier-minus",
- "reduce"
- ],
- "defaultCode": 57789,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 535,
- "order": 584,
- "prevSize": 32,
- "code": 60214,
- "ligatures": "zoom-out3, magnifier10",
- "name": "zoomout"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 99
- },
- {
- "icon": {
- "paths": [
- "M64 192h896v192h-896zM64 448h896v192h-896zM64 704h896v192h-896z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "menu",
- "list",
- "options",
- "lines",
- "hamburger"
- ],
- "defaultCode": 58031,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "order": 585,
- "id": 1448,
- "prevSize": 32,
- "code": 60522,
- "ligatures": "menu3, list4",
- "name": "options"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 100
- },
- {
- "icon": {
- "paths": [
- "M512 832c35.346 0 64 28.654 64 64v64c0 35.346-28.654 64-64 64s-64-28.654-64-64v-64c0-35.346 28.654-64 64-64zM512 192c-35.346 0-64-28.654-64-64v-64c0-35.346 28.654-64 64-64s64 28.654 64 64v64c0 35.346-28.654 64-64 64zM960 448c35.346 0 64 28.654 64 64s-28.654 64-64 64h-64c-35.348 0-64-28.654-64-64s28.652-64 64-64h64zM192 512c0 35.346-28.654 64-64 64h-64c-35.346 0-64-28.654-64-64s28.654-64 64-64h64c35.346 0 64 28.654 64 64zM828.784 738.274l45.256 45.258c24.992 24.99 24.992 65.516 0 90.508-24.994 24.992-65.518 24.992-90.51 0l-45.256-45.256c-24.992-24.99-24.992-65.516 0-90.51 24.994-24.992 65.518-24.992 90.51-0zM195.216 285.726l-45.256-45.256c-24.994-24.994-24.994-65.516 0-90.51s65.516-24.994 90.51 0l45.256 45.256c24.994 24.994 24.994 65.516 0 90.51s-65.516 24.994-90.51 0zM828.784 285.726c-24.992 24.992-65.516 24.992-90.51 0-24.992-24.994-24.992-65.516 0-90.51l45.256-45.254c24.992-24.994 65.516-24.994 90.51 0 24.992 24.994 24.992 65.516 0 90.51l-45.256 45.254zM195.216 738.274c
24.992-24.992 65.518-24.992 90.508 0 24.994 24.994 24.994 65.52 0 90.51l-45.254 45.256c-24.994 24.992-65.516 24.992-90.51 0s-24.994-65.518 0-90.508l45.256-45.258z",
- "M512 256c-141.384 0-256 114.616-256 256 0 141.382 114.616 256 256 256 141.382 0 256-114.618 256-256 0-141.384-114.616-256-256-256zM512 672c-88.366 0-160-71.634-160-160s71.634-160 160-160 160 71.634 160 160-71.634 160-160 160z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "sun",
- "weather"
- ],
- "defaultCode": 58094,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 844,
- "order": 635,
- "prevSize": 32,
- "code": 60620,
- "ligatures": "sun2, weather21",
- "name": "sun"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 101
- },
- {
- "icon": {
- "paths": [
- "M715.812 64.48c-60.25-34.784-124.618-55.904-189.572-64.48 122.936 160.082 144.768 384.762 37.574 570.42-107.2 185.67-312.688 279.112-512.788 252.68 39.898 51.958 90.376 97.146 150.628 131.934 245.908 141.974 560.37 57.72 702.344-188.198 141.988-245.924 57.732-560.372-188.186-702.356z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "moon",
- "night",
- "sleep"
- ],
- "defaultCode": 58105,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 855,
- "order": 636,
- "prevSize": 32,
- "code": 60621,
- "ligatures": "moon, night",
- "name": "moon"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 102
- },
- {
- "icon": {
- "paths": [
- "M672 1024l192-192-320-320 320-320-192-192-512 512z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "arrow-left",
- "left",
- "previous"
- ],
- "defaultCode": 58291,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 1056,
- "order": 637,
- "prevSize": 32,
- "code": 60864,
- "ligatures": "arrow-left, left4",
- "name": "arrowleft"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 103
- },
- {
- "icon": {
- "paths": [
- "M832 256l192-192-64-64-192 192h-448v-192h-128v192h-192v128h192v512h512v192h128v-192h192v-128h-192v-448zM320 320h320l-320 320v-320zM384 704l320-320v320h-320z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "tags": [
- "crop",
- "resize",
- "cut"
- ],
- "defaultCode": 58428,
- "grid": 16
- },
- "attrs": [],
- "properties": {
- "id": 1201,
- "order": 638,
- "prevSize": 32,
- "code": 61048,
- "ligatures": "crop, resize",
- "name": "crop"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 104
- },
- {
- "icon": {
- "paths": [
- "M0 64v896h1024v-896h-1024zM640 704v192h-256v-192h256zM640 192v192h-256v-192h256zM320 192v192h-256v-192h256zM704 384v-192h256v192h-256zM64 704h256v192h-256v-192zM704 896v-192h256v192h-256z"
- ],
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "isMulticolor": false,
- "tags": [
- "tablerowprops"
- ],
- "defaultCode": 58880,
- "grid": 16
- },
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "properties": {
- "id": 1680,
- "order": 639,
- "prevSize": 32,
- "code": 58884,
- "name": "tablerowprops"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 105
- },
- {
- "icon": {
- "paths": [
- "M0 64v896h1024v-896h-1024zM640 704v192h-256v-192h256zM640 192v192h-256v-192h256zM320 192v192h-256v-192h256zM64 448h256v192h-256v-192zM704 448h256v192h-256v-192zM704 384v-192h256v192h-256zM64 704h256v192h-256v-192zM704 896v-192h256v192h-256z"
- ],
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "isMulticolor": false,
- "tags": [
- "tablecellprops"
- ],
- "defaultCode": 58881,
- "grid": 16
- },
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "properties": {
- "id": 1681,
- "order": 640,
- "prevSize": 32,
- "code": 58885,
- "name": "tablecellprops"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 106
- },
- {
- "icon": {
- "paths": [
- "M0 64v832h1024v-832h-1024zM320 832h-256v-192h256v192zM320 576h-256v-192h256v192zM640 832h-256v-192h256v192zM640 576h-256v-192h256v192zM960 832h-256v-192h256v192zM960 576h-256v-192h256v192zM960 320h-896v-192h896v192z"
- ],
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "isMulticolor": false,
- "tags": [
- "table2"
- ],
- "defaultCode": 58882,
- "grid": 16
- },
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "properties": {
- "id": 1682,
- "order": 641,
- "prevSize": 32,
- "code": 58886,
- "name": "table2"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 107
- },
- {
- "icon": {
- "paths": [
- "M0 64v896h1024v-896h-1024zM384 896v-448h576v448h-576zM640 192v192h-256v-192h256zM320 192v192h-256v-192h256zM64 448h256v192h-256v-192zM704 384v-192h256v192h-256zM64 704h256v192h-256v-192z"
- ],
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "isMulticolor": false,
- "tags": [
- "tablemergecells"
- ],
- "defaultCode": 58884,
- "grid": 16
- },
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "properties": {
- "id": 1683,
- "order": 586,
- "prevSize": 32,
- "code": 58887,
- "name": "tablemergecells"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 108
- },
- {
- "icon": {
- "paths": [
- "M320 771.2v-182.4h-182.4v-89.6h182.4v-182.4h86.4v182.4h185.6v89.6h-185.6v182.4zM0 64v896h1024v-896h-1024zM640 896h-576v-704h576v704zM960 896h-256v-192h256v192zM960 640h-256v-192h256v192zM960 384h-256v-192h256v192z"
- ],
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "isMulticolor": false,
- "tags": [
- "tableinsertcolbefore"
- ],
- "defaultCode": 58885,
- "grid": 16
- },
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "properties": {
- "id": 1684,
- "order": 587,
- "prevSize": 32,
- "code": 58888,
- "name": "tableinsertcolbefore"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 109
- },
- {
- "icon": {
- "paths": [
- "M704 316.8v182.4h182.4v89.6h-182.4v182.4h-86.4v-182.4h-185.6v-89.6h185.6v-182.4zM0 64v896h1024v-896h-1024zM320 896h-256v-192h256v192zM320 640h-256v-192h256v192zM320 384h-256v-192h256v192zM960 896h-576v-704h576v704z"
- ],
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "isMulticolor": false,
- "tags": [
- "tableinsertcolafter"
- ],
- "defaultCode": 58886,
- "grid": 16
- },
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "properties": {
- "id": 1685,
- "order": 588,
- "prevSize": 32,
- "code": 58889,
- "name": "tableinsertcolafter"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 110
- },
- {
- "icon": {
- "paths": [
- "M691.2 451.2h-144v144h-70.4v-144h-144v-67.2h144v-144h70.4v144h144zM0 64v896h1024v-896h-1024zM320 896h-256v-192h256v192zM640 896h-256v-192h256v192zM960 896h-256v-192h256v192zM960 643.2h-896v-451.2h896v451.2z"
- ],
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "isMulticolor": false,
- "tags": [
- "tableinsertrowbefore"
- ],
- "defaultCode": 58887,
- "grid": 16
- },
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "properties": {
- "id": 1686,
- "order": 589,
- "prevSize": 32,
- "code": 58890,
- "name": "tableinsertrowbefore"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 111
- },
- {
- "icon": {
- "paths": [
- "M332.8 636.8h144v-144h70.4v144h144v67.2h-144v144h-70.4v-144h-144zM0 64v896h1024v-896h-1024zM384 192h256v192h-256v-192zM64 192h256v192h-256v-192zM960 896h-896v-451.2h896v451.2zM960 384h-256v-192h256v192z"
- ],
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "isMulticolor": false,
- "tags": [
- "tableinsertrowafter"
- ],
- "defaultCode": 58888,
- "grid": 16
- },
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "properties": {
- "id": 1687,
- "order": 590,
- "prevSize": 32,
- "code": 58891,
- "name": "tableinsertrowafter"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 112
- },
- {
- "icon": {
- "paths": [
- "M0 64v896h1024v-896h-1024zM384 192h256v192h-256v-192zM320 896h-256v-192h256v192zM320 640h-256v-192h256v192zM320 384h-256v-192h256v192zM960 896h-576v-448h576v448zM960 384h-256v-192h256v192zM864 803.2l-60.8 60.8-131.2-131.2-131.2 131.2-60.8-60.8 131.2-131.2-131.2-131.2 60.8-60.8 131.2 131.2 131.2-131.2 60.8 60.8-131.2 131.2z"
- ],
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "isMulticolor": false,
- "tags": [
- "tablesplitcells"
- ],
- "defaultCode": 58890,
- "grid": 16
- },
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "properties": {
- "id": 1688,
- "order": 591,
- "prevSize": 32,
- "code": 58893,
- "name": "tablesplitcells"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 113
- },
- {
- "icon": {
- "paths": [
- "M0 64h1024v896h-1024v-896zM60.8 192v704h899.2v-704h-899.2zM809.6 748.8l-96 96-204.8-204.8-204.8 204.8-96-96 204.8-204.8-204.8-204.8 96-96 204.8 204.8 204.8-204.8 96 96-204.8 204.8z"
- ],
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "isMulticolor": false,
- "tags": [
- "tabledelete"
- ],
- "defaultCode": 58891,
- "grid": 16
- },
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "properties": {
- "id": 1689,
- "order": 592,
- "prevSize": 32,
- "code": 58894,
- "name": "tabledelete"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 114
- },
- {
- "icon": {
- "paths": [
- "M0 64v832h1024v-832h-1024zM640 832h-256v-192h256v192zM640 576h-256v-192h256v192zM640 320h-256v-192h256v192zM960 832h-256v-192h256v192zM960 576h-256v-192h256v192zM960 320h-256v-192h256v192z"
- ],
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "isMulticolor": false,
- "tags": [
- "tableleftheader"
- ],
- "defaultCode": 58922,
- "grid": 16
- },
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "properties": {
- "id": 1690,
- "order": 593,
- "prevSize": 32,
- "code": 58922,
- "name": "tableleftheader"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 115
- },
- {
- "icon": {
- "paths": [
- "M0 64v832h1024v-832h-1024zM320 832h-256v-192h256v192zM320 576h-256v-192h256v192zM640 832h-256v-192h256v192zM640 576h-256v-192h256v192zM960 832h-256v-192h256v192zM960 576h-256v-192h256v192z"
- ],
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "isMulticolor": false,
- "tags": [
- "tabletopheader"
- ],
- "defaultCode": 58923,
- "grid": 16
- },
- "attrs": [
- {
- "fill": "rgb(0, 0, 0)"
- }
- ],
- "properties": {
- "id": 1691,
- "order": 594,
- "prevSize": 32,
- "code": 58923,
- "name": "tabletopheader"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 116
- },
- {
- "icon": {
- "paths": [
- "M886.4 387.2l-156.8 156.8 160 160-76.8 76.8-160-160-156.8 156.8-76.8-73.6 160-160-163.2-163.2 76.8-76.8 163.2 163.2 156.8-156.8 73.6 76.8zM0 64v896h1024v-896h-1024zM960 384h-22.4l-64 64h86.4v192h-89.6l64 64h25.6v192h-896v-192h310.4l64-64h-374.4v-192h371.2l-64-64h-307.2v-192h896v192z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "grid": 16,
- "tags": [
- "tabledeleterow"
- ],
- "defaultCode": 59392
- },
- "attrs": [],
- "properties": {
- "order": 595,
- "id": 1693,
- "prevSize": 32,
- "code": 59392,
- "name": "tabledeleterow"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 117
- },
- {
- "icon": {
- "paths": [
- "M320 460.8l64 64v12.8l-64 64v-140.8zM640 537.6l64 64v-137.6l-64 64v9.6zM1024 64v896h-1024v-896h1024zM960 192h-256v51.2l-12.8-12.8-51.2 51.2v-89.6h-256v89.6l-51.2-51.2-12.8 12.8v-51.2h-256v704h256v-118.4l35.2 35.2 28.8-28.8v115.2h256v-115.2l48 48 16-16v83.2h256v-707.2zM672 297.6l-156.8 156.8-163.2-163.2-76.8 76.8 163.2 163.2-156.8 156.8 76.8 76.8 156.8-156.8 160 160 76.8-76.8-160-160 156.8-156.8-76.8-76.8z"
- ],
- "attrs": [],
- "isMulticolor": false,
- "grid": 16,
- "tags": [
- "tabledeletecol"
- ],
- "defaultCode": 59393
- },
- "attrs": [],
- "properties": {
- "order": 596,
- "id": 1692,
- "prevSize": 32,
- "code": 59393,
- "name": "tabledeletecol"
- },
- "setIdx": 2,
- "setId": 1,
- "iconIdx": 118
- }
- ],
- "height": 1024,
- "metadata": {
- "name": "tinymce"
- },
- "preferences": {
- "showGlyphs": true,
- "showQuickUse": true,
- "showQuickUse2": true,
- "showSVGs": true,
- "fontPref": {
- "prefix": "icon-",
- "metadata": {
- "fontFamily": "tinymce",
- "majorVersion": 1,
- "minorVersion": 0
- },
- "metrics": {
- "emSize": 1024,
- "baseline": 6.25,
- "whitespace": 50
- },
- "resetPoint": 59649,
- "embed": false
- },
- "imagePref": {
- "prefix": "icon-",
- "png": true,
- "useClassSelector": true,
- "color": 4473924,
- "bgColor": 16777215
- },
- "historySize": 100,
- "gridSize": 16,
- "showGrid": true,
- "showCodes": true,
- "showLiga": false
- }
-}
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymceskinslightgrayskinie7mincss"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/src/wp-includes/js/tinymce/skins/lightgray/skin.ie7.min.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/skins/lightgray/skin.ie7.min.css 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/skins/lightgray/skin.ie7.min.css 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-.mce-container,.mce-container *,.mce-widget,.mce-widget *,.mce-reset{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:#333;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;-webkit-tap-highlight-color:transparent;line-height:normal;font-weight:normal;text-align:left;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr;max-width:none}.mce-widget button{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.mce-container *[unselectable]{-moz-user-select:none;-webkit-user-select:none;-o-user-select:none;user-select:none}.mce-fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.mce-fade.mce-in{opacity:1}.m
ce-tinymce{visibility:inherit !important;position:relative}.mce-fullscreen{border:0;padding:0;margin:0;overflow:hidden;height:100%;z-index:100}div.mce-fullscreen{position:fixed;top:0;left:0;width:100%;height:auto}.mce-tinymce{display:block}.mce-wordcount{position:absolute;top:0;right:0;padding:8px}div.mce-edit-area{background:#FFF;filter:none}.mce-statusbar{position:relative}.mce-statusbar .mce-container-body{position:relative}.mce-fullscreen .mce-resizehandle{display:none}.mce-charmap{border-collapse:collapse}.mce-charmap td{cursor:default;border:1px solid rgba(0,0,0,0.2);width:20px;height:20px;line-height:20px;text-align:center;vertical-align:middle;padding:2px}.mce-charmap td div{text-align:center}.mce-charmap td:hover{background:#D9D9D9}.mce-grid td.mce-grid-cell div{border:1px solid #d6d6d6;width:15px;height:15px;margin:0;cursor:pointer}.mce-grid td.mce-grid-cell div:focus{border-color:#3498db}.mce-grid td.mce-grid-cell div[disabled]{cursor:not-allowed}.mce-grid{border-spacing:
2px;border-collapse:separate}.mce-grid a{display:block;border:1px solid transparent}.mce-grid a:hover,.mce-grid a:focus{border-color:#3498db}.mce-grid-border{margin:0 4px 0 4px}.mce-grid-border a{border-color:#d6d6d6;width:13px;height:13px}.mce-grid-border a:hover,.mce-grid-border a.mce-active{border-color:#3498db;background:#3498db}.mce-text-center{text-align:center}div.mce-tinymce-inline{width:100%}.mce-colorbtn-trans div{text-align:center;vertical-align:middle;font-weight:bold;font-size:20px;line-height:16px;color:#707070}.mce-monospace{font-family:"Courier New",Courier,monospace}.mce-toolbar-grp{padding:2px 0}.mce-toolbar-grp .mce-flow-layout-item{margin-bottom:0}.mce-rtl .mce-wordcount{left:0;right:auto}.mce-croprect-container{position:absolute;top:0;left:0}.mce-croprect-handle{position:absolute;top:0;left:0;width:20px;height:20px;border:2px solid white}.mce-croprect-handle-nw{border-width:2px 0 0 2px;margin:-2px 0 0 -2px;cursor:nw-resize;top:100px;left:100px}.mce-cro
prect-handle-ne{border-width:2px 2px 0 0;margin:-2px 0 0 -20px;cursor:ne-resize;top:100px;left:200px}.mce-croprect-handle-sw{border-width:0 0 2px 2px;margin:-20px 2px 0 -2px;cursor:sw-resize;top:200px;left:100px}.mce-croprect-handle-se{border-width:0 2px 2px 0;margin:-20px 0 0 -20px;cursor:se-resize;top:200px;left:200px}.mce-croprect-handle-move{position:absolute;cursor:move;border:0}.mce-croprect-block{opacity:.3;filter:alpha(opacity=30);zoom:1;position:absolute;background:black}.mce-croprect-handle:focus{border-color:#3498db}.mce-croprect-handle-move:focus{outline:1px solid #3498db}.mce-imagepanel{overflow:auto;background:black}.mce-imagepanel-bg{position:absolute;background:url('data:image/gif;base64,R0lGODdhDAAMAIABAMzMzP///ywAAAAADAAMAAACFoQfqYeabNyDMkBQb81Uat85nxguUAEAOw==')}.mce-imagepanel img{position:absolute}.mce-imagetool.mce-btn .mce-ico{display:block;width:20px;height:20px;text-align:center;line-height:20px;font-size:20px;padding:5px}.mce-arrow-up{margin-top:12px}.mce-a
rrow-down{margin-top:-12px}.mce-arrow:before,.mce-arrow:after{position:absolute;left:50%;display:block;width:0;height:0;border-style:solid;border-color:transparent;content:""}.mce-arrow.mce-arrow-up:before{top:-9px;border-bottom-color:rgba(0,0,0,0.2);border-width:0 9px 9px;margin-left:-9px}.mce-arrow.mce-arrow-down:before{bottom:-9px;border-top-color:rgba(0,0,0,0.2);border-width:9px 9px 0;margin-left:-9px}.mce-arrow.mce-arrow-up:after{top:-8px;border-bottom-color:#f0f0f0;border-width:0 8px 8px;margin-left:-8px}.mce-arrow.mce-arrow-down:after{bottom:-8px;border-top-color:#f0f0f0;border-width:8px 8px 0;margin-left:-8px}.mce-arrow.mce-arrow-left:before,.mce-arrow.mce-arrow-left:after{margin:0}.mce-arrow.mce-arrow-left:before{left:8px}.mce-arrow.mce-arrow-left:after{left:9px}.mce-arrow.mce-arrow-right:before,.mce-arrow.mce-arrow-right:after{left:auto;margin:0}.mce-arrow.mce-arrow-right:before{right:8px}.mce-arrow.mce-arrow-right:after{right:9px}.mce-arrow.mce-arrow-center.mce-
arrow.mce-arrow-left:before{left:-9px;top:50%;border-right-color:rgba(0,0,0,0.2);border-width:9px 9px 9px 0;margin-top:-9px}.mce-arrow.mce-arrow-center.mce-arrow.mce-arrow-left:after{left:-8px;top:50%;border-right-color:#f0f0f0;border-width:8px 8px 8px 0;margin-top:-8px}.mce-arrow.mce-arrow-center.mce-arrow.mce-arrow-left{margin-left:12px}.mce-arrow.mce-arrow-center.mce-arrow.mce-arrow-right:before{right:-9px;top:50%;border-left-color:rgba(0,0,0,0.2);border-width:9px 0 9px 9px;margin-top:-9px}.mce-arrow.mce-arrow-center.mce-arrow.mce-arrow-right:after{right:-8px;top:50%;border-left-color:#f0f0f0;border-width:8px 0 8px 8px;margin-top:-8px}.mce-arrow.mce-arrow-center.mce-arrow.mce-arrow-right{margin-left:-14px}.mce-container,.mce-container-body{display:block}.mce-autoscroll{overflow:hidden}.mce-scrollbar{position:absolute;width:7px;height:100%;top:2px;right:2px;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-scrollbar-h{top:auto;right:auto;left:2px;bottom:2px;width:100%;height:7px}.mc
e-scrollbar-thumb{position:absolute;background-color:#000;border:1px solid #888;border-color:rgba(85,85,85,0.6);width:5px;height:100%}.mce-scrollbar-h .mce-scrollbar-thumb{width:100%;height:5px}.mce-scrollbar:hover,.mce-scrollbar.mce-active{background-color:#AAA;opacity:.6;filter:alpha(opacity=60);zoom:1}.mce-scroll{position:relative}.mce-panel{border:0 solid #cacaca;border:0 solid rgba(0,0,0,0.2);background-color:#f0f0f0}.mce-floatpanel{position:absolute}.mce-floatpanel.mce-fixed{position:fixed}.mce-floatpanel .mce-arrow,.mce-floatpanel .mce-arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.mce-floatpanel .mce-arrow{border-width:11px}.mce-floatpanel .mce-arrow:after{border-width:10px;content:""}.mce-floatpanel.mce-popover{filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;top:0;left:0;background:#FFF;border:1px solid rgba(0,0,0,0.2);border:1px solid rgba(0,0,0,0.25)}.mce-floatpa
nel.mce-popover.mce-bottom{margin-top:10px;*margin-top:0}.mce-floatpanel.mce-popover.mce-bottom>.mce-arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:rgba(0,0,0,0.2);border-bottom-color:rgba(0,0,0,0.25);top:-11px}.mce-floatpanel.mce-popover.mce-bottom>.mce-arrow:after{top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#FFF}.mce-floatpanel.mce-popover.mce-bottom.mce-start{margin-left:-22px}.mce-floatpanel.mce-popover.mce-bottom.mce-start>.mce-arrow{left:20px}.mce-floatpanel.mce-popover.mce-bottom.mce-end{margin-left:22px}.mce-floatpanel.mce-popover.mce-bottom.mce-end>.mce-arrow{right:10px;left:auto}.mce-fullscreen{border:0;padding:0;margin:0;overflow:hidden;height:100%}div.mce-fullscreen{position:fixed;top:0;left:0}#mce-modal-block{opacity:0;filter:alpha(opacity=0);zoom:1;position:fixed;left:0;top:0;width:100%;height:100%;background:#000}#mce-modal-block.mce-in{opacity:.3;filter:alpha(opacity=30);zoom:1}.mce-window-move{cursor:move}.mc
e-window{filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;background:#FFF;position:fixed;top:0;left:0;opacity:0;transform:scale(.1);transition:transform 100ms ease-in,opacity 150ms ease-in}.mce-window.mce-in{transform:scale(1);opacity:1}.mce-window-head{padding:9px 15px;border-bottom:1px solid #c5c5c5;position:relative}.mce-window-head .mce-close{position:absolute;right:0;top:0;height:38px;width:38px;text-align:center;cursor:pointer}.mce-window-head .mce-close i{color:#858585}.mce-close:hover i{color:#adadad}.mce-window-head .mce-title{line-height:20px;font-size:20px;font-weight:bold;text-rendering:optimizelegibility;padding-right:20px}.mce-window .mce-container-body{display:block}.mce-foot{display:block;background-color:#FFF;border-top:1px solid #c5c5c5}.mce-window-head .mce-dragh{position:absolute;top:0;left:0;cursor:move;width:90%;height:100%}.mce-window iframe{width:100%;height:100%}.mce-window-body .mce-listbox{border-color:#ccc}.mce-rtl
.mce-window-head .mce-close{position:absolute;right:auto;left:15px}.mce-rtl .mce-window-head .mce-dragh{left:auto;right:0}.mce-rtl .mce-window-head .mce-title{direction:rtl;text-align:right}.mce-tooltip{position:absolute;padding:5px;opacity:.8;filter:alpha(opacity=80);zoom:1}.mce-tooltip-inner{font-size:11px;background-color:#000;color:white;max-width:200px;padding:5px 8px 4px 8px;text-align:center;white-space:normal}.mce-tooltip-arrow{position:absolute;width:0;height:0;line-height:0;border:5px dashed #000}.mce-tooltip-arrow-n{border-bottom-color:#000}.mce-tooltip-arrow-s{border-top-color:#000}.mce-tooltip-arrow-e{border-left-color:#000}.mce-tooltip-arrow-w{border-right-color:#000}.mce-tooltip-nw,.mce-tooltip-sw{margin-left:-14px}.mce-tooltip-ne,.mce-tooltip-se{margin-left:14px}.mce-tooltip-n .mce-tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-nw .mce-tooltip-arrow{top
:0;left:10px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-ne .mce-tooltip-arrow{top:0;right:10px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-s .mce-tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-sw .mce-tooltip-arrow{bottom:0;left:10px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-se .mce-tooltip-arrow{bottom:0;right:10px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-e .mce-tooltip-arrow{right:0;top:50%;margin-top:-5px;border-left-style:solid;border-right:none;border-top-color:transparent;border-bottom-color:transparent}.mce-tooltip-w .mce-tooltip-arrow{left:0;top:50%;margin-top:-5px;borde
r-right-style:solid;border-left:none;border-top-color:transparent;border-bottom-color:transparent}.mce-progress{display:inline-block;position:relative;height:20px}.mce-progress .mce-bar-container{display:inline-block;width:100px;height:100%;margin-right:8px;border:1px solid #ccc;overflow:hidden}.mce-progress .mce-text{display:inline-block;margin-top:auto;margin-bottom:auto;font-size:14px;width:40px;color:#333}.mce-bar{display:block;width:0;height:100%;background-color:#d7d7d7;-webkit-transition:width .2s ease;transition:width .2s ease}.mce-notification{position:absolute;background-color:#F0F0F0;padding:5px;margin-top:5px;border-width:1px;border-style:solid;border-color:#CCCCCC;transition:transform 100ms ease-in,opacity 150ms ease-in;opacity:0}.mce-notification.mce-in{opacity:1}.mce-notification-success{background-color:#dff0d8;border-color:#d6e9c6}.mce-notification-info{background-color:#d9edf7;border-color:#779ECB}.mce-notification-warning{background-color:#fcf8e3;border-color:#fae
bcc}.mce-notification-error{background-color:#f2dede;border-color:#ebccd1}.mce-notification.mce-has-close{padding-right:15px}.mce-notification .mce-ico{margin-top:5px}.mce-notification-inner{display:inline-block;font-size:14px;margin:5px 8px 4px 8px;text-align:center;white-space:normal;color:#31708f}.mce-notification-inner a{text-decoration:underline;cursor:pointer}.mce-notification .mce-progress{margin-right:8px}.mce-notification .mce-progress .mce-text{margin-top:5px}.mce-notification *,.mce-notification .mce-progress .mce-text{color:#333333}.mce-notification .mce-progress .mce-bar-container{border-color:#CCCCCC}.mce-notification .mce-progress .mce-bar-container .mce-bar{background-color:#333333}.mce-notification-success *,.mce-notification-success .mce-progress .mce-text{color:#3c763d}.mce-notification-success .mce-progress .mce-bar-container{border-color:#d6e9c6}.mce-notification-success .mce-progress .mce-bar-container .mce-bar{background-color:#3c763d}.mce-notification-info *,
.mce-notification-info .mce-progress .mce-text{color:#31708f}.mce-notification-info .mce-progress .mce-bar-container{border-color:#779ECB}.mce-notification-info .mce-progress .mce-bar-container .mce-bar{background-color:#31708f}.mce-notification-warning *,.mce-notification-warning .mce-progress .mce-text{color:#8a6d3b}.mce-notification-warning .mce-progress .mce-bar-container{border-color:#faebcc}.mce-notification-warning .mce-progress .mce-bar-container .mce-bar{background-color:#8a6d3b}.mce-notification-error *,.mce-notification-error .mce-progress .mce-text{color:#a94442}.mce-notification-error .mce-progress .mce-bar-container{border-color:#ebccd1}.mce-notification-error .mce-progress .mce-bar-container .mce-bar{background-color:#a94442}.mce-notification .mce-close{position:absolute;top:6px;right:8px;font-size:20px;font-weight:bold;line-height:20px;color:#858585;cursor:pointer;height:20px;overflow:hidden}.mce-abs-layout{position:relative}body .mce-abs-layout-item,.mce-abs-end{pos
ition:absolute}.mce-abs-end{width:1px;height:1px}.mce-container-body.mce-abs-layout{overflow:hidden}.mce-btn{border:1px solid #b1b1b1;border-color:transparent transparent transparent transparent;position:relative;text-shadow:0 1px 1px rgba(255,255,255,0.75);display:inline-block;*display:inline;*zoom:1;background-color:#f0f0f0}.mce-btn:hover,.mce-btn:focus{color:#333;background-color:#e3e3e3;border-color:#ccc}.mce-btn.mce-disabled button,.mce-btn.mce-disabled:hover button{cursor:default;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-btn.mce-active,.mce-btn.mce-active:hover{background-color:#dbdbdb;border-color:#ccc}.mce-btn:active{background-color:#e0e0e0;border-color:#ccc}.mce-btn button{padding:4px 8px;font-size:14px;line-height:20px;*line-height:16px;cursor:pointer;color:#333;text-align:center;overflow:visible;-webkit-appearance:none}.mce-btn button::-moz-focus-inner{border:0;padding:0}.mce-btn i{text-shadow:1px 1px none}.mce-primary.mce-btn-has-text{min-width:50px}.mce-primary{c
olor:#fff;border:1px solid transparent;border-color:transparent;background-color:#2d8ac7}.mce-primary:hover,.mce-primary:focus{background-color:#257cb6;border-color:transparent}.mce-primary.mce-disabled button,.mce-primary.mce-disabled:hover button{cursor:default;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-primary.mce-active,.mce-primary.mce-active:hover,.mce-primary:not(.mce-disabled):active{background-color:#206ea1}.mce-primary button,.mce-primary button i{color:#fff;text-shadow:1px 1px none}.mce-btn .mce-txt{font-size:inherit;line-height:inherit;color:inherit}.mce-btn-large button{padding:9px 14px;font-size:16px;line-height:normal}.mce-btn-large i{margin-top:2px}.mce-btn-small button{padding:1px 5px;font-size:12px;*padding-bottom:2px}.mce-btn-small i{line-height:20px;vertical-align:top;*line-height:18px}.mce-btn .mce-caret{margin-top:8px;margin-left:0}.mce-btn-small .mce-caret{margin-top:8px;margin-left:0}.mce-caret{display:inline-block;*display:inline;*zoom:1;width:0;height:
0;vertical-align:top;border-top:4px solid #333;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.mce-disabled .mce-caret{border-top-color:#aaa}.mce-caret.mce-up{border-bottom:4px solid #333;border-top:0}.mce-btn-flat{border:0;background:transparent;filter:none}.mce-btn-flat:hover,.mce-btn-flat.mce-active,.mce-btn-flat:focus,.mce-btn-flat:active{border:0;background:#e6e6e6;filter:none}.mce-btn-has-text .mce-ico{padding-right:5px}.mce-rtl .mce-btn button{direction:rtl}.mce-btn-group .mce-btn{border-width:1px;margin:0;margin-left:2px}.mce-btn-group:not(:first-child){border-left:1px solid #d9d9d9;padding-left:3px;margin-left:3px}.mce-btn-group .mce-first{margin-left:0}.mce-btn-group .mce-btn.mce-flow-layout-item{margin:0}.mce-rtl .mce-btn-group .mce-btn{margin-left:0;margin-right:2px}.mce-rtl .mce-btn-group .mce-first{margin-right:0}.mce-rtl .mce-btn-group:not(:first-child){border-left:none;border-right:1px solid #d9d9d9;padding-right:4px;margin-
right:4px}.mce-checkbox{cursor:pointer}i.mce-i-checkbox{margin:0 3px 0 0;border:1px solid #c5c5c5;background-color:#f0f0f0;text-indent:-10em;*font-size:0;*line-height:0;*text-indent:0;overflow:hidden}.mce-checked i.mce-i-checkbox{color:#333;font-size:16px;line-height:16px;text-indent:0}.mce-checkbox:focus i.mce-i-checkbox,.mce-checkbox.mce-focus i.mce-i-checkbox{border:1px solid rgba(82,168,236,0.8)}.mce-checkbox.mce-disabled .mce-label,.mce-checkbox.mce-disabled i.mce-i-checkbox{color:#acacac}.mce-checkbox .mce-label{vertical-align:middle}.mce-rtl .mce-checkbox{direction:rtl;text-align:right}.mce-rtl i.mce-i-checkbox{margin:0 0 0 3px}.mce-combobox{position:relative;display:inline-block;*display:inline;*zoom:1;*height:32px}.mce-combobox input{border:1px solid #c5c5c5;border-right-color:#c5c5c5;height:28px}.mce-combobox.mce-disabled input{color:#adadad}.mce-combobox .mce-btn{border:1px solid #c5c5c5;border-left:0;margin:0}.mce-combobox button{padding-right:8px;padding-left:8px}.mce-c
ombobox.mce-disabled .mce-btn button{cursor:default;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-combobox .mce-status{position:absolute;right:2px;top:50%;line-height:16px;margin-top:-8px;font-size:12px;width:15px;height:15px;text-align:center;cursor:pointer}.mce-combobox.mce-has-status input{padding-right:20px}.mce-combobox.mce-has-open .mce-status{right:37px}.mce-combobox .mce-status.mce-i-warning{color:#c09853}.mce-combobox .mce-status.mce-i-checkmark{color:#468847}.mce-menu.mce-combobox-menu{border-top:0;margin-top:0;max-height:200px}.mce-menu.mce-combobox-menu .mce-menu-item{padding:4px 6px 4px 4px;font-size:11px}.mce-menu.mce-combobox-menu .mce-menu-item-sep{padding:0}.mce-menu.mce-combobox-menu .mce-text{font-size:11px}.mce-menu.mce-combobox-menu .mce-menu-item-link,.mce-menu.mce-combobox-menu .mce-menu-item-link b{font-size:11px}.mce-menu.mce-combobox-menu .mce-text b{font-size:11px}.mce-colorbox i{border:1px solid #c5c5c5;width:14px;height:14px}.mce-colorbutton .mce-ico{p
osition:relative}.mce-colorbutton-grid{margin:4px}.mce-colorbutton button{padding-right:6px;padding-left:6px}.mce-colorbutton .mce-preview{padding-right:3px;display:block;position:absolute;left:50%;top:50%;margin-left:-17px;margin-top:7px;background:gray;width:13px;height:2px;overflow:hidden}.mce-colorbutton.mce-btn-small .mce-preview{margin-left:-16px;padding-right:0;width:16px}.mce-colorbutton .mce-open{padding-left:4px;padding-right:4px;border-left:1px solid transparent}.mce-colorbutton:hover .mce-open{border-color:#ccc}.mce-colorbutton.mce-btn-small .mce-open{padding:0 3px 0 3px}.mce-rtl .mce-colorbutton{direction:rtl}.mce-rtl .mce-colorbutton .mce-preview{margin-left:0;padding-right:0;padding-left:3px}.mce-rtl .mce-colorbutton.mce-btn-small .mce-preview{margin-left:0;padding-right:0;padding-left:2px}.mce-rtl .mce-colorbutton .mce-open{padding-left:4px;padding-right:4px;border-left:0}.mce-colorpicker{position:relative;width:250px;height:220px}.mce-colorpicker-sv{position:absolut
e;top:0;left:0;width:90%;height:100%;border:1px solid #c5c5c5;cursor:crosshair;overflow:hidden}.mce-colorpicker-h-chunk{width:100%}.mce-colorpicker-overlay1,.mce-colorpicker-overlay2{width:100%;height:100%;position:absolute;top:0;left:0}.mce-colorpicker-overlay1{filter:progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr='#ffffff', endColorstr='#00ffffff');-ms-filter:"progid:DXImageTransform.Microsoft.gradient(GradientType=1,startColorstr='#ffffff', endColorstr='#00ffffff')";background:linear-gradient(to right, #fff, rgba(255,255,255,0))}.mce-colorpicker-overlay2{filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#00000000', endColorstr='#000000');-ms-filter:"progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='#00000000', endColorstr='#000000')";background:linear-gradient(to bottom, rgba(0,0,0,0), #000)}.mce-colorpicker-selector1{background:none;position:absolute;width:12px;height:12px;margin:
-8px 0 0 -8px;border:1px solid black;border-radius:50%}.mce-colorpicker-selector2{position:absolute;width:10px;height:10px;border:1px solid white;border-radius:50%}.mce-colorpicker-h{position:absolute;top:0;right:0;width:6.5%;height:100%;border:1px solid #c5c5c5;cursor:crosshair}.mce-colorpicker-h-marker{margin-top:-4px;position:absolute;top:0;left:-1px;width:100%;border:1px solid #333;background:#fff;height:4px;z-index:100}.mce-path{display:inline-block;*display:inline;*zoom:1;padding:8px;white-space:normal}.mce-path .mce-txt{display:inline-block;padding-right:3px}.mce-path .mce-path-body{display:inline-block}.mce-path-item{display:inline-block;*display:inline;*zoom:1;cursor:pointer;color:#333}.mce-path-item:hover{text-decoration:underline}.mce-path-item:focus{background:#666;color:#fff}.mce-path .mce-divider{display:inline}.mce-disabled .mce-path-item{color:#aaa}.mce-rtl .mce-path{direction:rtl}.mce-fieldset{border:0 solid #9E9E9E}.mce-fieldset>.mce-container-body{margin-top:-1
5px}.mce-fieldset-title{margin-left:5px;padding:0 5px 0 5px}.mce-fit-layout{display:inline-block;*display:inline;*zoom:1}.mce-fit-layout-item{position:absolute}.mce-flow-layout-item{display:inline-block;*display:inline;*zoom:1}.mce-flow-layout-item{margin:2px 0 2px 2px}.mce-flow-layout-item.mce-last{margin-right:2px}.mce-flow-layout{white-space:normal}.mce-tinymce-inline .mce-flow-layout{white-space:nowrap}.mce-rtl .mce-flow-layout{text-align:right;direction:rtl}.mce-rtl .mce-flow-layout-item{margin:2px 2px 2px 0}.mce-rtl .mce-flow-layout-item.mce-last{margin-left:2px}.mce-iframe{border:0 solid rgba(0,0,0,0.2);width:100%;height:100%}.mce-infobox{display:inline-block;*display:inline;*zoom:1;text-shadow:0 1px 1px rgba(255,255,255,0.75);overflow:hidden;border:1px solid red}.mce-infobox div{display:block;margin:5px}.mce-infobox div button{position:absolute;top:50%;right:4px;cursor:pointer;margin-top:-8px;display:none}.mce-infobox div button:focus{outline:2px solid #ccc}.mce-infobox.mce-
has-help div{margin-right:25px}.mce-infobox.mce-has-help button{display:block}.mce-infobox.mce-success{background:#dff0d8;border-color:#d6e9c6}.mce-infobox.mce-success div{color:#3c763d}.mce-infobox.mce-warning{background:#fcf8e3;border-color:#faebcc}.mce-infobox.mce-warning div{color:#8a6d3b}.mce-infobox.mce-error{background:#f2dede;border-color:#ebccd1}.mce-infobox.mce-error div{color:#a94442}.mce-rtl .mce-infobox div{text-align:right;direction:rtl}.mce-label{display:inline-block;*display:inline;*zoom:1;text-shadow:0 1px 1px rgba(255,255,255,0.75);overflow:hidden}.mce-label.mce-autoscroll{overflow:auto}.mce-label.mce-disabled{color:#aaa}.mce-label.mce-multiline{white-space:pre-wrap}.mce-label.mce-success{color:#468847}.mce-label.mce-warning{color:#c09853}.mce-label.mce-error{color:#b94a48}.mce-rtl .mce-label{text-align:right;direction:rtl}.mce-menubar .mce-menubtn{border-color:transparent;background:transparent;filter:none}.mce-menubar .mce-menubtn button{color:#333}.mce-menubar{b
order:1px solid rgba(217,217,217,0.52)}.mce-menubar .mce-menubtn button span{color:#333}.mce-menubar .mce-caret{border-top-color:#333}.mce-menubar .mce-menubtn:hover,.mce-menubar .mce-menubtn.mce-active,.mce-menubar .mce-menubtn:focus{border-color:#ccc;background:#fff;filter:none}.mce-menubtn button{color:#333}.mce-menubtn.mce-btn-small span{font-size:12px}.mce-menubtn.mce-fixed-width span{display:inline-block;overflow-x:hidden;text-overflow:ellipsis;width:90px}.mce-menubtn.mce-fixed-width.mce-btn-small span{width:70px}.mce-menubtn .mce-caret{*margin-top:6px}.mce-rtl .mce-menubtn button{direction:rtl;text-align:right}.mce-menu-item{display:block;padding:6px 15px 6px 12px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap;cursor:pointer;line-height:normal;border-left:4px solid transparent;margin-bottom:1px}.mce-menu-item .mce-ico,.mce-menu-item .mce-text{color:#333}.mce-menu-item.mce-disabled .mce-text,.mce-menu-item.mce-disabled .mce-ico{color:#adadad}.mce-
menu-item:hover .mce-text,.mce-menu-item.mce-selected .mce-text,.mce-menu-item:focus .mce-text{color:white}.mce-menu-item:hover .mce-ico,.mce-menu-item.mce-selected .mce-ico,.mce-menu-item:focus .mce-ico{color:white}.mce-menu-item.mce-disabled:hover{background:#CCC}.mce-menu-shortcut{display:inline-block;color:#adadad}.mce-menu-shortcut{display:inline-block;*display:inline;*zoom:1;padding:0 15px 0 20px}.mce-menu-item:hover .mce-menu-shortcut,.mce-menu-item.mce-selected .mce-menu-shortcut,.mce-menu-item:focus .mce-menu-shortcut{color:white}.mce-menu-item .mce-caret{margin-top:4px;*margin-top:3px;margin-right:6px;border-top:4px solid transparent;border-bottom:4px solid transparent;border-left:4px solid #333}.mce-menu-item.mce-selected .mce-caret,.mce-menu-item:focus .mce-caret,.mce-menu-item:hover .mce-caret{border-left-color:white}.mce-menu-align .mce-menu-shortcut{*margin-top:-2px}.mce-menu-align .mce-menu-shortcut,.mce-menu-align .mce-caret{position:absolute;right:0}.mce-menu-item.
mce-active i{visibility:visible}.mce-menu-item-normal.mce-active{background-color:#3498db}.mce-menu-item-preview.mce-active{border-left:5px solid #aaa}.mce-menu-item-normal.mce-active .mce-text{color:white}.mce-menu-item-normal.mce-active:hover .mce-text,.mce-menu-item-normal.mce-active:hover .mce-ico{color:white}.mce-menu-item-normal.mce-active:focus .mce-text,.mce-menu-item-normal.mce-active:focus .mce-ico{color:white}.mce-menu-item:hover,.mce-menu-item.mce-selected,.mce-menu-item:focus{text-decoration:none;color:white;background-color:#2d8ac7}.mce-menu-item-link{color:#093;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mce-menu-item-link b{color:#093}.mce-menu-item-ellipsis{display:block;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.mce-menu-item:hover *,.mce-menu-item.mce-selected *,.mce-menu-item:focus *{color:white}div.mce-menu .mce-menu-item-sep,.mce-menu-item-sep:hover{border:0;padding:0;height:1px;margin:9px 1px;overflow:hidden;background:transparen
t;border-bottom:1px solid rgba(0,0,0,0.1);cursor:default;filter:none}div.mce-menu .mce-menu-item b{font-weight:bold}.mce-menu-item-indent-1{padding-left:20px}.mce-menu-item-indent-2{padding-left:35px}.mce-menu-item-indent-2{padding-left:35px}.mce-menu-item-indent-3{padding-left:40px}.mce-menu-item-indent-4{padding-left:45px}.mce-menu-item-indent-5{padding-left:50px}.mce-menu-item-indent-6{padding-left:55px}.mce-menu.mce-rtl{direction:rtl}.mce-rtl .mce-menu-item{text-align:right;direction:rtl;padding:6px 12px 6px 15px}.mce-menu-align.mce-rtl .mce-menu-shortcut,.mce-menu-align.mce-rtl .mce-caret{right:auto;left:0}.mce-rtl .mce-menu-item .mce-caret{margin-left:6px;margin-right:0;border-right:4px solid #333;border-left:0}.mce-rtl .mce-menu-item.mce-selected .mce-caret,.mce-rtl .mce-menu-item:focus .mce-caret,.mce-rtl .mce-menu-item:hover .mce-caret{border-left-color:transparent;border-right-color:white}.mce-throbber{position:absolute;top:0;left:0;width:100%;height:100%;opacity:.6;filter
:alpha(opacity=60);zoom:1;background:#fff url('img/loader.gif') no-repeat center center}.mce-throbber-inline{position:static;height:50px}.mce-menu .mce-throbber-inline{height:25px;background-size:contain}.mce-menu{position:absolute;left:0;top:0;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;z-index:1000;padding:5px 0 5px 0;margin:-1px 0 0;min-width:160px;background:#fff;border:1px solid #989898;border:1px solid rgba(0,0,0,0.2);z-index:1002;max-height:400px;overflow:auto;overflow-x:hidden}.mce-menu i{display:none}.mce-menu-has-icons i{display:inline-block;*display:inline}.mce-menu-sub-tr-tl{margin:-6px 0 0 -1px}.mce-menu-sub-br-bl{margin:6px 0 0 -1px}.mce-menu-sub-tl-tr{margin:-6px 0 0 1px}.mce-menu-sub-bl-br{margin:6px 0 0 1px}.mce-listbox button{text-align:left;padding-right:20px;position:relative}.mce-listbox .mce-caret{position:absolute;margin-top:-2px;right:8px;top:50%}.mce-rtl .mce-listbox .mce-caret{right:auto;left:8px}.mce-rtl .mce-l
istbox button{padding-right:10px;padding-left:20px}.mce-container-body .mce-resizehandle{position:absolute;right:0;bottom:0;width:16px;height:16px;visibility:visible;cursor:s-resize;margin:0}.mce-container-body .mce-resizehandle-both{cursor:se-resize}i.mce-i-resize{color:#333}.mce-selectbox{background:#fff;border:1px solid #c5c5c5}.mce-slider{border:1px solid #AAA;background:#EEE;width:100px;height:10px;position:relative;display:block}.mce-slider.mce-vertical{width:10px;height:100px}.mce-slider-handle{border:1px solid #BBB;background:#DDD;display:block;width:13px;height:13px;position:absolute;top:0;left:0;margin-left:-1px;margin-top:-2px}.mce-slider-handle:focus{background:#BBB}.mce-spacer{visibility:hidden}.mce-splitbtn .mce-open{border-left:1px solid transparent}.mce-splitbtn:hover .mce-open{border-left-color:#ccc}.mce-splitbtn button{padding-right:6px;padding-left:6px}.mce-splitbtn .mce-open{padding-right:4px;padding-left:4px}.mce-splitbtn .mce-open.mce-active{background-color:#d
bdbdb;outline:1px solid #ccc}.mce-splitbtn.mce-btn-small .mce-open{padding:0 3px 0 3px}.mce-rtl .mce-splitbtn{direction:rtl;text-align:right}.mce-rtl .mce-splitbtn button{padding-right:4px;padding-left:4px}.mce-rtl .mce-splitbtn .mce-open{border-left:0}.mce-stack-layout-item{display:block}.mce-tabs{display:block;border-bottom:1px solid #c5c5c5}.mce-tabs,.mce-tabs+.mce-container-body{background:#FFF}.mce-tab{display:inline-block;*display:inline;*zoom:1;border:1px solid #c5c5c5;border-width:0 1px 0 0;background:#ffffff;padding:8px;text-shadow:0 1px 1px rgba(255,255,255,0.75);height:13px;cursor:pointer}.mce-tab:hover{background:#FDFDFD}.mce-tab.mce-active{background:#FDFDFD;border-bottom-color:transparent;margin-bottom:-1px;height:14px}.mce-rtl .mce-tabs{text-align:right;direction:rtl}.mce-rtl .mce-tab{border-width:0 0 0 1px}.mce-textbox{background:#fff;border:1px solid #c5c5c5;display:inline-block;-webkit-transition:border linear .2s, box-shadow linear .2s;transition:border linear .2s
, box-shadow linear .2s;height:28px;resize:none;padding:0 4px 0 4px;white-space:pre-wrap;*white-space:pre;color:#333}.mce-textbox:focus,.mce-textbox.mce-focus{border-color:#3498db}.mce-placeholder .mce-textbox{color:#aaa}.mce-textbox.mce-multiline{padding:4px;height:auto}.mce-textbox.mce-disabled{color:#adadad}.mce-rtl .mce-textbox{text-align:right;direction:rtl}@font-face{font-family:'tinymce';src:url('fonts/tinymce.eot');src:url('fonts/tinymce.eot?#iefix') format('embedded-opentype'),url('fonts/tinymce.woff') format('woff'),url('fonts/tinymce.ttf') format('truetype'),url('fonts/tinymce.svg#tinymce') format('svg');font-weight:normal;font-style:normal}@font-face{font-family:'tinymce-small';src:url('fonts/tinymce-small.eot');src:url('fonts/tinymce-small.eot?#iefix') format('embedded-opentype'),url('fonts/tinymce-small.woff') format('woff'),url('fonts/tinymce-small.ttf') format('truetype'),url('fonts/tinymce-small.svg#tinymce') format('svg');font-weight:normal;font-style:normal}.mce-i
co{font-family:'tinymce';font-style:normal;font-weight:normal;font-size:16px;line-height:16px;vertical-align:text-top;-webkit-font-smoothing:antialiased;display:inline-block;background:transparent center center;width:16px;height:16px;color:#333;-ie7-icon:' '}.mce-btn-small .mce-ico{font-family:'tinymce-small'}.mce-ico,i.mce-i-checkbox{zoom:expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = this.currentStyle['-ie7-icon'].substr(1, 1) + ' ')}.mce-i-save{-ie7-icon:"\e000"}.mce-i-newdocument{-ie7-icon:"\e001"}.mce-i-fullpage{-ie7-icon:"\e002"}.mce-i-alignleft{-ie7-icon:"\e003"}.mce-i-aligncenter{-ie7-icon:"\e004"}.mce-i-alignright{-ie7-icon:"\e005"}.mce-i-alignjustify{-ie7-icon:"\e006"}.mce-i-alignnone{-ie7-icon:"\e003"}.mce-i-cut{-ie7-icon:"\e007"}.mce-i-paste{-ie7-icon:"\e008"}.mce-i-searchreplace{-ie7-icon:"\e009"}.mce-i-bullist{-ie7-icon:"\e00a"}
.mce-i-numlist{-ie7-icon:"\e00b"}.mce-i-indent{-ie7-icon:"\e00c"}.mce-i-outdent{-ie7-icon:"\e00d"}.mce-i-blockquote{-ie7-icon:"\e00e"}.mce-i-undo{-ie7-icon:"\e00f"}.mce-i-redo{-ie7-icon:"\e010"}.mce-i-link{-ie7-icon:"\e011"}.mce-i-unlink{-ie7-icon:"\e012"}.mce-i-anchor{-ie7-icon:"\e013"}.mce-i-image{-ie7-icon:"\e014"}.mce-i-media{-ie7-icon:"\e015"}.mce-i-help{-ie7-icon:"\e016"}.mce-i-code{-ie7-icon:"\e017"}.mce-i-insertdatetime{-ie7-icon:"\e018"}.mce-i-preview{-ie7-icon:"\e019"}.mce-i-forecolor{-ie7-icon:"\e01a"}.mce-i-backcolor{-ie7-icon:"\e01a"}.mce-i-table{-ie7-icon:"\e01b"}.mce-i-hr{-ie7-icon:"\e01c"}.mce-i-removeformat{-ie7-icon:"\e01d"}.mce-i-subscript{-ie7-icon:"\e01e"}.mce-i-superscript{-ie7-icon:"\e01f"}.mce-i-charmap{-ie7-icon:"\e020"}.mce-i-emoti
cons{-ie7-icon:"\e021"}.mce-i-print{-ie7-icon:"\e022"}.mce-i-fullscreen{-ie7-icon:"\e023"}.mce-i-spellchecker{-ie7-icon:"\e024"}.mce-i-nonbreaking{-ie7-icon:"\e025"}.mce-i-template{-ie7-icon:"\e026"}.mce-i-pagebreak{-ie7-icon:"\e027"}.mce-i-restoredraft{-ie7-icon:"\e028"}.mce-i-untitled{-ie7-icon:"\e029"}.mce-i-bold{-ie7-icon:"\e02a"}.mce-i-italic{-ie7-icon:"\e02b"}.mce-i-underline{-ie7-icon:"\e02c"}.mce-i-strikethrough{-ie7-icon:"\e02d"}.mce-i-visualchars{-ie7-icon:"\e02e"}.mce-i-ltr{-ie7-icon:"\e02f"}.mce-i-rtl{-ie7-icon:"\e030"}.mce-i-copy{-ie7-icon:"\e031"}.mce-i-resize{-ie7-icon:"\e032"}.mce-i-browse{-ie7-icon:"\e034"}.mce-i-pastetext{-ie7-icon:"\e035"}.mce-i-rotateleft{-ie7-icon:"\eaa8"}.mce-i-rotateright{-ie7-icon:"\eaa9"}.mce-i-crop{-ie7-icon:"\ee78"
;}.mce-i-editimage{-ie7-icon:"\e914"}.mce-i-options{-ie7-icon:"\ec6a"}.mce-i-flipv{-ie7-icon:"\eaaa"}.mce-i-fliph{-ie7-icon:"\eaac"}.mce-i-zoomin{-ie7-icon:"\eb35"}.mce-i-zoomout{-ie7-icon:"\eb36"}.mce-i-sun{-ie7-icon:"\eccc"}.mce-i-moon{-ie7-icon:"\eccd"}.mce-i-arrowleft{-ie7-icon:"\edc0"}.mce-i-arrowright{-ie7-icon:"\edb8"}.mce-i-drop{-ie7-icon:"\e934"}.mce-i-contrast{-ie7-icon:"\ecd4"}.mce-i-sharpen{-ie7-icon:"\eba7"}.mce-i-palette{-ie7-icon:"\e92a"}.mce-i-resize2{-ie7-icon:"\edf9"}.mce-i-orientation{-ie7-icon:"\e601"}.mce-i-invert{-ie7-icon:"\e602"}.mce-i-gamma{-ie7-icon:"\e600"}.mce-i-remove{-ie7-icon:"\ed6a"}.mce-i-codesample{-ie7-icon:"\e603"}.mce-i-checkbox,.mce-i-selected{-ie7-icon:"\e033"}.mce-i-selected{visibility:hidden}.mce-i-backcolor{background:#BBB}
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymceskinslightgrayskinmincss"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/skins/lightgray/skin.min.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/skins/lightgray/skin.min.css 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/skins/lightgray/skin.min.css 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1 +1 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-.mce-container,.mce-container *,.mce-widget,.mce-widget *,.mce-reset{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:#333;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;-webkit-tap-highlight-color:transparent;line-height:normal;font-weight:normal;text-align:left;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr;max-width:none}.mce-widget button{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.mce-container *[unselectable]{-moz-user-select:none;-webkit-user-select:none;-o-user-select:none;user-select:none}.mce-fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.mce-fade.mce-in{opacity:1}.m
ce-tinymce{visibility:inherit !important;position:relative}.mce-fullscreen{border:0;padding:0;margin:0;overflow:hidden;height:100%;z-index:100}div.mce-fullscreen{position:fixed;top:0;left:0;width:100%;height:auto}.mce-tinymce{display:block}.mce-wordcount{position:absolute;top:0;right:0;padding:8px}div.mce-edit-area{background:#FFF;filter:none}.mce-statusbar{position:relative}.mce-statusbar .mce-container-body{position:relative}.mce-fullscreen .mce-resizehandle{display:none}.mce-charmap{border-collapse:collapse}.mce-charmap td{cursor:default;border:1px solid rgba(0,0,0,0.2);width:20px;height:20px;line-height:20px;text-align:center;vertical-align:middle;padding:2px}.mce-charmap td div{text-align:center}.mce-charmap td:hover{background:#D9D9D9}.mce-grid td.mce-grid-cell div{border:1px solid #d6d6d6;width:15px;height:15px;margin:0;cursor:pointer}.mce-grid td.mce-grid-cell div:focus{border-color:#3498db}.mce-grid td.mce-grid-cell div[disabled]{cursor:not-allowed}.mce-grid{border-spacing:
2px;border-collapse:separate}.mce-grid a{display:block;border:1px solid transparent}.mce-grid a:hover,.mce-grid a:focus{border-color:#3498db}.mce-grid-border{margin:0 4px 0 4px}.mce-grid-border a{border-color:#d6d6d6;width:13px;height:13px}.mce-grid-border a:hover,.mce-grid-border a.mce-active{border-color:#3498db;background:#3498db}.mce-text-center{text-align:center}div.mce-tinymce-inline{width:100%}.mce-colorbtn-trans div{text-align:center;vertical-align:middle;font-weight:bold;font-size:20px;line-height:16px;color:#707070}.mce-monospace{font-family:"Courier New",Courier,monospace}.mce-toolbar-grp{padding:2px 0}.mce-toolbar-grp .mce-flow-layout-item{margin-bottom:0}.mce-rtl .mce-wordcount{left:0;right:auto}.mce-croprect-container{position:absolute;top:0;left:0}.mce-croprect-handle{position:absolute;top:0;left:0;width:20px;height:20px;border:2px solid white}.mce-croprect-handle-nw{border-width:2px 0 0 2px;margin:-2px 0 0 -2px;cursor:nw-resize;top:100px;left:100px}.mce-cro
prect-handle-ne{border-width:2px 2px 0 0;margin:-2px 0 0 -20px;cursor:ne-resize;top:100px;left:200px}.mce-croprect-handle-sw{border-width:0 0 2px 2px;margin:-20px 2px 0 -2px;cursor:sw-resize;top:200px;left:100px}.mce-croprect-handle-se{border-width:0 2px 2px 0;margin:-20px 0 0 -20px;cursor:se-resize;top:200px;left:200px}.mce-croprect-handle-move{position:absolute;cursor:move;border:0}.mce-croprect-block{opacity:.3;filter:alpha(opacity=30);zoom:1;position:absolute;background:black}.mce-croprect-handle:focus{border-color:#3498db}.mce-croprect-handle-move:focus{outline:1px solid #3498db}.mce-imagepanel{overflow:auto;background:black}.mce-imagepanel-bg{position:absolute;background:url('data:image/gif;base64,R0lGODdhDAAMAIABAMzMzP///ywAAAAADAAMAAACFoQfqYeabNyDMkBQb81Uat85nxguUAEAOw==')}.mce-imagepanel img{position:absolute}.mce-imagetool.mce-btn .mce-ico{display:block;width:20px;height:20px;text-align:center;line-height:20px;font-size:20px;padding:5px}.mce-arrow-up{margin-top:12px}.mce-a
rrow-down{margin-top:-12px}.mce-arrow:before,.mce-arrow:after{position:absolute;left:50%;display:block;width:0;height:0;border-style:solid;border-color:transparent;content:""}.mce-arrow.mce-arrow-up:before{top:-9px;border-bottom-color:rgba(0,0,0,0.2);border-width:0 9px 9px;margin-left:-9px}.mce-arrow.mce-arrow-down:before{bottom:-9px;border-top-color:rgba(0,0,0,0.2);border-width:9px 9px 0;margin-left:-9px}.mce-arrow.mce-arrow-up:after{top:-8px;border-bottom-color:#f0f0f0;border-width:0 8px 8px;margin-left:-8px}.mce-arrow.mce-arrow-down:after{bottom:-8px;border-top-color:#f0f0f0;border-width:8px 8px 0;margin-left:-8px}.mce-arrow.mce-arrow-left:before,.mce-arrow.mce-arrow-left:after{margin:0}.mce-arrow.mce-arrow-left:before{left:8px}.mce-arrow.mce-arrow-left:after{left:9px}.mce-arrow.mce-arrow-right:before,.mce-arrow.mce-arrow-right:after{left:auto;margin:0}.mce-arrow.mce-arrow-right:before{right:8px}.mce-arrow.mce-arrow-right:after{right:9px}.mce-arrow.mce-arrow-center.mce-
arrow.mce-arrow-left:before{left:-9px;top:50%;border-right-color:rgba(0,0,0,0.2);border-width:9px 9px 9px 0;margin-top:-9px}.mce-arrow.mce-arrow-center.mce-arrow.mce-arrow-left:after{left:-8px;top:50%;border-right-color:#f0f0f0;border-width:8px 8px 8px 0;margin-top:-8px}.mce-arrow.mce-arrow-center.mce-arrow.mce-arrow-left{margin-left:12px}.mce-arrow.mce-arrow-center.mce-arrow.mce-arrow-right:before{right:-9px;top:50%;border-left-color:rgba(0,0,0,0.2);border-width:9px 0 9px 9px;margin-top:-9px}.mce-arrow.mce-arrow-center.mce-arrow.mce-arrow-right:after{right:-8px;top:50%;border-left-color:#f0f0f0;border-width:8px 0 8px 8px;margin-top:-8px}.mce-arrow.mce-arrow-center.mce-arrow.mce-arrow-right{margin-left:-14px}.mce-edit-aria-container>.mce-container-body{display:flex}.mce-edit-aria-container>.mce-container-body .mce-edit-area{flex:1}.mce-edit-aria-container>.mce-container-body .mce-sidebar>.mce-container-body{display:flex;align-items:stretch;height:100%}.mce-edit-aria-cont
ainer>.mce-container-body .mce-sidebar-panel{min-width:250px;max-width:250px;position:relative}.mce-edit-aria-container>.mce-container-body .mce-sidebar-panel>.mce-container-body{position:absolute;width:100%;height:100%;overflow:auto;top:0;left:0}.mce-sidebar-toolbar{border:0 solid rgba(0,0,0,0.2);border-left-width:1px}.mce-sidebar-toolbar .mce-btn.mce-active,.mce-sidebar-toolbar .mce-btn.mce-active:hover{border:1px solid transparent;border-color:transparent;background-color:#2d8ac7}.mce-sidebar-toolbar .mce-btn.mce-active button,.mce-sidebar-toolbar .mce-btn.mce-active:hover button,.mce-sidebar-toolbar .mce-btn.mce-active button i,.mce-sidebar-toolbar .mce-btn.mce-active:hover button i{color:#fff;text-shadow:1px 1px none}.mce-sidebar-panel{border:0 solid rgba(0,0,0,0.2);border-left-width:1px}.mce-container,.mce-container-body{display:block}.mce-autoscroll{overflow:hidden}.mce-scrollbar{position:absolute;width:7px;height:100%;top:2px;right:2px;opacity:.4;filter:alpha(opacit
y=40);zoom:1}.mce-scrollbar-h{top:auto;right:auto;left:2px;bottom:2px;width:100%;height:7px}.mce-scrollbar-thumb{position:absolute;background-color:#000;border:1px solid #888;border-color:rgba(85,85,85,0.6);width:5px;height:100%}.mce-scrollbar-h .mce-scrollbar-thumb{width:100%;height:5px}.mce-scrollbar:hover,.mce-scrollbar.mce-active{background-color:#AAA;opacity:.6;filter:alpha(opacity=60);zoom:1}.mce-scroll{position:relative}.mce-panel{border:0 solid #cacaca;border:0 solid rgba(0,0,0,0.2);background-color:#f0f0f0}.mce-floatpanel{position:absolute}.mce-floatpanel.mce-fixed{position:fixed}.mce-floatpanel .mce-arrow,.mce-floatpanel .mce-arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.mce-floatpanel .mce-arrow{border-width:11px}.mce-floatpanel .mce-arrow:after{border-width:10px;content:""}.mce-floatpanel.mce-popover{filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;top:0;left:0;
background:#FFF;border:1px solid rgba(0,0,0,0.2);border:1px solid rgba(0,0,0,0.25)}.mce-floatpanel.mce-popover.mce-bottom{margin-top:10px;*margin-top:0}.mce-floatpanel.mce-popover.mce-bottom>.mce-arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:rgba(0,0,0,0.2);border-bottom-color:rgba(0,0,0,0.25);top:-11px}.mce-floatpanel.mce-popover.mce-bottom>.mce-arrow:after{top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#FFF}.mce-floatpanel.mce-popover.mce-bottom.mce-start{margin-left:-22px}.mce-floatpanel.mce-popover.mce-bottom.mce-start>.mce-arrow{left:20px}.mce-floatpanel.mce-popover.mce-bottom.mce-end{margin-left:22px}.mce-floatpanel.mce-popover.mce-bottom.mce-end>.mce-arrow{right:10px;left:auto}.mce-fullscreen{border:0;padding:0;margin:0;overflow:hidden;height:100%}div.mce-fullscreen{position:fixed;top:0;left:0}#mce-modal-block{opacity:0;filter:alpha(opacity=0);zoom:1;position:fixed;left:0;top:0;width:100%;height:100%;background:#000}#mce
-modal-block.mce-in{opacity:.3;filter:alpha(opacity=30);zoom:1}.mce-window-move{cursor:move}.mce-window{filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;background:#FFF;position:fixed;top:0;left:0;opacity:0;transform:scale(.1);transition:transform 100ms ease-in,opacity 150ms ease-in}.mce-window.mce-in{transform:scale(1);opacity:1}.mce-window-head{padding:9px 15px;border-bottom:1px solid #c5c5c5;position:relative}.mce-window-head .mce-close{position:absolute;right:0;top:0;height:38px;width:38px;text-align:center;cursor:pointer}.mce-window-head .mce-close i{color:#858585}.mce-close:hover i{color:#adadad}.mce-window-head .mce-title{line-height:20px;font-size:20px;font-weight:bold;text-rendering:optimizelegibility;padding-right:20px}.mce-window .mce-container-body{display:block}.mce-foot{display:block;background-color:#FFF;border-top:1px solid #c5c5c5}.mce-window-head .mce-dragh{position:absolute;top:0;left:0;cursor:move;width:90%;height:100%}.mc
e-window iframe{width:100%;height:100%}.mce-window-body .mce-listbox{border-color:#ccc}.mce-rtl .mce-window-head .mce-close{position:absolute;right:auto;left:15px}.mce-rtl .mce-window-head .mce-dragh{left:auto;right:0}.mce-rtl .mce-window-head .mce-title{direction:rtl;text-align:right}.mce-tooltip{position:absolute;padding:5px;opacity:.8;filter:alpha(opacity=80);zoom:1}.mce-tooltip-inner{font-size:11px;background-color:#000;color:white;max-width:200px;padding:5px 8px 4px 8px;text-align:center;white-space:normal}.mce-tooltip-arrow{position:absolute;width:0;height:0;line-height:0;border:5px dashed #000}.mce-tooltip-arrow-n{border-bottom-color:#000}.mce-tooltip-arrow-s{border-top-color:#000}.mce-tooltip-arrow-e{border-left-color:#000}.mce-tooltip-arrow-w{border-right-color:#000}.mce-tooltip-nw,.mce-tooltip-sw{margin-left:-14px}.mce-tooltip-ne,.mce-tooltip-se{margin-left:14px}.mce-tooltip-n .mce-tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-style:solid;border-top:none;bord
er-left-color:transparent;border-right-color:transparent}.mce-tooltip-nw .mce-tooltip-arrow{top:0;left:10px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-ne .mce-tooltip-arrow{top:0;right:10px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-s .mce-tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-sw .mce-tooltip-arrow{bottom:0;left:10px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-se .mce-tooltip-arrow{bottom:0;right:10px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-e .mce-tooltip-arrow{right:0;top:50%;margin-top:-5px;border-left-style:solid;border-right:none;border-top-color:transparent;border-
bottom-color:transparent}.mce-tooltip-w .mce-tooltip-arrow{left:0;top:50%;margin-top:-5px;border-right-style:solid;border-left:none;border-top-color:transparent;border-bottom-color:transparent}.mce-progress{display:inline-block;position:relative;height:20px}.mce-progress .mce-bar-container{display:inline-block;width:100px;height:100%;margin-right:8px;border:1px solid #ccc;overflow:hidden}.mce-progress .mce-text{display:inline-block;margin-top:auto;margin-bottom:auto;font-size:14px;width:40px;color:#333}.mce-bar{display:block;width:0;height:100%;background-color:#d7d7d7;-webkit-transition:width .2s ease;transition:width .2s ease}.mce-notification{position:absolute;background-color:#F0F0F0;padding:5px;margin-top:5px;border-width:1px;border-style:solid;border-color:#CCCCCC;transition:transform 100ms ease-in,opacity 150ms ease-in;opacity:0}.mce-notification.mce-in{opacity:1}.mce-notification-success{background-color:#dff0d8;border-color:#d6e9c6}.mce-notification-info{background-color:#d
9edf7;border-color:#779ECB}.mce-notification-warning{background-color:#fcf8e3;border-color:#faebcc}.mce-notification-error{background-color:#f2dede;border-color:#ebccd1}.mce-notification.mce-has-close{padding-right:15px}.mce-notification .mce-ico{margin-top:5px}.mce-notification-inner{display:inline-block;font-size:14px;margin:5px 8px 4px 8px;text-align:center;white-space:normal;color:#31708f}.mce-notification-inner a{text-decoration:underline;cursor:pointer}.mce-notification .mce-progress{margin-right:8px}.mce-notification .mce-progress .mce-text{margin-top:5px}.mce-notification *,.mce-notification .mce-progress .mce-text{color:#333333}.mce-notification .mce-progress .mce-bar-container{border-color:#CCCCCC}.mce-notification .mce-progress .mce-bar-container .mce-bar{background-color:#333333}.mce-notification-success *,.mce-notification-success .mce-progress .mce-text{color:#3c763d}.mce-notification-success .mce-progress .mce-bar-container{border-color:#d6e9c6}.mce-notification-succe
ss .mce-progress .mce-bar-container .mce-bar{background-color:#3c763d}.mce-notification-info *,.mce-notification-info .mce-progress .mce-text{color:#31708f}.mce-notification-info .mce-progress .mce-bar-container{border-color:#779ECB}.mce-notification-info .mce-progress .mce-bar-container .mce-bar{background-color:#31708f}.mce-notification-warning *,.mce-notification-warning .mce-progress .mce-text{color:#8a6d3b}.mce-notification-warning .mce-progress .mce-bar-container{border-color:#faebcc}.mce-notification-warning .mce-progress .mce-bar-container .mce-bar{background-color:#8a6d3b}.mce-notification-error *,.mce-notification-error .mce-progress .mce-text{color:#a94442}.mce-notification-error .mce-progress .mce-bar-container{border-color:#ebccd1}.mce-notification-error .mce-progress .mce-bar-container .mce-bar{background-color:#a94442}.mce-notification .mce-close{position:absolute;top:6px;right:8px;font-size:20px;font-weight:bold;line-height:20px;color:#858585;cursor:pointer;height:20
px;overflow:hidden}.mce-abs-layout{position:relative}body .mce-abs-layout-item,.mce-abs-end{position:absolute}.mce-abs-end{width:1px;height:1px}.mce-container-body.mce-abs-layout{overflow:hidden}.mce-btn{border:1px solid #b1b1b1;border-color:transparent transparent transparent transparent;position:relative;text-shadow:0 1px 1px rgba(255,255,255,0.75);display:inline-block;*display:inline;*zoom:1;background-color:#f0f0f0}.mce-btn:hover,.mce-btn:focus{color:#333;background-color:#e3e3e3;border-color:#ccc}.mce-btn.mce-disabled button,.mce-btn.mce-disabled:hover button{cursor:default;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-btn.mce-active,.mce-btn.mce-active:hover{background-color:#dbdbdb;border-color:#ccc}.mce-btn:active{background-color:#e0e0e0;border-color:#ccc}.mce-btn button{padding:4px 8px;font-size:14px;line-height:20px;*line-height:16px;cursor:pointer;color:#333;text-align:center;overflow:visible;-webkit-appearance:none}.mce-btn button::-moz-focus-inner{border:0;padding:0}
.mce-btn i{text-shadow:1px 1px none}.mce-primary.mce-btn-has-text{min-width:50px}.mce-primary{color:#fff;border:1px solid transparent;border-color:transparent;background-color:#2d8ac7}.mce-primary:hover,.mce-primary:focus{background-color:#257cb6;border-color:transparent}.mce-primary.mce-disabled button,.mce-primary.mce-disabled:hover button{cursor:default;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-primary.mce-active,.mce-primary.mce-active:hover,.mce-primary:not(.mce-disabled):active{background-color:#206ea1}.mce-primary button,.mce-primary button i{color:#fff;text-shadow:1px 1px none}.mce-btn .mce-txt{font-size:inherit;line-height:inherit;color:inherit}.mce-btn-large button{padding:9px 14px;font-size:16px;line-height:normal}.mce-btn-large i{margin-top:2px}.mce-btn-small button{padding:1px 5px;font-size:12px;*padding-bottom:2px}.mce-btn-small i{line-height:20px;vertical-align:top;*line-height:18px}.mce-btn .mce-caret{margin-top:8px;margin-left:0}.mce-btn-small .mce-caret{margi
n-top:8px;margin-left:0}.mce-caret{display:inline-block;*display:inline;*zoom:1;width:0;height:0;vertical-align:top;border-top:4px solid #333;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.mce-disabled .mce-caret{border-top-color:#aaa}.mce-caret.mce-up{border-bottom:4px solid #333;border-top:0}.mce-btn-flat{border:0;background:transparent;filter:none}.mce-btn-flat:hover,.mce-btn-flat.mce-active,.mce-btn-flat:focus,.mce-btn-flat:active{border:0;background:#e6e6e6;filter:none}.mce-btn-has-text .mce-ico{padding-right:5px}.mce-rtl .mce-btn button{direction:rtl}.mce-btn-group .mce-btn{border-width:1px;margin:0;margin-left:2px}.mce-btn-group:not(:first-child){border-left:1px solid #d9d9d9;padding-left:3px;margin-left:3px}.mce-btn-group .mce-first{margin-left:0}.mce-btn-group .mce-btn.mce-flow-layout-item{margin:0}.mce-rtl .mce-btn-group .mce-btn{margin-left:0;margin-right:2px}.mce-rtl .mce-btn-group .mce-first{margin-right:0}.mce-rtl .mce-btn-gr
oup:not(:first-child){border-left:none;border-right:1px solid #d9d9d9;padding-right:4px;margin-right:4px}.mce-checkbox{cursor:pointer}i.mce-i-checkbox{margin:0 3px 0 0;border:1px solid #c5c5c5;background-color:#f0f0f0;text-indent:-10em;*font-size:0;*line-height:0;*text-indent:0;overflow:hidden}.mce-checked i.mce-i-checkbox{color:#333;font-size:16px;line-height:16px;text-indent:0}.mce-checkbox:focus i.mce-i-checkbox,.mce-checkbox.mce-focus i.mce-i-checkbox{border:1px solid rgba(82,168,236,0.8)}.mce-checkbox.mce-disabled .mce-label,.mce-checkbox.mce-disabled i.mce-i-checkbox{color:#acacac}.mce-checkbox .mce-label{vertical-align:middle}.mce-rtl .mce-checkbox{direction:rtl;text-align:right}.mce-rtl i.mce-i-checkbox{margin:0 0 0 3px}.mce-combobox{position:relative;display:inline-block;*display:inline;*zoom:1;*height:32px}.mce-combobox input{border:1px solid #c5c5c5;border-right-color:#c5c5c5;height:28px}.mce-combobox.mce-disabled input{color:#adadad}.mce-combobox .mce-btn{border:1px soli
d #c5c5c5;border-left:0;margin:0}.mce-combobox button{padding-right:8px;padding-left:8px}.mce-combobox.mce-disabled .mce-btn button{cursor:default;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-combobox .mce-status{position:absolute;right:2px;top:50%;line-height:16px;margin-top:-8px;font-size:12px;width:15px;height:15px;text-align:center;cursor:pointer}.mce-combobox.mce-has-status input{padding-right:20px}.mce-combobox.mce-has-open .mce-status{right:37px}.mce-combobox .mce-status.mce-i-warning{color:#c09853}.mce-combobox .mce-status.mce-i-checkmark{color:#468847}.mce-menu.mce-combobox-menu{border-top:0;margin-top:0;max-height:200px}.mce-menu.mce-combobox-menu .mce-menu-item{padding:4px 6px 4px 4px;font-size:11px}.mce-menu.mce-combobox-menu .mce-menu-item-sep{padding:0}.mce-menu.mce-combobox-menu .mce-text{font-size:11px}.mce-menu.mce-combobox-menu .mce-menu-item-link,.mce-menu.mce-combobox-menu .mce-menu-item-link b{font-size:11px}.mce-menu.mce-combobox-menu .mce-text b{font-size:1
1px}.mce-colorbox i{border:1px solid #c5c5c5;width:14px;height:14px}.mce-colorbutton .mce-ico{position:relative}.mce-colorbutton-grid{margin:4px}.mce-colorbutton button{padding-right:6px;padding-left:6px}.mce-colorbutton .mce-preview{padding-right:3px;display:block;position:absolute;left:50%;top:50%;margin-left:-17px;margin-top:7px;background:gray;width:13px;height:2px;overflow:hidden}.mce-colorbutton.mce-btn-small .mce-preview{margin-left:-16px;padding-right:0;width:16px}.mce-colorbutton .mce-open{padding-left:4px;padding-right:4px;border-left:1px solid transparent}.mce-colorbutton:hover .mce-open{border-color:#ccc}.mce-colorbutton.mce-btn-small .mce-open{padding:0 3px 0 3px}.mce-rtl .mce-colorbutton{direction:rtl}.mce-rtl .mce-colorbutton .mce-preview{margin-left:0;padding-right:0;padding-left:3px}.mce-rtl .mce-colorbutton.mce-btn-small .mce-preview{margin-left:0;padding-right:0;padding-left:2px}.mce-rtl .mce-colorbutton .mce-open{padding-left:4px;padding-right:4px;border-left:0}.
mce-colorpicker{position:relative;width:250px;height:220px}.mce-colorpicker-sv{position:absolute;top:0;left:0;width:90%;height:100%;border:1px solid #c5c5c5;cursor:crosshair;overflow:hidden}.mce-colorpicker-h-chunk{width:100%}.mce-colorpicker-overlay1,.mce-colorpicker-overlay2{width:100%;height:100%;position:absolute;top:0;left:0}.mce-colorpicker-overlay1{filter:progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr='#ffffff', endColorstr='#00ffffff');-ms-filter:"progid:DXImageTransform.Microsoft.gradient(GradientType=1,startColorstr='#ffffff', endColorstr='#00ffffff')";background:linear-gradient(to right, #fff, rgba(255,255,255,0))}.mce-colorpicker-overlay2{filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#00000000', endColorstr='#000000');-ms-filter:"progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='#00000000', endColorstr='#000000')";background:linear-gradient(to bottom, rgba(0,0,0,0), #0
00)}.mce-colorpicker-selector1{background:none;position:absolute;width:12px;height:12px;margin:-8px 0 0 -8px;border:1px solid black;border-radius:50%}.mce-colorpicker-selector2{position:absolute;width:10px;height:10px;border:1px solid white;border-radius:50%}.mce-colorpicker-h{position:absolute;top:0;right:0;width:6.5%;height:100%;border:1px solid #c5c5c5;cursor:crosshair}.mce-colorpicker-h-marker{margin-top:-4px;position:absolute;top:0;left:-1px;width:100%;border:1px solid #333;background:#fff;height:4px;z-index:100}.mce-path{display:inline-block;*display:inline;*zoom:1;padding:8px;white-space:normal}.mce-path .mce-txt{display:inline-block;padding-right:3px}.mce-path .mce-path-body{display:inline-block}.mce-path-item{display:inline-block;*display:inline;*zoom:1;cursor:pointer;color:#333}.mce-path-item:hover{text-decoration:underline}.mce-path-item:focus{background:#666;color:#fff}.mce-path .mce-divider{display:inline}.mce-disabled .mce-path-item{color:#aaa}.mce-rtl .mce-path{direct
ion:rtl}.mce-fieldset{border:0 solid #9E9E9E}.mce-fieldset>.mce-container-body{margin-top:-15px}.mce-fieldset-title{margin-left:5px;padding:0 5px 0 5px}.mce-fit-layout{display:inline-block;*display:inline;*zoom:1}.mce-fit-layout-item{position:absolute}.mce-flow-layout-item{display:inline-block;*display:inline;*zoom:1}.mce-flow-layout-item{margin:2px 0 2px 2px}.mce-flow-layout-item.mce-last{margin-right:2px}.mce-flow-layout{white-space:normal}.mce-tinymce-inline .mce-flow-layout{white-space:nowrap}.mce-rtl .mce-flow-layout{text-align:right;direction:rtl}.mce-rtl .mce-flow-layout-item{margin:2px 2px 2px 0}.mce-rtl .mce-flow-layout-item.mce-last{margin-left:2px}.mce-iframe{border:0 solid rgba(0,0,0,0.2);width:100%;height:100%}.mce-infobox{display:inline-block;*display:inline;*zoom:1;text-shadow:0 1px 1px rgba(255,255,255,0.75);overflow:hidden;border:1px solid red}.mce-infobox div{display:block;margin:5px}.mce-infobox div button{position:absolute;top:50%;right:4px;cursor:pointer;marg
in-top:-8px;display:none}.mce-infobox div button:focus{outline:2px solid #ccc}.mce-infobox.mce-has-help div{margin-right:25px}.mce-infobox.mce-has-help button{display:block}.mce-infobox.mce-success{background:#dff0d8;border-color:#d6e9c6}.mce-infobox.mce-success div{color:#3c763d}.mce-infobox.mce-warning{background:#fcf8e3;border-color:#faebcc}.mce-infobox.mce-warning div{color:#8a6d3b}.mce-infobox.mce-error{background:#f2dede;border-color:#ebccd1}.mce-infobox.mce-error div{color:#a94442}.mce-rtl .mce-infobox div{text-align:right;direction:rtl}.mce-label{display:inline-block;*display:inline;*zoom:1;text-shadow:0 1px 1px rgba(255,255,255,0.75);overflow:hidden}.mce-label.mce-autoscroll{overflow:auto}.mce-label.mce-disabled{color:#aaa}.mce-label.mce-multiline{white-space:pre-wrap}.mce-label.mce-success{color:#468847}.mce-label.mce-warning{color:#c09853}.mce-label.mce-error{color:#b94a48}.mce-rtl .mce-label{text-align:right;direction:rtl}.mce-menubar .mce-menubtn{border-color:transparen
t;background:transparent;filter:none}.mce-menubar .mce-menubtn button{color:#333}.mce-menubar{border:1px solid rgba(217,217,217,0.52)}.mce-menubar .mce-menubtn button span{color:#333}.mce-menubar .mce-caret{border-top-color:#333}.mce-menubar .mce-menubtn:hover,.mce-menubar .mce-menubtn.mce-active,.mce-menubar .mce-menubtn:focus{border-color:#ccc;background:#fff;filter:none}.mce-menubtn button{color:#333}.mce-menubtn.mce-btn-small span{font-size:12px}.mce-menubtn.mce-fixed-width span{display:inline-block;overflow-x:hidden;text-overflow:ellipsis;width:90px}.mce-menubtn.mce-fixed-width.mce-btn-small span{width:70px}.mce-menubtn .mce-caret{*margin-top:6px}.mce-rtl .mce-menubtn button{direction:rtl;text-align:right}.mce-menu-item{display:block;padding:6px 15px 6px 12px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap;cursor:pointer;line-height:normal;border-left:4px solid transparent;margin-bottom:1px}.mce-menu-item .mce-ico,.mce-menu-item .mce-text{color:#333
}.mce-menu-item.mce-disabled .mce-text,.mce-menu-item.mce-disabled .mce-ico{color:#adadad}.mce-menu-item:hover .mce-text,.mce-menu-item.mce-selected .mce-text,.mce-menu-item:focus .mce-text{color:white}.mce-menu-item:hover .mce-ico,.mce-menu-item.mce-selected .mce-ico,.mce-menu-item:focus .mce-ico{color:white}.mce-menu-item.mce-disabled:hover{background:#CCC}.mce-menu-shortcut{display:inline-block;color:#adadad}.mce-menu-shortcut{display:inline-block;*display:inline;*zoom:1;padding:0 15px 0 20px}.mce-menu-item:hover .mce-menu-shortcut,.mce-menu-item.mce-selected .mce-menu-shortcut,.mce-menu-item:focus .mce-menu-shortcut{color:white}.mce-menu-item .mce-caret{margin-top:4px;*margin-top:3px;margin-right:6px;border-top:4px solid transparent;border-bottom:4px solid transparent;border-left:4px solid #333}.mce-menu-item.mce-selected .mce-caret,.mce-menu-item:focus .mce-caret,.mce-menu-item:hover .mce-caret{border-left-color:white}.mce-menu-align .mce-menu-shortcut{*margin-top:-2px}.mce-men
u-align .mce-menu-shortcut,.mce-menu-align .mce-caret{position:absolute;right:0}.mce-menu-item.mce-active i{visibility:visible}.mce-menu-item-normal.mce-active{background-color:#3498db}.mce-menu-item-preview.mce-active{border-left:5px solid #aaa}.mce-menu-item-normal.mce-active .mce-text{color:white}.mce-menu-item-normal.mce-active:hover .mce-text,.mce-menu-item-normal.mce-active:hover .mce-ico{color:white}.mce-menu-item-normal.mce-active:focus .mce-text,.mce-menu-item-normal.mce-active:focus .mce-ico{color:white}.mce-menu-item:hover,.mce-menu-item.mce-selected,.mce-menu-item:focus{text-decoration:none;color:white;background-color:#2d8ac7}.mce-menu-item-link{color:#093;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mce-menu-item-link b{color:#093}.mce-menu-item-ellipsis{display:block;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.mce-menu-item:hover *,.mce-menu-item.mce-selected *,.mce-menu-item:focus *{color:white}div.mce-menu .mce-menu-item-sep,.mce-menu-it
em-sep:hover{border:0;padding:0;height:1px;margin:9px 1px;overflow:hidden;background:transparent;border-bottom:1px solid rgba(0,0,0,0.1);cursor:default;filter:none}div.mce-menu .mce-menu-item b{font-weight:bold}.mce-menu-item-indent-1{padding-left:20px}.mce-menu-item-indent-2{padding-left:35px}.mce-menu-item-indent-2{padding-left:35px}.mce-menu-item-indent-3{padding-left:40px}.mce-menu-item-indent-4{padding-left:45px}.mce-menu-item-indent-5{padding-left:50px}.mce-menu-item-indent-6{padding-left:55px}.mce-menu.mce-rtl{direction:rtl}.mce-rtl .mce-menu-item{text-align:right;direction:rtl;padding:6px 12px 6px 15px}.mce-menu-align.mce-rtl .mce-menu-shortcut,.mce-menu-align.mce-rtl .mce-caret{right:auto;left:0}.mce-rtl .mce-menu-item .mce-caret{margin-left:6px;margin-right:0;border-right:4px solid #333;border-left:0}.mce-rtl .mce-menu-item.mce-selected .mce-caret,.mce-rtl .mce-menu-item:focus .mce-caret,.mce-rtl .mce-menu-item:hover .mce-caret{border-left-color:transparent;border-right-co
lor:white}.mce-throbber{position:absolute;top:0;left:0;width:100%;height:100%;opacity:.6;filter:alpha(opacity=60);zoom:1;background:#fff url('img/loader.gif') no-repeat center center}.mce-throbber-inline{position:static;height:50px}.mce-menu .mce-throbber-inline{height:25px;background-size:contain}.mce-menu{position:absolute;left:0;top:0;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;z-index:1000;padding:5px 0 5px 0;margin:-1px 0 0;min-width:160px;background:#fff;border:1px solid #989898;border:1px solid rgba(0,0,0,0.2);z-index:1002;max-height:400px;overflow:auto;overflow-x:hidden}.mce-menu i{display:none}.mce-menu-has-icons i{display:inline-block;*display:inline}.mce-menu-sub-tr-tl{margin:-6px 0 0 -1px}.mce-menu-sub-br-bl{margin:6px 0 0 -1px}.mce-menu-sub-tl-tr{margin:-6px 0 0 1px}.mce-menu-sub-bl-br{margin:6px 0 0 1px}.mce-listbox button{text-align:left;padding-right:20px;position:relative}.mce-listbox .mce-caret{position:absolute;margin-
top:-2px;right:8px;top:50%}.mce-rtl .mce-listbox .mce-caret{right:auto;left:8px}.mce-rtl .mce-listbox button{padding-right:10px;padding-left:20px}.mce-container-body .mce-resizehandle{position:absolute;right:0;bottom:0;width:16px;height:16px;visibility:visible;cursor:s-resize;margin:0}.mce-container-body .mce-resizehandle-both{cursor:se-resize}i.mce-i-resize{color:#333}.mce-selectbox{background:#fff;border:1px solid #c5c5c5}.mce-slider{border:1px solid #AAA;background:#EEE;width:100px;height:10px;position:relative;display:block}.mce-slider.mce-vertical{width:10px;height:100px}.mce-slider-handle{border:1px solid #BBB;background:#DDD;display:block;width:13px;height:13px;position:absolute;top:0;left:0;margin-left:-1px;margin-top:-2px}.mce-slider-handle:focus{background:#BBB}.mce-spacer{visibility:hidden}.mce-splitbtn .mce-open{border-left:1px solid transparent}.mce-splitbtn:hover .mce-open{border-left-color:#ccc}.mce-splitbtn button{padding-right:6px;padding-left:6px}.mce-splitbtn .mce
-open{padding-right:4px;padding-left:4px}.mce-splitbtn .mce-open.mce-active{background-color:#dbdbdb;outline:1px solid #ccc}.mce-splitbtn.mce-btn-small .mce-open{padding:0 3px 0 3px}.mce-rtl .mce-splitbtn{direction:rtl;text-align:right}.mce-rtl .mce-splitbtn button{padding-right:4px;padding-left:4px}.mce-rtl .mce-splitbtn .mce-open{border-left:0}.mce-stack-layout-item{display:block}.mce-tabs{display:block;border-bottom:1px solid #c5c5c5}.mce-tabs,.mce-tabs+.mce-container-body{background:#FFF}.mce-tab{display:inline-block;*display:inline;*zoom:1;border:1px solid #c5c5c5;border-width:0 1px 0 0;background:#ffffff;padding:8px;text-shadow:0 1px 1px rgba(255,255,255,0.75);height:13px;cursor:pointer}.mce-tab:hover{background:#FDFDFD}.mce-tab.mce-active{background:#FDFDFD;border-bottom-color:transparent;margin-bottom:-1px;height:14px}.mce-rtl .mce-tabs{text-align:right;direction:rtl}.mce-rtl .mce-tab{border-width:0 0 0 1px}.mce-textbox{background:#fff;border:1px solid #c5c5c5;display:inline
-block;-webkit-transition:border linear .2s, box-shadow linear .2s;transition:border linear .2s, box-shadow linear .2s;height:28px;resize:none;padding:0 4px 0 4px;white-space:pre-wrap;*white-space:pre;color:#333}.mce-textbox:focus,.mce-textbox.mce-focus{border-color:#3498db}.mce-placeholder .mce-textbox{color:#aaa}.mce-textbox.mce-multiline{padding:4px;height:auto}.mce-textbox.mce-disabled{color:#adadad}.mce-rtl .mce-textbox{text-align:right;direction:rtl}@font-face{font-family:'tinymce';src:url('fonts/tinymce.eot');src:url('fonts/tinymce.eot?#iefix') format('embedded-opentype'),url('fonts/tinymce.woff') format('woff'),url('fonts/tinymce.ttf') format('truetype'),url('fonts/tinymce.svg#tinymce') format('svg');font-weight:normal;font-style:normal}@font-face{font-family:'tinymce-small';src:url('fonts/tinymce-small.eot');src:url('fonts/tinymce-small.eot?#iefix') format('embedded-opentype'),url('fonts/tinymce-small.woff') format('woff'),url('fonts/tinymce-small.ttf') format('truetype'),u
rl('fonts/tinymce-small.svg#tinymce') format('svg');font-weight:normal;font-style:normal}.mce-ico{font-family:'tinymce',Arial;font-style:normal;font-weight:normal;font-variant:normal;font-size:16px;line-height:16px;speak:none;vertical-align:text-top;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;background:transparent center center;background-size:cover;width:16px;height:16px;color:#333}.mce-btn-small .mce-ico{font-family:'tinymce-small',Arial}.mce-i-save:before{content:"\e000"}.mce-i-newdocument:before{content:"\e001"}.mce-i-fullpage:before{content:"\e002"}.mce-i-alignleft:before{content:"\e003"}.mce-i-aligncenter:before{content:"\e004"}.mce-i-alignright:before{content:"\e005"}.mce-i-alignjustify:before{content:"\e006"}.mce-i-alignnone:before{content:"\e003"}.mce-i-cut:before{content:"\e007"}.mce-i-paste:before{content:"\e008"}.mce-i-searchr
eplace:before{content:"\e009"}.mce-i-bullist:before{content:"\e00a"}.mce-i-numlist:before{content:"\e00b"}.mce-i-indent:before{content:"\e00c"}.mce-i-outdent:before{content:"\e00d"}.mce-i-blockquote:before{content:"\e00e"}.mce-i-undo:before{content:"\e00f"}.mce-i-redo:before{content:"\e010"}.mce-i-link:before{content:"\e011"}.mce-i-unlink:before{content:"\e012"}.mce-i-anchor:before{content:"\e013"}.mce-i-image:before{content:"\e014"}.mce-i-media:before{content:"\e015"}.mce-i-help:before{content:"\e016"}.mce-i-code:before{content:"\e017"}.mce-i-insertdatetime:before{content:"\e018"}.mce-i-preview:before{content:"\e019"}.mce-i-forecolor:before{content:"\e01a"}.mce-i-backcolor:before{content:"\e01a"}.mce-i-table:before{content:"\e01b"}.mce-i-hr:before{content:"\e01c"}.mce-i-remov
eformat:before{content:"\e01d"}.mce-i-subscript:before{content:"\e01e"}.mce-i-superscript:before{content:"\e01f"}.mce-i-charmap:before{content:"\e020"}.mce-i-emoticons:before{content:"\e021"}.mce-i-print:before{content:"\e022"}.mce-i-fullscreen:before{content:"\e023"}.mce-i-spellchecker:before{content:"\e024"}.mce-i-nonbreaking:before{content:"\e025"}.mce-i-template:before{content:"\e026"}.mce-i-pagebreak:before{content:"\e027"}.mce-i-restoredraft:before{content:"\e028"}.mce-i-bold:before{content:"\e02a"}.mce-i-italic:before{content:"\e02b"}.mce-i-underline:before{content:"\e02c"}.mce-i-strikethrough:before{content:"\e02d"}.mce-i-visualchars:before{content:"\e02e"}.mce-i-visualblocks:before{content:"\e02e"}.mce-i-ltr:before{content:"\e02f"}.mce-i-rtl:before{content:"\e030"}.mce-i-copy:b
efore{content:"\e031"}.mce-i-resize:before{content:"\e032"}.mce-i-browse:before{content:"\e034"}.mce-i-pastetext:before{content:"\e035"}.mce-i-rotateleft:before{content:"\eaa8"}.mce-i-rotateright:before{content:"\eaa9"}.mce-i-crop:before{content:"\ee78"}.mce-i-editimage:before{content:"\e915"}.mce-i-options:before{content:"\ec6a"}.mce-i-flipv:before{content:"\eaaa"}.mce-i-fliph:before{content:"\eaac"}.mce-i-zoomin:before{content:"\eb35"}.mce-i-zoomout:before{content:"\eb36"}.mce-i-sun:before{content:"\eccc"}.mce-i-moon:before{content:"\eccd"}.mce-i-arrowleft:before{content:"\edc0"}.mce-i-arrowright:before{content:"\e93c"}.mce-i-drop:before{content:"\e935"}.mce-i-contrast:before{content:"\ecd4"}.mce-i-sharpen:before{content:"\eba7"}.mce-i-resize2:before{content:"\edf9"}.mce-i-o
rientation:before{content:"\e601"}.mce-i-invert:before{content:"\e602"}.mce-i-gamma:before{content:"\e600"}.mce-i-remove:before{content:"\ed6a"}.mce-i-tablerowprops:before{content:"\e604"}.mce-i-tablecellprops:before{content:"\e605"}.mce-i-table2:before{content:"\e606"}.mce-i-tablemergecells:before{content:"\e607"}.mce-i-tableinsertcolbefore:before{content:"\e608"}.mce-i-tableinsertcolafter:before{content:"\e609"}.mce-i-tableinsertrowbefore:before{content:"\e60a"}.mce-i-tableinsertrowafter:before{content:"\e60b"}.mce-i-tablesplitcells:before{content:"\e60d"}.mce-i-tabledelete:before{content:"\e60e"}.mce-i-tableleftheader:before{content:"\e62a"}.mce-i-tabletopheader:before{content:"\e62b"}.mce-i-tabledeleterow:before{content:"\e800"}.mce-i-tabledeletecol:before{content:"\e801"}.mce-i-codesample:before{conte
nt:"\e603"}.mce-i-fill:before{content:"\e902"}.mce-i-borderwidth:before{content:"\e903"}.mce-i-line:before{content:"\e904"}.mce-i-count:before{content:"\e905"}.mce-i-translate:before{content:"\e907"}.mce-i-drag:before{content:"\e908"}.mce-i-home:before{content:"\e90b"}.mce-i-upload:before{content:"\e914"}.mce-i-bubble:before{content:"\e91c"}.mce-i-user:before{content:"\e91d"}.mce-i-lock:before{content:"\e926"}.mce-i-unlock:before{content:"\e927"}.mce-i-settings:before{content:"\e928"}.mce-i-remove2:before{content:"\e92a"}.mce-i-menu:before{content:"\e92d"}.mce-i-warning:before{content:"\e930"}.mce-i-question:before{content:"\e931"}.mce-i-pluscircle:before{content:"\e932"}.mce-i-info:before{content:"\e933"}.mce-i-notice:before{content:"\e934"}.mce-i-arrowup:before{content:"
;\e93b"}.mce-i-arrowdown:before{content:"\e93d"}.mce-i-arrowup2:before{content:"\e93f"}.mce-i-arrowdown2:before{content:"\e940"}.mce-i-menu2:before{content:"\e941"}.mce-i-newtab:before{content:"\e961"}.mce-i-a11y:before{content:"\e900"}.mce-i-plus:before{content:"\e93a"}.mce-i-insert:before{content:"\e93a"}.mce-i-minus:before{content:"\e939"}.mce-i-books:before{content:"\e911"}.mce-i-reload:before{content:"\e906"}.mce-i-toc:before{content:"\e901"}.mce-i-checkmark:before{content:"\e033"}.mce-i-checkbox:before,.mce-i-selected:before{content:"\e033"}.mce-i-insert{font-size:14px}.mce-i-selected{visibility:hidden}i.mce-i-backcolor{text-shadow:none;background:#BBB}
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.mce-container,.mce-container *,.mce-widget,.mce-widget *,.mce-reset{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:#333;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;-webkit-tap-highlight-color:transparent;line-height:normal;font-weight:normal;text-align:left;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr;max-width:none}.mce-widget button{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.mce-container *[unselectable]{-moz-user-select:none;-webkit-user-select:none;-o-user-select:none;user-select:none}.mce-fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.mce-fade.mce-in{opacity:1}.m
ce-tinymce{visibility:inherit !important;position:relative}.mce-fullscreen{border:0;padding:0;margin:0;overflow:hidden;height:100%;z-index:100}div.mce-fullscreen{position:fixed;top:0;left:0;width:100%;height:auto}.mce-tinymce{display:block}.mce-wordcount{position:absolute;top:0;right:0;padding:8px}div.mce-edit-area{background:#FFF;filter:none}.mce-statusbar{position:relative}.mce-statusbar .mce-container-body{position:relative}.mce-fullscreen .mce-resizehandle{display:none}.mce-charmap{border-collapse:collapse}.mce-charmap td{cursor:default;border:1px solid rgba(0,0,0,0.2);width:20px;height:20px;line-height:20px;text-align:center;vertical-align:middle;padding:2px}.mce-charmap td div{text-align:center}.mce-charmap td:hover{background:#D9D9D9}.mce-grid td.mce-grid-cell div{border:1px solid #d6d6d6;width:15px;height:15px;margin:0;cursor:pointer}.mce-grid td.mce-grid-cell div:focus{border-color:#3498db}.mce-grid td.mce-grid-cell div[disabled]{cursor:not-allowed}.mce-grid{border-spacing:
2px;border-collapse:separate}.mce-grid a{display:block;border:1px solid transparent}.mce-grid a:hover,.mce-grid a:focus{border-color:#3498db}.mce-grid-border{margin:0 4px 0 4px}.mce-grid-border a{border-color:#d6d6d6;width:13px;height:13px}.mce-grid-border a:hover,.mce-grid-border a.mce-active{border-color:#3498db;background:#3498db}.mce-text-center{text-align:center}div.mce-tinymce-inline{width:100%}.mce-colorbtn-trans div{text-align:center;vertical-align:middle;font-weight:bold;font-size:20px;line-height:16px;color:#707070}.mce-monospace{font-family:"Courier New",Courier,monospace}.mce-toolbar-grp{padding:2px 0}.mce-toolbar-grp .mce-flow-layout-item{margin-bottom:0}.mce-rtl .mce-wordcount{left:0;right:auto}.mce-container b{font-weight:bold}.mce-container p{margin-bottom:5px}.mce-container a{cursor:pointer;color:#2980b9}.mce-container a:hover{text-decoration:underline}.mce-container ul{margin-left:15px}.mce-container .mce-table-striped{border-collapse:collapse;margin:10px
}.mce-container .mce-table-striped thead>tr{background-color:#fafafa}.mce-container .mce-table-striped thead>tr th{font-weight:bold}.mce-container .mce-table-striped td,.mce-container .mce-table-striped th{padding:5px}.mce-container .mce-table-striped tr:nth-child(even){background-color:#fafafa}.mce-container .mce-table-striped tbody>tr:hover{background-color:#e1e1e1}.mce-branding-powered-by{background-color:#f0f0f0;position:absolute;right:0;bottom:0;width:91px;height:9px;margin-right:-1px;margin-bottom:-1px;border:1px solid #c5c5c5;border-width:1px 1px 0 1px;padding:6px 6px 0 6px;background-image:url('data:image/gif;base64,R0lGODlhXwAJAIABAIiIiAAAACH5BAEKAAEALAAAAABfAAkAAAJxhBGpy+2PUnzqGNpmPNJqDIZSJY4m+KXLF3At2V6xPFfuvMF6J6fINTnhTr9XcaRC6pKvFYlZjDIszaXRSA3ijlXo9AlWindaldSJthJ55XAz6+ZWbVCOdojP77p8J8vlUSI4SHEnaEiYqOhARdhIWAAAOw');background-repeat:no-repeat;background-position:center center}.mce-croprect-container{position:absolute;top:0;left:0}.mce-croprect-handle{position:
absolute;top:0;left:0;width:20px;height:20px;border:2px solid white}.mce-croprect-handle-nw{border-width:2px 0 0 2px;margin:-2px 0 0 -2px;cursor:nw-resize;top:100px;left:100px}.mce-croprect-handle-ne{border-width:2px 2px 0 0;margin:-2px 0 0 -20px;cursor:ne-resize;top:100px;left:200px}.mce-croprect-handle-sw{border-width:0 0 2px 2px;margin:-20px 2px 0 -2px;cursor:sw-resize;top:200px;left:100px}.mce-croprect-handle-se{border-width:0 2px 2px 0;margin:-20px 0 0 -20px;cursor:se-resize;top:200px;left:200px}.mce-croprect-handle-move{position:absolute;cursor:move;border:0}.mce-croprect-block{opacity:.3;filter:alpha(opacity=30);zoom:1;position:absolute;background:black}.mce-croprect-handle:focus{border-color:#3498db}.mce-croprect-handle-move:focus{outline:1px solid #3498db}.mce-imagepanel{overflow:auto;background:black}.mce-imagepanel-bg{position:absolute;background:url('data:image/gif;base64,R0lGODdhDAAMAIABAMzMzP///ywAAAAADAAMAAACFoQfqYeabNyDMkBQb81Uat85nxguUAEAOw==')}.mce-imagepanel img{p
osition:absolute}.mce-imagetool.mce-btn .mce-ico{display:block;width:20px;height:20px;text-align:center;line-height:20px;font-size:20px;padding:5px}.mce-arrow-up{margin-top:12px}.mce-arrow-down{margin-top:-12px}.mce-arrow:before,.mce-arrow:after{position:absolute;left:50%;display:block;width:0;height:0;border-style:solid;border-color:transparent;content:""}.mce-arrow.mce-arrow-up:before{top:-9px;border-bottom-color:rgba(0,0,0,0.2);border-width:0 9px 9px;margin-left:-9px}.mce-arrow.mce-arrow-down:before{bottom:-9px;border-top-color:rgba(0,0,0,0.2);border-width:9px 9px 0;margin-left:-9px}.mce-arrow.mce-arrow-up:after{top:-8px;border-bottom-color:#f0f0f0;border-width:0 8px 8px;margin-left:-8px}.mce-arrow.mce-arrow-down:after{bottom:-8px;border-top-color:#f0f0f0;border-width:8px 8px 0;margin-left:-8px}.mce-arrow.mce-arrow-left:before,.mce-arrow.mce-arrow-left:after{margin:0}.mce-arrow.mce-arrow-left:before{left:8px}.mce-arrow.mce-arrow-left:after{left:9px}.mce-arrow.mce-arrow-
right:before,.mce-arrow.mce-arrow-right:after{left:auto;margin:0}.mce-arrow.mce-arrow-right:before{right:8px}.mce-arrow.mce-arrow-right:after{right:9px}.mce-arrow.mce-arrow-center.mce-arrow.mce-arrow-left:before{left:-9px;top:50%;border-right-color:rgba(0,0,0,0.2);border-width:9px 9px 9px 0;margin-top:-9px}.mce-arrow.mce-arrow-center.mce-arrow.mce-arrow-left:after{left:-8px;top:50%;border-right-color:#f0f0f0;border-width:8px 8px 8px 0;margin-top:-8px}.mce-arrow.mce-arrow-center.mce-arrow.mce-arrow-left{margin-left:12px}.mce-arrow.mce-arrow-center.mce-arrow.mce-arrow-right:before{right:-9px;top:50%;border-left-color:rgba(0,0,0,0.2);border-width:9px 0 9px 9px;margin-top:-9px}.mce-arrow.mce-arrow-center.mce-arrow.mce-arrow-right:after{right:-8px;top:50%;border-left-color:#f0f0f0;border-width:8px 0 8px 8px;margin-top:-8px}.mce-arrow.mce-arrow-center.mce-arrow.mce-arrow-right{margin-left:-14px}.mce-edit-aria-container>.mce-container-body{display:flex}.mce-edit-aria-container>.mce-c
ontainer-body .mce-edit-area{flex:1}.mce-edit-aria-container>.mce-container-body .mce-sidebar>.mce-container-body{display:flex;align-items:stretch;height:100%}.mce-edit-aria-container>.mce-container-body .mce-sidebar-panel{min-width:250px;max-width:250px;position:relative}.mce-edit-aria-container>.mce-container-body .mce-sidebar-panel>.mce-container-body{position:absolute;width:100%;height:100%;overflow:auto;top:0;left:0}.mce-sidebar-toolbar{border:0 solid rgba(0,0,0,0.2);border-left-width:1px}.mce-sidebar-toolbar .mce-btn.mce-active,.mce-sidebar-toolbar .mce-btn.mce-active:hover{border:1px solid transparent;border-color:transparent;background-color:#2d8ac7}.mce-sidebar-toolbar .mce-btn.mce-active button,.mce-sidebar-toolbar .mce-btn.mce-active:hover button,.mce-sidebar-toolbar .mce-btn.mce-active button i,.mce-sidebar-toolbar .mce-btn.mce-active:hover button i{color:#fff;text-shadow:1px 1px none}.mce-sidebar-panel{border:0 solid rgba(0,0,0,0.2);border-left-width:1px}
.mce-container,.mce-container-body{display:block}.mce-autoscroll{overflow:hidden}.mce-scrollbar{position:absolute;width:7px;height:100%;top:2px;right:2px;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-scrollbar-h{top:auto;right:auto;left:2px;bottom:2px;width:100%;height:7px}.mce-scrollbar-thumb{position:absolute;background-color:#000;border:1px solid #888;border-color:rgba(85,85,85,0.6);width:5px;height:100%}.mce-scrollbar-h .mce-scrollbar-thumb{width:100%;height:5px}.mce-scrollbar:hover,.mce-scrollbar.mce-active{background-color:#AAA;opacity:.6;filter:alpha(opacity=60);zoom:1}.mce-scroll{position:relative}.mce-panel{border:0 solid #cacaca;border:0 solid rgba(0,0,0,0.2);background-color:#f0f0f0}.mce-floatpanel{position:absolute}.mce-floatpanel.mce-fixed{position:fixed}.mce-floatpanel .mce-arrow,.mce-floatpanel .mce-arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.mce-floatpanel .mce-arrow{border-width:11px}.mce-floatpanel .mc
e-arrow:after{border-width:10px;content:""}.mce-floatpanel.mce-popover{filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;top:0;left:0;background:#FFF;border:1px solid rgba(0,0,0,0.2);border:1px solid rgba(0,0,0,0.25)}.mce-floatpanel.mce-popover.mce-bottom{margin-top:10px;*margin-top:0}.mce-floatpanel.mce-popover.mce-bottom>.mce-arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:rgba(0,0,0,0.2);border-bottom-color:rgba(0,0,0,0.25);top:-11px}.mce-floatpanel.mce-popover.mce-bottom>.mce-arrow:after{top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#FFF}.mce-floatpanel.mce-popover.mce-bottom.mce-start{margin-left:-22px}.mce-floatpanel.mce-popover.mce-bottom.mce-start>.mce-arrow{left:20px}.mce-floatpanel.mce-popover.mce-bottom.mce-end{margin-left:22px}.mce-floatpanel.mce-popover.mce-bottom.mce-end>.mce-arrow{right:10px;left:auto}.mce-fullscreen{border:0;padding:0;margin:0;overflow:hidden;heig
ht:100%}div.mce-fullscreen{position:fixed;top:0;left:0}#mce-modal-block{opacity:0;filter:alpha(opacity=0);zoom:1;position:fixed;left:0;top:0;width:100%;height:100%;background:#000}#mce-modal-block.mce-in{opacity:.3;filter:alpha(opacity=30);zoom:1}.mce-window-move{cursor:move}.mce-window{filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;background:#FFF;position:fixed;top:0;left:0;opacity:0;transform:scale(.1);transition:transform 100ms ease-in,opacity 150ms ease-in}.mce-window.mce-in{transform:scale(1);opacity:1}.mce-window-head{padding:9px 15px;border-bottom:1px solid #c5c5c5;position:relative}.mce-window-head .mce-close{position:absolute;right:0;top:0;height:38px;width:38px;text-align:center;cursor:pointer}.mce-window-head .mce-close i{color:#858585}.mce-close:hover i{color:#adadad}.mce-window-head .mce-title{line-height:20px;font-size:20px;font-weight:bold;text-rendering:optimizelegibility;padding-right:20px}.mce-window .mce-container-body{d
isplay:block}.mce-foot{display:block;background-color:#FFF;border-top:1px solid #c5c5c5}.mce-window-head .mce-dragh{position:absolute;top:0;left:0;cursor:move;width:90%;height:100%}.mce-window iframe{width:100%;height:100%}.mce-window-body .mce-listbox{border-color:#ccc}.mce-rtl .mce-window-head .mce-close{position:absolute;right:auto;left:15px}.mce-rtl .mce-window-head .mce-dragh{left:auto;right:0}.mce-rtl .mce-window-head .mce-title{direction:rtl;text-align:right}.mce-tooltip{position:absolute;padding:5px;opacity:.8;filter:alpha(opacity=80);zoom:1}.mce-tooltip-inner{font-size:11px;background-color:#000;color:white;max-width:200px;padding:5px 8px 4px 8px;text-align:center;white-space:normal}.mce-tooltip-arrow{position:absolute;width:0;height:0;line-height:0;border:5px dashed #000}.mce-tooltip-arrow-n{border-bottom-color:#000}.mce-tooltip-arrow-s{border-top-color:#000}.mce-tooltip-arrow-e{border-left-color:#000}.mce-tooltip-arrow-w{border-right-color:#000}.mce-tooltip-nw,.mce-toolti
p-sw{margin-left:-14px}.mce-tooltip-ne,.mce-tooltip-se{margin-left:14px}.mce-tooltip-n .mce-tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-nw .mce-tooltip-arrow{top:0;left:10px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-ne .mce-tooltip-arrow{top:0;right:10px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-s .mce-tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-sw .mce-tooltip-arrow{bottom:0;left:10px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-se .mce-tooltip-arrow{bottom:0;right:10px;border-top-style:solid;border-bottom:none;border-left-color:tra
nsparent;border-right-color:transparent}.mce-tooltip-e .mce-tooltip-arrow{right:0;top:50%;margin-top:-5px;border-left-style:solid;border-right:none;border-top-color:transparent;border-bottom-color:transparent}.mce-tooltip-w .mce-tooltip-arrow{left:0;top:50%;margin-top:-5px;border-right-style:solid;border-left:none;border-top-color:transparent;border-bottom-color:transparent}.mce-progress{display:inline-block;position:relative;height:20px}.mce-progress .mce-bar-container{display:inline-block;width:100px;height:100%;margin-right:8px;border:1px solid #ccc;overflow:hidden}.mce-progress .mce-text{display:inline-block;margin-top:auto;margin-bottom:auto;font-size:14px;width:40px;color:#333}.mce-bar{display:block;width:0;height:100%;background-color:#d7d7d7;-webkit-transition:width .2s ease;transition:width .2s ease}.mce-notification{position:absolute;background-color:#F0F0F0;padding:5px;margin-top:5px;border-width:1px;border-style:solid;border-color:#CCCCCC;transition:transform 100ms ease-
in,opacity 150ms ease-in;opacity:0}.mce-notification.mce-in{opacity:1}.mce-notification-success{background-color:#dff0d8;border-color:#d6e9c6}.mce-notification-info{background-color:#d9edf7;border-color:#779ECB}.mce-notification-warning{background-color:#fcf8e3;border-color:#faebcc}.mce-notification-error{background-color:#f2dede;border-color:#ebccd1}.mce-notification.mce-has-close{padding-right:15px}.mce-notification .mce-ico{margin-top:5px}.mce-notification-inner{display:inline-block;font-size:14px;margin:5px 8px 4px 8px;text-align:center;white-space:normal;color:#31708f}.mce-notification-inner a{text-decoration:underline;cursor:pointer}.mce-notification .mce-progress{margin-right:8px}.mce-notification .mce-progress .mce-text{margin-top:5px}.mce-notification *,.mce-notification .mce-progress .mce-text{color:#333333}.mce-notification .mce-progress .mce-bar-container{border-color:#CCCCCC}.mce-notification .mce-progress .mce-bar-container .mce-bar{background-color:#333333}.mce-notifi
cation-success *,.mce-notification-success .mce-progress .mce-text{color:#3c763d}.mce-notification-success .mce-progress .mce-bar-container{border-color:#d6e9c6}.mce-notification-success .mce-progress .mce-bar-container .mce-bar{background-color:#3c763d}.mce-notification-info *,.mce-notification-info .mce-progress .mce-text{color:#31708f}.mce-notification-info .mce-progress .mce-bar-container{border-color:#779ECB}.mce-notification-info .mce-progress .mce-bar-container .mce-bar{background-color:#31708f}.mce-notification-warning *,.mce-notification-warning .mce-progress .mce-text{color:#8a6d3b}.mce-notification-warning .mce-progress .mce-bar-container{border-color:#faebcc}.mce-notification-warning .mce-progress .mce-bar-container .mce-bar{background-color:#8a6d3b}.mce-notification-error *,.mce-notification-error .mce-progress .mce-text{color:#a94442}.mce-notification-error .mce-progress .mce-bar-container{border-color:#ebccd1}.mce-notification-error .mce-progress .mce-bar-container .m
ce-bar{background-color:#a94442}.mce-notification .mce-close{position:absolute;top:6px;right:8px;font-size:20px;font-weight:bold;line-height:20px;color:#858585;cursor:pointer;height:20px;overflow:hidden}.mce-abs-layout{position:relative}body .mce-abs-layout-item,.mce-abs-end{position:absolute}.mce-abs-end{width:1px;height:1px}.mce-container-body.mce-abs-layout{overflow:hidden}.mce-btn{border:1px solid #b1b1b1;border-color:transparent transparent transparent transparent;position:relative;text-shadow:0 1px 1px rgba(255,255,255,0.75);display:inline-block;*display:inline;*zoom:1;background-color:#f0f0f0}.mce-btn:hover,.mce-btn:focus{color:#333;background-color:#e3e3e3;border-color:#ccc}.mce-btn.mce-disabled button,.mce-btn.mce-disabled:hover button{cursor:default;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-btn.mce-active,.mce-btn.mce-active:hover{background-color:#dbdbdb;border-color:#ccc}.mce-btn:active{background-color:#e0e0e0;border-color:#ccc}.mce-btn button{padding:4px 8px;font
-size:14px;line-height:20px;*line-height:16px;cursor:pointer;color:#333;text-align:center;overflow:visible;-webkit-appearance:none}.mce-btn button::-moz-focus-inner{border:0;padding:0}.mce-btn i{text-shadow:1px 1px none}.mce-primary.mce-btn-has-text{min-width:50px}.mce-primary{color:#fff;border:1px solid transparent;border-color:transparent;background-color:#2d8ac7}.mce-primary:hover,.mce-primary:focus{background-color:#257cb6;border-color:transparent}.mce-primary.mce-disabled button,.mce-primary.mce-disabled:hover button{cursor:default;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-primary.mce-active,.mce-primary.mce-active:hover,.mce-primary:not(.mce-disabled):active{background-color:#206ea1}.mce-primary button,.mce-primary button i{color:#fff;text-shadow:1px 1px none}.mce-btn .mce-txt{font-size:inherit;line-height:inherit;color:inherit}.mce-btn-large button{padding:9px 14px;font-size:16px;line-height:normal}.mce-btn-large i{margin-top:2px}.mce-btn-small button{padding:1px 5px;fo
nt-size:12px;*padding-bottom:2px}.mce-btn-small i{line-height:20px;vertical-align:top;*line-height:18px}.mce-btn .mce-caret{margin-top:8px;margin-left:0}.mce-btn-small .mce-caret{margin-top:8px;margin-left:0}.mce-caret{display:inline-block;*display:inline;*zoom:1;width:0;height:0;vertical-align:top;border-top:4px solid #333;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.mce-disabled .mce-caret{border-top-color:#aaa}.mce-caret.mce-up{border-bottom:4px solid #333;border-top:0}.mce-btn-flat{border:0;background:transparent;filter:none}.mce-btn-flat:hover,.mce-btn-flat.mce-active,.mce-btn-flat:focus,.mce-btn-flat:active{border:0;background:#e6e6e6;filter:none}.mce-btn-has-text .mce-ico{padding-right:5px}.mce-rtl .mce-btn button{direction:rtl}.mce-btn-group .mce-btn{border-width:1px;margin:0;margin-left:2px}.mce-btn-group:not(:first-child){border-left:1px solid #d9d9d9;padding-left:3px;margin-left:3px}.mce-btn-group .mce-first{margin-left:0}.mce
-btn-group .mce-btn.mce-flow-layout-item{margin:0}.mce-rtl .mce-btn-group .mce-btn{margin-left:0;margin-right:2px}.mce-rtl .mce-btn-group .mce-first{margin-right:0}.mce-rtl .mce-btn-group:not(:first-child){border-left:none;border-right:1px solid #d9d9d9;padding-right:4px;margin-right:4px}.mce-checkbox{cursor:pointer}i.mce-i-checkbox{margin:0 3px 0 0;border:1px solid #c5c5c5;background-color:#f0f0f0;text-indent:-10em;*font-size:0;*line-height:0;*text-indent:0;overflow:hidden}.mce-checked i.mce-i-checkbox{color:#333;font-size:16px;line-height:16px;text-indent:0}.mce-checkbox:focus i.mce-i-checkbox,.mce-checkbox.mce-focus i.mce-i-checkbox{border:1px solid rgba(82,168,236,0.8)}.mce-checkbox.mce-disabled .mce-label,.mce-checkbox.mce-disabled i.mce-i-checkbox{color:#acacac}.mce-checkbox .mce-label{vertical-align:middle}.mce-rtl .mce-checkbox{direction:rtl;text-align:right}.mce-rtl i.mce-i-checkbox{margin:0 0 0 3px}.mce-combobox{position:relative;display:inline-block;*display:inline;*zoom:
1;*height:32px}.mce-combobox input{border:1px solid #c5c5c5;border-right-color:#c5c5c5;height:28px}.mce-combobox.mce-disabled input{color:#adadad}.mce-combobox .mce-btn{border:1px solid #c5c5c5;border-left:0;margin:0}.mce-combobox button{padding-right:8px;padding-left:8px}.mce-combobox.mce-disabled .mce-btn button{cursor:default;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-combobox .mce-status{position:absolute;right:2px;top:50%;line-height:16px;margin-top:-8px;font-size:12px;width:15px;height:15px;text-align:center;cursor:pointer}.mce-combobox.mce-has-status input{padding-right:20px}.mce-combobox.mce-has-open .mce-status{right:37px}.mce-combobox .mce-status.mce-i-warning{color:#c09853}.mce-combobox .mce-status.mce-i-checkmark{color:#468847}.mce-menu.mce-combobox-menu{border-top:0;margin-top:0;max-height:200px}.mce-menu.mce-combobox-menu .mce-menu-item{padding:4px 6px 4px 4px;font-size:11px}.mce-menu.mce-combobox-menu .mce-menu-item-sep{padding:0}.mce-menu.mce-combobox-menu .mce-
text{font-size:11px}.mce-menu.mce-combobox-menu .mce-menu-item-link,.mce-menu.mce-combobox-menu .mce-menu-item-link b{font-size:11px}.mce-menu.mce-combobox-menu .mce-text b{font-size:11px}.mce-colorbox i{border:1px solid #c5c5c5;width:14px;height:14px}.mce-colorbutton .mce-ico{position:relative}.mce-colorbutton-grid{margin:4px}.mce-colorbutton button{padding-right:6px;padding-left:6px}.mce-colorbutton .mce-preview{padding-right:3px;display:block;position:absolute;left:50%;top:50%;margin-left:-17px;margin-top:7px;background:gray;width:13px;height:2px;overflow:hidden}.mce-colorbutton.mce-btn-small .mce-preview{margin-left:-16px;padding-right:0;width:16px}.mce-colorbutton .mce-open{padding-left:4px;padding-right:4px;border-left:1px solid transparent}.mce-colorbutton:hover .mce-open{border-color:#ccc}.mce-colorbutton.mce-btn-small .mce-open{padding:0 3px 0 3px}.mce-rtl .mce-colorbutton{direction:rtl}.mce-rtl .mce-colorbutton .mce-preview{margin-left:0;padding-right:0;padding-left:3px}.m
ce-rtl .mce-colorbutton.mce-btn-small .mce-preview{margin-left:0;padding-right:0;padding-left:2px}.mce-rtl .mce-colorbutton .mce-open{padding-left:4px;padding-right:4px;border-left:0}.mce-colorpicker{position:relative;width:250px;height:220px}.mce-colorpicker-sv{position:absolute;top:0;left:0;width:90%;height:100%;border:1px solid #c5c5c5;cursor:crosshair;overflow:hidden}.mce-colorpicker-h-chunk{width:100%}.mce-colorpicker-overlay1,.mce-colorpicker-overlay2{width:100%;height:100%;position:absolute;top:0;left:0}.mce-colorpicker-overlay1{filter:progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr='#ffffff', endColorstr='#00ffffff');-ms-filter:"progid:DXImageTransform.Microsoft.gradient(GradientType=1,startColorstr='#ffffff', endColorstr='#00ffffff')";background:linear-gradient(to right, #fff, rgba(255,255,255,0))}.mce-colorpicker-overlay2{filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#00000000', endColorstr='#000000');-m
s-filter:"progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='#00000000', endColorstr='#000000')";background:linear-gradient(to bottom, rgba(0,0,0,0), #000)}.mce-colorpicker-selector1{background:none;position:absolute;width:12px;height:12px;margin:-8px 0 0 -8px;border:1px solid black;border-radius:50%}.mce-colorpicker-selector2{position:absolute;width:10px;height:10px;border:1px solid white;border-radius:50%}.mce-colorpicker-h{position:absolute;top:0;right:0;width:6.5%;height:100%;border:1px solid #c5c5c5;cursor:crosshair}.mce-colorpicker-h-marker{margin-top:-4px;position:absolute;top:0;left:-1px;width:100%;border:1px solid #333;background:#fff;height:4px;z-index:100}.mce-path{display:inline-block;*display:inline;*zoom:1;padding:8px;white-space:normal}.mce-path .mce-txt{display:inline-block;padding-right:3px}.mce-path .mce-path-body{display:inline-block}.mce-path-item{display:inline-block;*display:inline;*zoom:1;cursor:pointer;color:#333}.mce-path-item
:hover{text-decoration:underline}.mce-path-item:focus{background:#666;color:#fff}.mce-path .mce-divider{display:inline}.mce-disabled .mce-path-item{color:#aaa}.mce-rtl .mce-path{direction:rtl}.mce-fieldset{border:0 solid #9E9E9E}.mce-fieldset>.mce-container-body{margin-top:-15px}.mce-fieldset-title{margin-left:5px;padding:0 5px 0 5px}.mce-fit-layout{display:inline-block;*display:inline;*zoom:1}.mce-fit-layout-item{position:absolute}.mce-flow-layout-item{display:inline-block;*display:inline;*zoom:1}.mce-flow-layout-item{margin:2px 0 2px 2px}.mce-flow-layout-item.mce-last{margin-right:2px}.mce-flow-layout{white-space:normal}.mce-tinymce-inline .mce-flow-layout{white-space:nowrap}.mce-rtl .mce-flow-layout{text-align:right;direction:rtl}.mce-rtl .mce-flow-layout-item{margin:2px 2px 2px 0}.mce-rtl .mce-flow-layout-item.mce-last{margin-left:2px}.mce-iframe{border:0 solid rgba(0,0,0,0.2);width:100%;height:100%}.mce-infobox{display:inline-block;*display:inline;*zoom:1;text-shadow:0 1px 1
px rgba(255,255,255,0.75);overflow:hidden;border:1px solid red}.mce-infobox div{display:block;margin:5px}.mce-infobox div button{position:absolute;top:50%;right:4px;cursor:pointer;margin-top:-8px;display:none}.mce-infobox div button:focus{outline:2px solid #ccc}.mce-infobox.mce-has-help div{margin-right:25px}.mce-infobox.mce-has-help button{display:block}.mce-infobox.mce-success{background:#dff0d8;border-color:#d6e9c6}.mce-infobox.mce-success div{color:#3c763d}.mce-infobox.mce-warning{background:#fcf8e3;border-color:#faebcc}.mce-infobox.mce-warning div{color:#8a6d3b}.mce-infobox.mce-error{background:#f2dede;border-color:#ebccd1}.mce-infobox.mce-error div{color:#a94442}.mce-rtl .mce-infobox div{text-align:right;direction:rtl}.mce-label{display:inline-block;*display:inline;*zoom:1;text-shadow:0 1px 1px rgba(255,255,255,0.75);overflow:hidden}.mce-label.mce-autoscroll{overflow:auto}.mce-label.mce-disabled{color:#aaa}.mce-label.mce-multiline{white-space:pre-wrap}.mce-label.mce-success{co
lor:#468847}.mce-label.mce-warning{color:#c09853}.mce-label.mce-error{color:#b94a48}.mce-rtl .mce-label{text-align:right;direction:rtl}.mce-menubar .mce-menubtn{border-color:transparent;background:transparent;filter:none}.mce-menubar .mce-menubtn button{color:#333}.mce-menubar{border:1px solid rgba(217,217,217,0.52)}.mce-menubar .mce-menubtn button span{color:#333}.mce-menubar .mce-caret{border-top-color:#333}.mce-menubar .mce-menubtn:hover,.mce-menubar .mce-menubtn.mce-active,.mce-menubar .mce-menubtn:focus{border-color:#ccc;background:#fff;filter:none}.mce-menubtn button{color:#333}.mce-menubtn.mce-btn-small span{font-size:12px}.mce-menubtn.mce-fixed-width span{display:inline-block;overflow-x:hidden;text-overflow:ellipsis;width:90px}.mce-menubtn.mce-fixed-width.mce-btn-small span{width:70px}.mce-menubtn .mce-caret{*margin-top:6px}.mce-rtl .mce-menubtn button{direction:rtl;text-align:right}.mce-menu-item{display:block;padding:6px 15px 6px 12px;clear:both;font-weight:normal;line-hei
ght:20px;color:#333;white-space:nowrap;cursor:pointer;line-height:normal;border-left:4px solid transparent;margin-bottom:1px}.mce-menu-item .mce-ico,.mce-menu-item .mce-text{color:#333}.mce-menu-item.mce-disabled .mce-text,.mce-menu-item.mce-disabled .mce-ico{color:#adadad}.mce-menu-item:hover .mce-text,.mce-menu-item.mce-selected .mce-text,.mce-menu-item:focus .mce-text{color:white}.mce-menu-item:hover .mce-ico,.mce-menu-item.mce-selected .mce-ico,.mce-menu-item:focus .mce-ico{color:white}.mce-menu-item.mce-disabled:hover{background:#CCC}.mce-menu-shortcut{display:inline-block;color:#adadad}.mce-menu-shortcut{display:inline-block;*display:inline;*zoom:1;padding:0 15px 0 20px}.mce-menu-item:hover .mce-menu-shortcut,.mce-menu-item.mce-selected .mce-menu-shortcut,.mce-menu-item:focus .mce-menu-shortcut{color:white}.mce-menu-item .mce-caret{margin-top:4px;*margin-top:3px;margin-right:6px;border-top:4px solid transparent;border-bottom:4px solid transparent;border-left:4px solid #333}.mc
e-menu-item.mce-selected .mce-caret,.mce-menu-item:focus .mce-caret,.mce-menu-item:hover .mce-caret{border-left-color:white}.mce-menu-align .mce-menu-shortcut{*margin-top:-2px}.mce-menu-align .mce-menu-shortcut,.mce-menu-align .mce-caret{position:absolute;right:0}.mce-menu-item.mce-active i{visibility:visible}.mce-menu-item-normal.mce-active{background-color:#3498db}.mce-menu-item-preview.mce-active{border-left:5px solid #aaa}.mce-menu-item-normal.mce-active .mce-text{color:white}.mce-menu-item-normal.mce-active:hover .mce-text,.mce-menu-item-normal.mce-active:hover .mce-ico{color:white}.mce-menu-item-normal.mce-active:focus .mce-text,.mce-menu-item-normal.mce-active:focus .mce-ico{color:white}.mce-menu-item:hover,.mce-menu-item.mce-selected,.mce-menu-item:focus{text-decoration:none;color:white;background-color:#2d8ac7}.mce-menu-item-link{color:#093;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mce-menu-item-link b{color:#093}.mce-menu-item-ellipsis{display:block;text-o
verflow:ellipsis;white-space:nowrap;overflow:hidden}.mce-menu-item:hover *,.mce-menu-item.mce-selected *,.mce-menu-item:focus *{color:white}div.mce-menu .mce-menu-item-sep,.mce-menu-item-sep:hover{border:0;padding:0;height:1px;margin:9px 1px;overflow:hidden;background:transparent;border-bottom:1px solid rgba(0,0,0,0.1);cursor:default;filter:none}div.mce-menu .mce-menu-item b{font-weight:bold}.mce-menu-item-indent-1{padding-left:20px}.mce-menu-item-indent-2{padding-left:35px}.mce-menu-item-indent-2{padding-left:35px}.mce-menu-item-indent-3{padding-left:40px}.mce-menu-item-indent-4{padding-left:45px}.mce-menu-item-indent-5{padding-left:50px}.mce-menu-item-indent-6{padding-left:55px}.mce-menu.mce-rtl{direction:rtl}.mce-rtl .mce-menu-item{text-align:right;direction:rtl;padding:6px 12px 6px 15px}.mce-menu-align.mce-rtl .mce-menu-shortcut,.mce-menu-align.mce-rtl .mce-caret{right:auto;left:0}.mce-rtl .mce-menu-item .mce-caret{margin-left:6px;margin-right:0;border-right:4px solid #333;borde
r-left:0}.mce-rtl .mce-menu-item.mce-selected .mce-caret,.mce-rtl .mce-menu-item:focus .mce-caret,.mce-rtl .mce-menu-item:hover .mce-caret{border-left-color:transparent;border-right-color:white}.mce-throbber{position:absolute;top:0;left:0;width:100%;height:100%;opacity:.6;filter:alpha(opacity=60);zoom:1;background:#fff url('img/loader.gif') no-repeat center center}.mce-throbber-inline{position:static;height:50px}.mce-menu .mce-throbber-inline{height:25px;background-size:contain}.mce-menu{position:absolute;left:0;top:0;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;z-index:1000;padding:5px 0 5px 0;margin:-1px 0 0;min-width:160px;background:#fff;border:1px solid #989898;border:1px solid rgba(0,0,0,0.2);z-index:1002;max-height:400px;overflow:auto;overflow-x:hidden}.mce-menu i{display:none}.mce-menu-has-icons i{display:inline-block;*display:inline}.mce-menu-sub-tr-tl{margin:-6px 0 0 -1px}.mce-menu-sub-br-bl{margin:6px 0 0 -1px}.mce-menu-sub-tl-
tr{margin:-6px 0 0 1px}.mce-menu-sub-bl-br{margin:6px 0 0 1px}.mce-listbox button{text-align:left;padding-right:20px;position:relative}.mce-listbox .mce-caret{position:absolute;margin-top:-2px;right:8px;top:50%}.mce-rtl .mce-listbox .mce-caret{right:auto;left:8px}.mce-rtl .mce-listbox button{padding-right:10px;padding-left:20px}.mce-container-body .mce-resizehandle{position:absolute;right:0;bottom:0;width:16px;height:16px;visibility:visible;cursor:s-resize;margin:0}.mce-container-body .mce-resizehandle-both{cursor:se-resize}i.mce-i-resize{color:#333}.mce-selectbox{background:#fff;border:1px solid #c5c5c5}.mce-slider{border:1px solid #AAA;background:#EEE;width:100px;height:10px;position:relative;display:block}.mce-slider.mce-vertical{width:10px;height:100px}.mce-slider-handle{border:1px solid #BBB;background:#DDD;display:block;width:13px;height:13px;position:absolute;top:0;left:0;margin-left:-1px;margin-top:-2px}.mce-slider-handle:focus{background:#BBB}.mce-spacer{visibility:hidden}.
mce-splitbtn .mce-open{border-left:1px solid transparent}.mce-splitbtn:hover .mce-open{border-left-color:#ccc}.mce-splitbtn button{padding-right:6px;padding-left:6px}.mce-splitbtn .mce-open{padding-right:4px;padding-left:4px}.mce-splitbtn .mce-open.mce-active{background-color:#dbdbdb;outline:1px solid #ccc}.mce-splitbtn.mce-btn-small .mce-open{padding:0 3px 0 3px}.mce-rtl .mce-splitbtn{direction:rtl;text-align:right}.mce-rtl .mce-splitbtn button{padding-right:4px;padding-left:4px}.mce-rtl .mce-splitbtn .mce-open{border-left:0}.mce-stack-layout-item{display:block}.mce-tabs{display:block;border-bottom:1px solid #c5c5c5}.mce-tabs,.mce-tabs+.mce-container-body{background:#FFF}.mce-tab{display:inline-block;*display:inline;*zoom:1;border:1px solid #c5c5c5;border-width:0 1px 0 0;background:#ffffff;padding:8px;text-shadow:0 1px 1px rgba(255,255,255,0.75);height:13px;cursor:pointer}.mce-tab:hover{background:#FDFDFD}.mce-tab.mce-active{background:#FDFDFD;border-bottom-color:transparent;margin
-bottom:-1px;height:14px}.mce-rtl .mce-tabs{text-align:right;direction:rtl}.mce-rtl .mce-tab{border-width:0 0 0 1px}.mce-textbox{background:#fff;border:1px solid #c5c5c5;display:inline-block;-webkit-transition:border linear .2s, box-shadow linear .2s;transition:border linear .2s, box-shadow linear .2s;height:28px;resize:none;padding:0 4px 0 4px;white-space:pre-wrap;*white-space:pre;color:#333}.mce-textbox:focus,.mce-textbox.mce-focus{border-color:#3498db}.mce-placeholder .mce-textbox{color:#aaa}.mce-textbox.mce-multiline{padding:4px;height:auto}.mce-textbox.mce-disabled{color:#adadad}.mce-rtl .mce-textbox{text-align:right;direction:rtl}@font-face{font-family:'tinymce';src:url('fonts/tinymce.eot');src:url('fonts/tinymce.eot?#iefix') format('embedded-opentype'),url('fonts/tinymce.woff') format('woff'),url('fonts/tinymce.ttf') format('truetype'),url('fonts/tinymce.svg#tinymce') format('svg');font-weight:normal;font-style:normal}@font-face{font-family:'tinymce-small';src:url('fonts/tiny
mce-small.eot');src:url('fonts/tinymce-small.eot?#iefix') format('embedded-opentype'),url('fonts/tinymce-small.woff') format('woff'),url('fonts/tinymce-small.ttf') format('truetype'),url('fonts/tinymce-small.svg#tinymce') format('svg');font-weight:normal;font-style:normal}.mce-ico{font-family:'tinymce',Arial;font-style:normal;font-weight:normal;font-variant:normal;font-size:16px;line-height:16px;speak:none;vertical-align:text-top;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;background:transparent center center;background-size:cover;width:16px;height:16px;color:#333}.mce-btn-small .mce-ico{font-family:'tinymce-small',Arial}.mce-i-save:before{content:"\e000"}.mce-i-newdocument:before{content:"\e001"}.mce-i-fullpage:before{content:"\e002"}.mce-i-alignleft:before{content:"\e003"}.mce-i-aligncenter:before{content:"\e004"}.mce-i-alignright:before{content:"\e005"}.mce-i-alignjustify:bef
ore{content:"\e006"}.mce-i-alignnone:before{content:"\e003"}.mce-i-cut:before{content:"\e007"}.mce-i-paste:before{content:"\e008"}.mce-i-searchreplace:before{content:"\e009"}.mce-i-bullist:before{content:"\e00a"}.mce-i-numlist:before{content:"\e00b"}.mce-i-indent:before{content:"\e00c"}.mce-i-outdent:before{content:"\e00d"}.mce-i-blockquote:before{content:"\e00e"}.mce-i-undo:before{content:"\e00f"}.mce-i-redo:before{content:"\e010"}.mce-i-link:before{content:"\e011"}.mce-i-unlink:before{content:"\e012"}.mce-i-anchor:before{content:"\e013"}.mce-i-image:before{content:"\e014"}.mce-i-media:before{content:"\e015"}.mce-i-help:before{content:"\e016"}.mce-i-code:before{content:"\e017"}.mce-i-insertdatetime:before{content:"\e018"}.mce-i-preview:before{content:"\e019"}.mce-i-forecolor:
before{content:"\e01a"}.mce-i-backcolor:before{content:"\e01a"}.mce-i-table:before{content:"\e01b"}.mce-i-hr:before{content:"\e01c"}.mce-i-removeformat:before{content:"\e01d"}.mce-i-subscript:before{content:"\e01e"}.mce-i-superscript:before{content:"\e01f"}.mce-i-charmap:before{content:"\e020"}.mce-i-emoticons:before{content:"\e021"}.mce-i-print:before{content:"\e022"}.mce-i-fullscreen:before{content:"\e023"}.mce-i-spellchecker:before{content:"\e024"}.mce-i-nonbreaking:before{content:"\e025"}.mce-i-template:before{content:"\e026"}.mce-i-pagebreak:before{content:"\e027"}.mce-i-restoredraft:before{content:"\e028"}.mce-i-bold:before{content:"\e02a"}.mce-i-italic:before{content:"\e02b"}.mce-i-underline:before{content:"\e02c"}.mce-i-strikethrough:before{content:"\e02d"}.mce-i-visualchars:bef
ore{content:"\e02e"}.mce-i-visualblocks:before{content:"\e02e"}.mce-i-ltr:before{content:"\e02f"}.mce-i-rtl:before{content:"\e030"}.mce-i-copy:before{content:"\e031"}.mce-i-resize:before{content:"\e032"}.mce-i-browse:before{content:"\e034"}.mce-i-pastetext:before{content:"\e035"}.mce-i-rotateleft:before{content:"\eaa8"}.mce-i-rotateright:before{content:"\eaa9"}.mce-i-crop:before{content:"\ee78"}.mce-i-editimage:before{content:"\e915"}.mce-i-options:before{content:"\ec6a"}.mce-i-flipv:before{content:"\eaaa"}.mce-i-fliph:before{content:"\eaac"}.mce-i-zoomin:before{content:"\eb35"}.mce-i-zoomout:before{content:"\eb36"}.mce-i-sun:before{content:"\eccc"}.mce-i-moon:before{content:"\eccd"}.mce-i-arrowleft:before{content:"\edc0"}.mce-i-arrowright:before{content:"\e93c"}.mce-i-drop:be
fore{content:"\e935"}.mce-i-contrast:before{content:"\ecd4"}.mce-i-sharpen:before{content:"\eba7"}.mce-i-resize2:before{content:"\edf9"}.mce-i-orientation:before{content:"\e601"}.mce-i-invert:before{content:"\e602"}.mce-i-gamma:before{content:"\e600"}.mce-i-remove:before{content:"\ed6a"}.mce-i-tablerowprops:before{content:"\e604"}.mce-i-tablecellprops:before{content:"\e605"}.mce-i-table2:before{content:"\e606"}.mce-i-tablemergecells:before{content:"\e607"}.mce-i-tableinsertcolbefore:before{content:"\e608"}.mce-i-tableinsertcolafter:before{content:"\e609"}.mce-i-tableinsertrowbefore:before{content:"\e60a"}.mce-i-tableinsertrowafter:before{content:"\e60b"}.mce-i-tablesplitcells:before{content:"\e60d"}.mce-i-tabledelete:before{content:"\e60e"}.mce-i-tableleftheader:before{content:"\e62a"}.mce-i-tabl
etopheader:before{content:"\e62b"}.mce-i-tabledeleterow:before{content:"\e800"}.mce-i-tabledeletecol:before{content:"\e801"}.mce-i-codesample:before{content:"\e603"}.mce-i-fill:before{content:"\e902"}.mce-i-borderwidth:before{content:"\e903"}.mce-i-line:before{content:"\e904"}.mce-i-count:before{content:"\e905"}.mce-i-translate:before{content:"\e907"}.mce-i-drag:before{content:"\e908"}.mce-i-home:before{content:"\e90b"}.mce-i-upload:before{content:"\e914"}.mce-i-bubble:before{content:"\e91c"}.mce-i-user:before{content:"\e91d"}.mce-i-lock:before{content:"\e926"}.mce-i-unlock:before{content:"\e927"}.mce-i-settings:before{content:"\e928"}.mce-i-remove2:before{content:"\e92a"}.mce-i-menu:before{content:"\e92d"}.mce-i-warning:before{content:"\e930"}.mce-i-question:before{content:"\e931&
quot;}.mce-i-pluscircle:before{content:"\e932"}.mce-i-info:before{content:"\e933"}.mce-i-notice:before{content:"\e934"}.mce-i-arrowup:before{content:"\e93b"}.mce-i-arrowdown:before{content:"\e93d"}.mce-i-arrowup2:before{content:"\e93f"}.mce-i-arrowdown2:before{content:"\e940"}.mce-i-menu2:before{content:"\e941"}.mce-i-newtab:before{content:"\e961"}.mce-i-a11y:before{content:"\e900"}.mce-i-plus:before{content:"\e93a"}.mce-i-insert:before{content:"\e93a"}.mce-i-minus:before{content:"\e939"}.mce-i-books:before{content:"\e911"}.mce-i-reload:before{content:"\e906"}.mce-i-toc:before{content:"\e901"}.mce-i-checkmark:before{content:"\e033"}.mce-i-checkbox:before,.mce-i-selected:before{content:"\e033"}.mce-i-insert{font-size:14px}.mce-i-selected{visibility:hidden}i.mce-i-backcolor{text-shadow:none;background:#BBB}
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcethemesinlitethemejs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/themes/inlite/theme.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/themes/inlite/theme.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/themes/inlite/theme.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -81,58 +81,71 @@
</span><span class="cx" style="display: block; padding: 0 10px"> define(id, [], function () { return ref; });
</span><span class="cx" style="display: block; padding: 0 10px"> };
</span><span class="cx" style="display: block; padding: 0 10px"> /*jsc
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-["tinymce/inlite/Theme","global!tinymce.ThemeManager","global!tinymce.util.Delay","tinymce/inlite/ui/Panel","tinymce/inlite/ui/Buttons","tinymce/inlite/core/SkinLoader","tinymce/inlite/core/SelectionMatcher","tinymce/inlite/core/ElementMatcher","tinymce/inlite/core/Matcher","tinymce/inlite/alien/Arr","tinymce/inlite/alien/EditorSettings","tinymce/inlite/core/PredicateId","global!tinymce.util.Tools","global!tinymce.ui.Factory","global!tinymce.DOM","tinymce/inlite/ui/Toolbar","tinymce/inlite/ui/Forms","tinymce/inlite/core/Measure","tinymce/inlite/core/Layout","tinymce/inlite/alien/Type","tinymce/inlite/file/Conversions","tinymce/inlite/file/Picker","tinymce/inlite/core
/Actions","global!tinymce.EditorManager","global!tinymce.util.Promise","tinymce/inlite/alien/Uuid","tinymce/inlite/alien/Unlink","tinymce/inlite/core/UrlType","global!tinymce.geom.Rect","tinymce/inlite/core/Convert","tinymce/inlite/alien/Bookmark","global!tinymce.dom.TreeWalker","global!tinymce.dom.RangeUtils"]
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+["tinymce.themes.inlite.Theme","tinymce.core.ThemeManager","tinymce.core.ui.Api","tinymce.core.util.Delay","tinymce.themes.inlite.alien.Arr","tinymce.themes.inlite.alien.EditorSettings","tinymce.themes.inlite.core.ElementMatcher","tinymce.themes.inlite.core.Matcher","tinymce.themes.inlite.core.PredicateId","tinymce.themes.inlite.core.SelectionMatcher","tinymce.themes.inlite.core.SkinLoader","tinymce.themes.inlite.ui.Buttons","tinymce.themes.inlite.ui.Panel","global!tinymce.util.Tools.resolve","tinymce.themes.inlite.alien.Type","tinymce.themes.inlite.core.Measure","tinymce.core.util.Tools","tinymce.core.EditorManager","tinymce.core.dom.DOMUtils","tinymce.core.ui.Factory","tinymce.themes.i
nlite.ui.Toolbar","tinymce.themes.inlite.ui.Forms","tinymce.themes.inlite.core.Layout","tinymce.themes.inlite.file.Conversions","tinymce.themes.inlite.file.Picker","tinymce.themes.inlite.core.Actions","tinymce.core.geom.Rect","tinymce.themes.inlite.core.Convert","tinymce.core.util.Promise","tinymce.themes.inlite.alien.Uuid","tinymce.themes.inlite.alien.Unlink","tinymce.themes.inlite.core.UrlType","tinymce.themes.inlite.alien.Bookmark","tinymce.core.dom.TreeWalker","tinymce.core.dom.RangeUtils"]
</ins><span class="cx" style="display: block; padding: 0 10px"> jsc*/
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-defineGlobal("global!tinymce.ThemeManager", tinymce.ThemeManager);
-defineGlobal("global!tinymce.util.Delay", tinymce.util.Delay);
-defineGlobal("global!tinymce.util.Tools", tinymce.util.Tools);
-defineGlobal("global!tinymce.ui.Factory", tinymce.ui.Factory);
-defineGlobal("global!tinymce.DOM", tinymce.DOM);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+defineGlobal("global!tinymce.util.Tools.resolve", tinymce.util.Tools.resolve);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Type.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ResolveGlobal.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce/inlite/alien/Type', [
-], function () {
- var isType = function (type) {
- return function (value) {
- return typeof value === type;
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ThemeManager',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.ThemeManager');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isArray = function (value) {
- return Array.isArray(value);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isNull = function (value) {
- return value === null;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Api',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.ui.Api');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isObject = function (predicate) {
- return function (value) {
- return !isNull(value) && !isArray(value) && predicate(value);
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- isString: isType("string"),
- isNumber: isType("number"),
- isBoolean: isType("boolean"),
- isFunction: isType("function"),
- isObject: isObject(isType("object")),
- isNull: isNull,
- isArray: isArray
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.Delay',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.util.Delay');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Toolbar.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Arr.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="cx" style="display: block; padding: 0 10px"> * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -141,114 +154,149 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce/inlite/ui/Toolbar', [
- 'global!tinymce.util.Tools',
- 'global!tinymce.ui.Factory',
- 'tinymce/inlite/alien/Type'
-], function (Tools, Factory, Type) {
- var getSelectorStateResult = function (itemName, item) {
- var result = function (selector, handler) {
- return {
- selector: selector,
- handler: handler
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.inlite.alien.Arr',
+ [
+ ],
+ function () {
+ var flatten = function (arr) {
+ return arr.reduce(function (results, item) {
+ return Array.isArray(item) ? results.concat(flatten(item)) : results.concat(item);
+ }, []);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var activeHandler = function(state) {
- item.active(state);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ flatten: flatten
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var disabledHandler = function (state) {
- item.disabled(state);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Type.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (item.settings.stateSelector) {
- return result(item.settings.stateSelector, activeHandler);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.inlite.alien.Type',
+ [
+ ],
+ function () {
+ var isType = function (type) {
+ return function (value) {
+ return typeof value === type;
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (item.settings.disabledStateSelector) {
- return result(item.settings.disabledStateSelector, disabledHandler);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isArray = function (value) {
+ return Array.isArray(value);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isNull = function (value) {
+ return value === null;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var bindSelectorChanged = function (editor, itemName, item) {
- return function () {
- var result = getSelectorStateResult(itemName, item);
- if (result !== null) {
- editor.selection.selectorChanged(result.selector, result.handler);
- }
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isObject = function (predicate) {
+ return function (value) {
+ return !isNull(value) && !isArray(value) && predicate(value);
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var itemsToArray = function (items) {
- if (Type.isArray(items)) {
- return items;
- } else if (Type.isString(items)) {
- return items.split(/[ ,]/);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ isString: isType("string"),
+ isNumber: isType("number"),
+ isBoolean: isType("boolean"),
+ isFunction: isType("function"),
+ isObject: isObject(isType("object")),
+ isNull: isNull,
+ isArray: isArray
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return [];
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * EditorSettings.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var create = function (editor, name, items) {
- var toolbarItems = [], buttonGroup;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.inlite.alien.EditorSettings',
+ [
+ 'tinymce.themes.inlite.alien.Type'
+ ],
+ function (Type) {
+ var validDefaultOrDie = function (value, predicate) {
+ if (predicate(value)) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!items) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ throw new Error('Default value doesn\'t match requested type.');
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(itemsToArray(items), function(item) {
- var itemName;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getByTypeOr = function (predicate) {
+ return function (editor, name, defaultValue) {
+ var settings = editor.settings;
+ validDefaultOrDie(defaultValue, predicate);
+ return name in settings && predicate(settings[name]) ? settings[name] : defaultValue;
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (item == '|') {
- buttonGroup = null;
- } else {
- if (Factory.has(item)) {
- item = {type: item};
- toolbarItems.push(item);
- buttonGroup = null;
- } else {
- if (editor.buttons[item]) {
- if (!buttonGroup) {
- buttonGroup = {type: 'buttongroup', items: []};
- toolbarItems.push(buttonGroup);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var splitNoEmpty = function (str, delim) {
+ return str.split(delim).filter(function (item) {
+ return item.length > 0;
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- itemName = item;
- item = editor.buttons[itemName];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var itemsToArray = function (value, defaultValue) {
+ var stringToItemsArray = function (value) {
+ return typeof value === 'string' ? splitNoEmpty(value, /[ ,]/) : value;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof item == 'function') {
- item = item();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var boolToItemsArray = function (value, defaultValue) {
+ return value === false ? [] : defaultValue;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- item.type = item.type || 'button';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (Type.isArray(value)) {
+ return value;
+ } else if (Type.isString(value)) {
+ return stringToItemsArray(value);
+ } else if (Type.isBoolean(value)) {
+ return boolToItemsArray(value, defaultValue);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- item = Factory.create(item);
- item.on('postRender', bindSelectorChanged(editor, itemName, item));
- buttonGroup.items.push(item);
- }
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return defaultValue;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Factory.create({
- type: 'toolbar',
- layout: 'flow',
- name: name,
- items: toolbarItems
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getToolbarItemsOr = function (predicate) {
+ return function (editor, name, defaultValue) {
+ var value = name in editor.settings ? editor.settings[name] : defaultValue;
+ validDefaultOrDie(defaultValue, predicate);
+ return itemsToArray(value, defaultValue);
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- create: create
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ // TODO: Add Option based getString, getBool if merged with core
+ getStringOr: getByTypeOr(Type.isString),
+ getBoolOr: getByTypeOr(Type.isBoolean),
+ getNumberOr: getByTypeOr(Type.isNumber),
+ getHandlerOr: getByTypeOr(Type.isFunction),
+ getToolbarItemsOr: getToolbarItemsOr(Type.isArray)
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-defineGlobal("global!tinymce.util.Promise", tinymce.util.Promise);
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Uuid.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Matcher.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="cx" style="display: block; padding: 0 10px"> * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -257,33 +305,124 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.inlite.core.Matcher',
+ [
+ ],
+ function () {
+ // result :: String, Rect -> Matcher.result
+ var result = function (id, rect) {
+ return {
+ id: id,
+ rect: rect
+ };
+ };
+
+ // match :: Editor, [(Editor -> Matcher.result | Null)] -> Matcher.result | Null
+ var match = function (editor, matchers) {
+ for (var i = 0; i < matchers.length; i++) {
+ var f = matchers[i];
+ var result = f(editor);
+
+ if (result) {
+ return result;
+ }
+ }
+
+ return null;
+ };
+
+ return {
+ match: match,
+ result: result
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Generates unique ids this is the same as in core but since
- * it's not exposed as a global we can't access it.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/inlite/alien/Uuid", [
-], function() {
- var count = 0;
</del><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var seed = function () {
- var rnd = function () {
- return Math.round(Math.random() * 0xFFFFFFFF).toString(36);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.DOMUtils',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.dom.DOMUtils');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return 's' + Date.now().toString(36) + rnd() + rnd() + rnd();
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var uuid = function (prefix) {
- return prefix + (count++) + seed();
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.geom.Rect',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.geom.Rect');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- uuid: uuid
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Convert.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.inlite.core.Convert',
+ [
+ ],
+ function () {
+ var fromClientRect = function (clientRect) {
+ return {
+ x: clientRect.left,
+ y: clientRect.top,
+ w: clientRect.width,
+ h: clientRect.height
+ };
+ };
+
+ var toClientRect = function (geomRect) {
+ return {
+ left: geomRect.x,
+ top: geomRect.y,
+ width: geomRect.w,
+ height: geomRect.h,
+ right: geomRect.x + geomRect.w,
+ bottom: geomRect.y + geomRect.h
+ };
+ };
+
+ return {
+ fromClientRect: fromClientRect,
+ toClientRect: toClientRect
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Bookmark.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Measure.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="cx" style="display: block; padding: 0 10px"> * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -292,216 +431,333 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce/inlite/alien/Bookmark', [
-], function () {
- /**
- * Returns a range bookmark. This will convert indexed bookmarks into temporary span elements with
- * index 0 so that they can be restored properly after the DOM has been modified. Text bookmarks will not have spans
- * added to them since they can be restored after a dom operation.
- *
- * So this: <p><b>|</b><b>|</b></p>
- * becomes: <p><b><span data-mce-type="bookmark">|</span></b><b data-mce-type="bookmark">|</span></b></p>
- *
- * @param {DOMRange} rng DOM Range to get bookmark on.
- * @return {Object} Bookmark object.
- */
- var create = function (dom, rng) {
- var bookmark = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.inlite.core.Measure',
+ [
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.core.geom.Rect',
+ 'tinymce.themes.inlite.core.Convert'
+ ],
+ function (DOMUtils, Rect, Convert) {
+ var toAbsolute = function (rect) {
+ var vp = DOMUtils.DOM.getViewPort();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setupEndPoint(start) {
- var offsetNode, container, offset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ x: rect.x + vp.x,
+ y: rect.y + vp.y,
+ w: rect.w,
+ h: rect.h
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = rng[start ? 'startContainer' : 'endContainer'];
- offset = rng[start ? 'startOffset' : 'endOffset'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var measureElement = function (elm) {
+ var clientRect = elm.getBoundingClientRect();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (container.nodeType == 1) {
- offsetNode = dom.create('span', {'data-mce-type': 'bookmark'});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return toAbsolute({
+ x: clientRect.left,
+ y: clientRect.top,
+ w: Math.max(elm.clientWidth, elm.offsetWidth),
+ h: Math.max(elm.clientHeight, elm.offsetHeight)
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (container.hasChildNodes()) {
- offset = Math.min(offset, container.childNodes.length - 1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getElementRect = function (editor, elm) {
+ return measureElement(elm);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (start) {
- container.insertBefore(offsetNode, container.childNodes[offset]);
- } else {
- dom.insertAfter(offsetNode, container.childNodes[offset]);
- }
- } else {
- container.appendChild(offsetNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getPageAreaRect = function (editor) {
+ return measureElement(editor.getElement().ownerDocument.body);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = offsetNode;
- offset = 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getContentAreaRect = function (editor) {
+ return measureElement(editor.getContentAreaContainer() || editor.getBody());
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bookmark[start ? 'startContainer' : 'endContainer'] = container;
- bookmark[start ? 'startOffset' : 'endOffset'] = offset;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getSelectionRect = function (editor) {
+ var clientRect = editor.selection.getBoundingClientRect();
+ return clientRect ? toAbsolute(Convert.fromClientRect(clientRect)) : null;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- setupEndPoint(true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ getElementRect: getElementRect,
+ getPageAreaRect: getPageAreaRect,
+ getContentAreaRect: getContentAreaRect,
+ getSelectionRect: getSelectionRect
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!rng.collapsed) {
- setupEndPoint();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ElementMatcher.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return bookmark;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.inlite.core.ElementMatcher',
+ [
+ 'tinymce.themes.inlite.core.Matcher',
+ 'tinymce.themes.inlite.core.Measure'
+ ],
+ function (Matcher, Measure) {
+ // element :: Element, [PredicateId] -> (Editor -> Matcher.result | Null)
+ var element = function (element, predicateIds) {
+ return function (editor) {
+ for (var i = 0; i < predicateIds.length; i++) {
+ if (predicateIds[i].predicate(element)) {
+ return Matcher.result(predicateIds[i].id, Measure.getElementRect(editor, element));
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Moves the selection to the current bookmark and removes any selection container wrappers.
- *
- * @param {Object} bookmark Bookmark object to move selection to.
- */
- var resolve = function (dom, bookmark) {
- function restoreEndPoint(start) {
- var container, offset, node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function nodeIndex(container) {
- var node = container.parentNode.firstChild, idx = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // parent :: [Elements], [PredicateId] -> (Editor -> Matcher.result | Null)
+ var parent = function (elements, predicateIds) {
+ return function (editor) {
+ for (var i = 0; i < elements.length; i++) {
+ for (var x = 0; x < predicateIds.length; x++) {
+ if (predicateIds[x].predicate(elements[i])) {
+ return Matcher.result(predicateIds[x].id, Measure.getElementRect(editor, elements[i]));
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (node) {
- if (node == container) {
- return idx;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Skip data-mce-type=bookmark nodes
- if (node.nodeType != 1 || node.getAttribute('data-mce-type') != 'bookmark') {
- idx++;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ element: element,
+ parent: parent
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.nextSibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return -1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.Tools',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.util.Tools');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = node = bookmark[start ? 'startContainer' : 'endContainer'];
- offset = bookmark[start ? 'startOffset' : 'endOffset'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * PredicateId.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!container) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.inlite.core.PredicateId',
+ [
+ 'tinymce.core.util.Tools'
+ ],
+ function (Tools) {
+ var create = function (id, predicate) {
+ return {
+ id: id,
+ predicate: predicate
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (container.nodeType == 1) {
- offset = nodeIndex(container);
- container = container.parentNode;
- dom.remove(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // fromContextToolbars :: [ContextToolbar] -> [PredicateId]
+ var fromContextToolbars = function (toolbars) {
+ return Tools.map(toolbars, function (toolbar) {
+ return create(toolbar.id, toolbar.predicate);
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bookmark[start ? 'startContainer' : 'endContainer'] = container;
- bookmark[start ? 'startOffset' : 'endOffset'] = offset;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ create: create,
+ fromContextToolbars: fromContextToolbars
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- restoreEndPoint(true);
- restoreEndPoint();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * SelectionMatcher.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var rng = dom.createRng();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.inlite.core.SelectionMatcher',
+ [
+ 'tinymce.themes.inlite.core.Matcher',
+ 'tinymce.themes.inlite.core.Measure'
+ ],
+ function (Matcher, Measure) {
+ // textSelection :: String -> (Editor -> Matcher.result | Null)
+ var textSelection = function (id) {
+ return function (editor) {
+ if (!editor.selection.isCollapsed()) {
+ return Matcher.result(id, Measure.getSelectionRect(editor));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng.setStart(bookmark.startContainer, bookmark.startOffset);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (bookmark.endContainer) {
- rng.setEnd(bookmark.endContainer, bookmark.endOffset);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // emptyTextBlock :: [Elements], String -> (Editor -> Matcher.result | Null)
+ var emptyTextBlock = function (elements, id) {
+ return function (editor) {
+ var i, textBlockElementsMap = editor.schema.getTextBlockElements();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return rng;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0; i < elements.length; i++) {
+ if (elements[i].nodeName === 'TABLE') {
+ return null;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- create: create,
- resolve: resolve
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0; i < elements.length; i++) {
+ if (elements[i].nodeName in textBlockElementsMap) {
+ if (editor.dom.isEmpty(elements[i])) {
+ return Matcher.result(id, Measure.getSelectionRect(editor));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-defineGlobal("global!tinymce.dom.TreeWalker", tinymce.dom.TreeWalker);
-defineGlobal("global!tinymce.dom.RangeUtils", tinymce.dom.RangeUtils);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ textSelection: textSelection,
+ emptyTextBlock: emptyTextBlock
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Unlink.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ResolveGlobal.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.EditorManager',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.EditorManager');
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Unlink implementation that doesn't leave partial links for example it would produce:
- * a[b<a href="x">c]d</a>e -> a[bc]de
- * instead of:
- * a[b<a href="x">c]d</a>e -> a[bc]<a href="x">d</a>e
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * SkinLoader.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/inlite/alien/Unlink", [
- 'tinymce/inlite/alien/Bookmark',
- 'global!tinymce.util.Tools',
- 'global!tinymce.dom.TreeWalker',
- 'global!tinymce.dom.RangeUtils'
-], function (Bookmark, Tools, TreeWalker, RangeUtils) {
- var getSelectedElements = function (rootElm, startNode, endNode) {
- var walker, node, elms = [];
</del><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- walker = new TreeWalker(startNode, rootElm);
- for (node = startNode; node; node = walker.next()) {
- if (node.nodeType === 1) {
- elms.push(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.inlite.core.SkinLoader',
+ [
+ 'tinymce.core.EditorManager',
+ 'tinymce.core.dom.DOMUtils'
+ ],
+ function (EditorManager, DOMUtils) {
+ var fireSkinLoaded = function (editor, callback) {
+ var done = function () {
+ editor._skinLoaded = true;
+ editor.fire('SkinLoaded');
+ callback();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node === endNode) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.initialized) {
+ done();
+ } else {
+ editor.on('init', done);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return elms;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var urlFromName = function (name) {
+ var prefix = EditorManager.baseURL + '/skins/';
+ return name ? prefix + name : prefix + 'lightgray';
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var unwrapElements = function (editor, elms) {
- var bookmark, dom, selection;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var toAbsoluteUrl = function (editor, url) {
+ return editor.documentBaseURI.toAbsolute(url);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom = editor.dom;
- selection = editor.selection;
- bookmark = Bookmark.create(dom, selection.getRng());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var load = function (editor, callback) {
+ var settings = editor.settings;
+ var skinUrl = settings.skin_url ? toAbsoluteUrl(editor, settings.skin_url) : urlFromName(settings.skin);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(elms, function (elm) {
- editor.dom.remove(elm, true);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var done = function () {
+ fireSkinLoaded(editor, callback);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- selection.setRng(Bookmark.resolve(dom, bookmark));
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOMUtils.DOM.styleSheetLoader.load(skinUrl + '/skin.min.css', done);
+ editor.contentCSS.push(skinUrl + '/content.inline.min.css');
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isLink = function (elm) {
- return elm.nodeName === 'A' && elm.hasAttribute('href');
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ load: load
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getParentAnchorOrSelf = function (dom, elm) {
- var anchorElm = dom.getParent(elm, isLink);
- return anchorElm ? anchorElm : elm;
- };
</del><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getSelectedAnchors = function (editor) {
- var startElm, endElm, rootElm, anchorElms, selection, dom, rng;
</del><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- selection = editor.selection;
- dom = editor.dom;
- rng = selection.getRng();
- startElm = getParentAnchorOrSelf(dom, RangeUtils.getNode(rng.startContainer, rng.startOffset));
- endElm = RangeUtils.getNode(rng.endContainer, rng.endOffset);
- rootElm = editor.getBody();
- anchorElms = Tools.grep(getSelectedElements(rootElm, startElm, endElm), isLink);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return anchorElms;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Factory',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.ui.Factory');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var unlinkSelection = function (editor) {
- unwrapElements(editor, getSelectedAnchors(editor));
- };
-
- return {
- unlinkSelection: unlinkSelection
- };
-});
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Actions.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Toolbar.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="cx" style="display: block; padding: 0 10px"> * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -510,105 +766,131 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce/inlite/core/Actions', [
- 'tinymce/inlite/alien/Uuid',
- 'tinymce/inlite/alien/Unlink'
-], function (Uuid, Unlink) {
- var createTableHtml = function (cols, rows) {
- var x, y, html;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.inlite.ui.Toolbar',
+ [
+ 'tinymce.core.util.Tools',
+ 'tinymce.core.ui.Factory',
+ 'tinymce.themes.inlite.alien.Type'
+ ],
+ function (Tools, Factory, Type) {
+ var getSelectorStateResult = function (itemName, item) {
+ var result = function (selector, handler) {
+ return {
+ selector: selector,
+ handler: handler
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- html = '<table data-mce-id="mce" style="width: 100%">';
- html += '<tbody>';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var activeHandler = function (state) {
+ item.active(state);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (y = 0; y < rows; y++) {
- html += '<tr>';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var disabledHandler = function (state) {
+ item.disabled(state);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (x = 0; x < cols; x++) {
- html += '<td><br></td>';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (item.settings.stateSelector) {
+ return result(item.settings.stateSelector, activeHandler);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- html += '</tr>';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (item.settings.disabledStateSelector) {
+ return result(item.settings.disabledStateSelector, disabledHandler);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- html += '</tbody>';
- html += '</table>';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return html;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var bindSelectorChanged = function (editor, itemName, item) {
+ return function () {
+ var result = getSelectorStateResult(itemName, item);
+ if (result !== null) {
+ editor.selection.selectorChanged(result.selector, result.handler);
+ }
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getInsertedElement = function (editor) {
- var elms = editor.dom.select('*[data-mce-id]');
- return elms[0];
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var itemsToArray = function (items) {
+ if (Type.isArray(items)) {
+ return items;
+ } else if (Type.isString(items)) {
+ return items.split(/[ ,]/);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var insertTable = function (editor, cols, rows) {
- editor.undoManager.transact(function () {
- var tableElm, cellElm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return [];
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.insertContent(createTableHtml(cols, rows));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var create = function (editor, name, items) {
+ var toolbarItems = [], buttonGroup;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tableElm = getInsertedElement(editor);
- tableElm.removeAttribute('data-mce-id');
- cellElm = editor.dom.select('td,th', tableElm);
- editor.selection.setCursorLocation(cellElm[0], 0);
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!items) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var formatBlock = function (editor, formatName) {
- editor.execCommand('FormatBlock', false, formatName);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(itemsToArray(items), function (item) {
+ var itemName;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var insertBlob = function (editor, base64, blob) {
- var blobCache, blobInfo;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (item == '|') {
+ buttonGroup = null;
+ } else {
+ if (editor.buttons[item]) {
+ if (!buttonGroup) {
+ buttonGroup = { type: 'buttongroup', items: [] };
+ toolbarItems.push(buttonGroup);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- blobCache = editor.editorUpload.blobCache;
- blobInfo = blobCache.create(Uuid.uuid('mceu'), blob, base64);
- blobCache.add(blobInfo);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ itemName = item;
+ item = editor.buttons[itemName];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.insertContent(editor.dom.createHTML('img', {src: blobInfo.blobUri()}));
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof item == 'function') {
+ item = item();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var collapseSelectionToEnd = function (editor) {
- editor.selection.collapse(false);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ item.type = item.type || 'button';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var unlink = function (editor) {
- editor.focus();
- Unlink.unlinkSelection(editor);
- collapseSelectionToEnd(editor);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ item = Factory.create(item);
+ item.on('postRender', bindSelectorChanged(editor, itemName, item));
+ buttonGroup.items.push(item);
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var changeHref = function (editor, elm, url) {
- editor.focus();
- editor.dom.setAttrib(elm, 'href', url);
- collapseSelectionToEnd(editor);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Factory.create({
+ type: 'toolbar',
+ layout: 'flow',
+ name: name,
+ items: toolbarItems
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var insertLink = function (editor, url) {
- editor.execCommand('mceInsertLink', false, {href: url});
- collapseSelectionToEnd(editor);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ create: create
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var updateOrInsertLink = function (editor, url) {
- var elm = editor.dom.getParent(editor.selection.getStart(), 'a[href]');
- elm ? changeHref(editor, elm, url) : insertLink(editor, url);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var createLink = function (editor, url) {
- url.trim().length === 0 ? unlink(editor) : updateOrInsertLink(editor, url);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.Promise',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.util.Promise');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- insertTable: insertTable,
- formatBlock: formatBlock,
- insertBlob: insertBlob,
- createLink: createLink,
- unlink: unlink
- };
-});
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * UrlType.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Uuid.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="cx" style="display: block; padding: 0 10px"> * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -617,26 +899,37 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce/inlite/core/UrlType', [
-], function () {
- var isDomainLike = function (href) {
- return /^www\.|\.(com|org|edu|gov|uk|net|ca|de|jp|fr|au|us|ru|ch|it|nl|se|no|es|mil)$/i.test(href.trim());
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Generates unique ids this is the same as in core but since
+ * it's not exposed as a global we can't access it.
+ */
+define(
+ "tinymce.themes.inlite.alien.Uuid",
+ [
+ ],
+ function () {
+ var count = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isAbsolute = function (href) {
- return /^https?:\/\//.test(href.trim());
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var seed = function () {
+ var rnd = function () {
+ return Math.round(Math.random() * 0xFFFFFFFF).toString(36);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- isDomainLike: isDomainLike,
- isAbsolute: isAbsolute
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return 's' + Date.now().toString(36) + rnd() + rnd() + rnd();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var uuid = function (prefix) {
+ return prefix + (count++) + seed();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ uuid: uuid
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Forms.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Bookmark.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="cx" style="display: block; padding: 0 10px"> * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -645,166 +938,173 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce/inlite/ui/Forms', [
- 'global!tinymce.util.Tools',
- 'global!tinymce.ui.Factory',
- 'global!tinymce.util.Promise',
- 'tinymce/inlite/core/Actions',
- 'tinymce/inlite/core/UrlType'
-], function (Tools, Factory, Promise, Actions, UrlType) {
- var focusFirstTextBox = function (form) {
- form.find('textbox').eq(0).each(function (ctrl) {
- ctrl.focus();
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.inlite.alien.Bookmark',
+ [
+ ],
+ function () {
+ /**
+ * Returns a range bookmark. This will convert indexed bookmarks into temporary span elements with
+ * index 0 so that they can be restored properly after the DOM has been modified. Text bookmarks will not have spans
+ * added to them since they can be restored after a dom operation.
+ *
+ * So this: <p><b>|</b><b>|</b></p>
+ * becomes: <p><b><span data-mce-type="bookmark">|</span></b><b data-mce-type="bookmark">|</span></b></p>
+ *
+ * @param {DOMRange} rng DOM Range to get bookmark on.
+ * @return {Object} Bookmark object.
+ */
+ var create = function (dom, rng) {
+ var bookmark = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var createForm = function (name, spec) {
- var form = Factory.create(
- Tools.extend({
- type: 'form',
- layout: 'flex',
- direction: 'row',
- padding: 5,
- name: name,
- spacing: 3
- }, spec)
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setupEndPoint(start) {
+ var offsetNode, container, offset;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- form.on('show', function () {
- focusFirstTextBox(form);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = rng[start ? 'startContainer' : 'endContainer'];
+ offset = rng[start ? 'startOffset' : 'endOffset'];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return form;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (container.nodeType == 1) {
+ offsetNode = dom.create('span', { 'data-mce-type': 'bookmark' });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var toggleVisibility = function (ctrl, state) {
- return state ? ctrl.show() : ctrl.hide();
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (container.hasChildNodes()) {
+ offset = Math.min(offset, container.childNodes.length - 1);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var askAboutPrefix = function (editor, href) {
- return new Promise(function (resolve) {
- editor.windowManager.confirm(
- 'The URL you entered seems to be an external link. Do you want to add the required http:// prefix?',
- function (result) {
- var output = result === true ? 'http://' + href : href;
- resolve(output);
- }
- );
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (start) {
+ container.insertBefore(offsetNode, container.childNodes[offset]);
+ } else {
+ dom.insertAfter(offsetNode, container.childNodes[offset]);
+ }
+ } else {
+ container.appendChild(offsetNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var convertLinkToAbsolute = function (editor, href) {
- return !UrlType.isAbsolute(href) && UrlType.isDomainLike(href) ? askAboutPrefix(editor, href) : Promise.resolve(href);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = offsetNode;
+ offset = 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var createQuickLinkForm = function (editor, hide) {
- var attachState = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bookmark[start ? 'startContainer' : 'endContainer'] = container;
+ bookmark[start ? 'startOffset' : 'endOffset'] = offset;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var unlink = function () {
- editor.focus();
- Actions.unlink(editor);
- hide();
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ setupEndPoint(true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var onChangeHandler = function (e) {
- var meta = e.meta;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!rng.collapsed) {
+ setupEndPoint();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (meta && meta.attach) {
- attachState = {
- href: this.value(),
- attach: meta.attach
- };
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return bookmark;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var onShowHandler = function (e) {
- if (e.control === this) {
- var elm, linkurl = '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Moves the selection to the current bookmark and removes any selection container wrappers.
+ *
+ * @param {Object} bookmark Bookmark object to move selection to.
+ */
+ var resolve = function (dom, bookmark) {
+ function restoreEndPoint(start) {
+ var container, offset, node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elm = editor.dom.getParent(editor.selection.getStart(), 'a[href]');
- if (elm) {
- linkurl = editor.dom.getAttrib(elm, 'href');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function nodeIndex(container) {
+ var node = container.parentNode.firstChild, idx = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.fromJSON({
- linkurl: linkurl
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (node) {
+ if (node == container) {
+ return idx;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- toggleVisibility(this.find('#unlink'), elm);
- this.find('#linkurl')[0].focus();
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Skip data-mce-type=bookmark nodes
+ if (node.nodeType != 1 || node.getAttribute('data-mce-type') != 'bookmark') {
+ idx++;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return createForm('quicklink', {
- items: [
- {type: 'button', name: 'unlink', icon: 'unlink', onclick: unlink, tooltip: 'Remove link'},
- {type: 'filepicker', name: 'linkurl', placeholder: 'Paste or type a link', filetype: 'file', onchange: onChangeHandler},
- {type: 'button', icon: 'checkmark', subtype: 'primary', tooltip: 'Ok', onclick: 'submit'}
- ],
- onshow: onShowHandler,
- onsubmit: function (e) {
- convertLinkToAbsolute(editor, e.data.linkurl).then(function (url) {
- editor.undoManager.transact(function () {
- if (url === attachState.href) {
- attachState.attach();
- attachState = {};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node.nextSibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Actions.createLink(editor, url);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return -1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- hide();
- });
- }
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = node = bookmark[start ? 'startContainer' : 'endContainer'];
+ offset = bookmark[start ? 'startOffset' : 'endOffset'];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- createQuickLinkForm: createQuickLinkForm
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!container) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-defineGlobal("global!tinymce.geom.Rect", tinymce.geom.Rect);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (container.nodeType == 1) {
+ offset = nodeIndex(container);
+ container = container.parentNode;
+ dom.remove(node);
+ }
+
+ bookmark[start ? 'startContainer' : 'endContainer'] = container;
+ bookmark[start ? 'startOffset' : 'endOffset'] = offset;
+ }
+
+ restoreEndPoint(true);
+ restoreEndPoint();
+
+ var rng = dom.createRng();
+
+ rng.setStart(bookmark.startContainer, bookmark.startOffset);
+
+ if (bookmark.endContainer) {
+ rng.setEnd(bookmark.endContainer, bookmark.endOffset);
+ }
+
+ return rng;
+ };
+
+ return {
+ create: create,
+ resolve: resolve
+ };
+ }
+);
+
+
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Convert.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ResolveGlobal.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce/inlite/core/Convert', [
-], function () {
- var fromClientRect = function (clientRect) {
- return {
- x: clientRect.left,
- y: clientRect.top,
- w: clientRect.width,
- h: clientRect.height
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.TreeWalker',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.dom.TreeWalker');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var toClientRect = function (geomRect) {
- return {
- left: geomRect.x,
- top: geomRect.y,
- width: geomRect.w,
- height: geomRect.h,
- right: geomRect.x + geomRect.w,
- bottom: geomRect.y + geomRect.h
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- fromClientRect: fromClientRect,
- toClientRect: toClientRect
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.RangeUtils',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.dom.RangeUtils');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Measure.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Unlink.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="cx" style="display: block; padding: 0 10px"> * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -813,60 +1113,87 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce/inlite/core/Measure', [
- 'global!tinymce.DOM',
- 'global!tinymce.geom.Rect',
- 'tinymce/inlite/core/Convert'
-], function (DOM, Rect, Convert) {
- var toAbsolute = function (rect) {
- var vp = DOM.getViewPort();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Unlink implementation that doesn't leave partial links for example it would produce:
+ * a[b<a href="x">c]d</a>e -> a[bc]de
+ * instead of:
+ * a[b<a href="x">c]d</a>e -> a[bc]<a href="x">d</a>e
+ */
+define(
+ "tinymce.themes.inlite.alien.Unlink",
+ [
+ 'tinymce.themes.inlite.alien.Bookmark',
+ 'tinymce.core.util.Tools',
+ 'tinymce.core.dom.TreeWalker',
+ 'tinymce.core.dom.RangeUtils'
+ ],
+ function (Bookmark, Tools, TreeWalker, RangeUtils) {
+ var getSelectedElements = function (rootElm, startNode, endNode) {
+ var walker, node, elms = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- x: rect.x + vp.x,
- y: rect.y + vp.y,
- w: rect.w,
- h: rect.h
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ walker = new TreeWalker(startNode, rootElm);
+ for (node = startNode; node; node = walker.next()) {
+ if (node.nodeType === 1) {
+ elms.push(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var measureElement = function (elm) {
- var clientRect = elm.getBoundingClientRect();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node === endNode) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return toAbsolute({
- x: clientRect.left,
- y: clientRect.top,
- w: Math.max(elm.clientWidth, elm.offsetWidth),
- h: Math.max(elm.clientHeight, elm.offsetHeight)
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return elms;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getElementRect = function (editor, elm) {
- return measureElement(elm);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var unwrapElements = function (editor, elms) {
+ var bookmark, dom, selection;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getPageAreaRect = function (editor) {
- return measureElement(editor.getElement().ownerDocument.body);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom = editor.dom;
+ selection = editor.selection;
+ bookmark = Bookmark.create(dom, selection.getRng());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getContentAreaRect = function (editor) {
- return measureElement(editor.getContentAreaContainer() || editor.getBody());
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(elms, function (elm) {
+ editor.dom.remove(elm, true);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getSelectionRect = function (editor) {
- var clientRect = editor.selection.getBoundingClientRect();
- return clientRect ? toAbsolute(Convert.fromClientRect(clientRect)) : null;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ selection.setRng(Bookmark.resolve(dom, bookmark));
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- getElementRect: getElementRect,
- getPageAreaRect: getPageAreaRect,
- getContentAreaRect: getContentAreaRect,
- getSelectionRect: getSelectionRect
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isLink = function (elm) {
+ return elm.nodeName === 'A' && elm.hasAttribute('href');
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getParentAnchorOrSelf = function (dom, elm) {
+ var anchorElm = dom.getParent(elm, isLink);
+ return anchorElm ? anchorElm : elm;
+ };
+
+ var getSelectedAnchors = function (editor) {
+ var startElm, endElm, rootElm, anchorElms, selection, dom, rng;
+
+ selection = editor.selection;
+ dom = editor.dom;
+ rng = selection.getRng();
+ startElm = getParentAnchorOrSelf(dom, RangeUtils.getNode(rng.startContainer, rng.startOffset));
+ endElm = RangeUtils.getNode(rng.endContainer, rng.endOffset);
+ rootElm = editor.getBody();
+ anchorElms = Tools.grep(getSelectedElements(rootElm, startElm, endElm), isLink);
+
+ return anchorElms;
+ };
+
+ var unlinkSelection = function (editor) {
+ unwrapElements(editor, getSelectedAnchors(editor));
+ };
+
+ return {
+ unlinkSelection: unlinkSelection
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Layout.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Actions.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="cx" style="display: block; padding: 0 10px"> * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -875,99 +1202,109 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce/inlite/core/Layout', [
- 'global!tinymce.geom.Rect',
- 'tinymce/inlite/core/Convert'
-], function (Rect, Convert) {
- var result = function (rect, position) {
- return {
- rect: rect,
- position: position
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.inlite.core.Actions',
+ [
+ 'tinymce.themes.inlite.alien.Uuid',
+ 'tinymce.themes.inlite.alien.Unlink'
+ ],
+ function (Uuid, Unlink) {
+ var createTableHtml = function (cols, rows) {
+ var x, y, html;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var moveTo = function (rect, toRect) {
- return {x: toRect.x, y: toRect.y, w: rect.w, h: rect.h};
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ html = '<table data-mce-id="mce" style="width: 100%">';
+ html += '<tbody>';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var calcByPositions = function (testPositions1, testPositions2, targetRect, contentAreaRect, panelRect) {
- var relPos, relRect, outputPanelRect;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (y = 0; y < rows; y++) {
+ html += '<tr>';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- relPos = Rect.findBestRelativePosition(panelRect, targetRect, contentAreaRect, testPositions1);
- targetRect = Rect.clamp(targetRect, contentAreaRect);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (x = 0; x < cols; x++) {
+ html += '<td><br></td>';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (relPos) {
- relRect = Rect.relativePosition(panelRect, targetRect, relPos);
- outputPanelRect = moveTo(panelRect, relRect);
- return result(outputPanelRect, relPos);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ html += '</tr>';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- targetRect = Rect.intersect(contentAreaRect, targetRect);
- if (targetRect) {
- relPos = Rect.findBestRelativePosition(panelRect, targetRect, contentAreaRect, testPositions2);
- if (relPos) {
- relRect = Rect.relativePosition(panelRect, targetRect, relPos);
- outputPanelRect = moveTo(panelRect, relRect);
- return result(outputPanelRect, relPos);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ html += '</tbody>';
+ html += '</table>';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- outputPanelRect = moveTo(panelRect, targetRect);
- return result(outputPanelRect, relPos);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return html;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getInsertedElement = function (editor) {
+ var elms = editor.dom.select('*[data-mce-id]');
+ return elms[0];
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var calcInsert = function (targetRect, contentAreaRect, panelRect) {
- return calcByPositions(
- ['cr-cl', 'cl-cr'],
- ['bc-tc', 'bl-tl', 'br-tr'],
- targetRect,
- contentAreaRect,
- panelRect
- );
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var insertTable = function (editor, cols, rows) {
+ editor.undoManager.transact(function () {
+ var tableElm, cellElm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var calc = function (targetRect, contentAreaRect, panelRect) {
- return calcByPositions(
- ['tc-bc', 'bc-tc', 'tl-bl', 'bl-tl', 'tr-br', 'br-tr'],
- ['bc-tc', 'bl-tl', 'br-tr'],
- targetRect,
- contentAreaRect,
- panelRect
- );
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.insertContent(createTableHtml(cols, rows));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var userConstrain = function (handler, targetRect, contentAreaRect, panelRect) {
- var userConstrainedPanelRect;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ tableElm = getInsertedElement(editor);
+ tableElm.removeAttribute('data-mce-id');
+ cellElm = editor.dom.select('td,th', tableElm);
+ editor.selection.setCursorLocation(cellElm[0], 0);
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof handler === 'function') {
- userConstrainedPanelRect = handler({
- elementRect: Convert.toClientRect(targetRect),
- contentAreaRect: Convert.toClientRect(contentAreaRect),
- panelRect: Convert.toClientRect(panelRect)
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var formatBlock = function (editor, formatName) {
+ editor.execCommand('FormatBlock', false, formatName);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Convert.fromClientRect(userConstrainedPanelRect);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var insertBlob = function (editor, base64, blob) {
+ var blobCache, blobInfo;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return panelRect;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ blobCache = editor.editorUpload.blobCache;
+ blobInfo = blobCache.create(Uuid.uuid('mceu'), blob, base64);
+ blobCache.add(blobInfo);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var defaultHandler = function (rects) {
- return rects.panelRect;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.insertContent(editor.dom.createHTML('img', { src: blobInfo.blobUri() }));
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- calcInsert: calcInsert,
- calc: calc,
- userConstrain: userConstrain,
- defaultHandler: defaultHandler
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var collapseSelectionToEnd = function (editor) {
+ editor.selection.collapse(false);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var unlink = function (editor) {
+ editor.focus();
+ Unlink.unlinkSelection(editor);
+ collapseSelectionToEnd(editor);
+ };
+
+ var changeHref = function (editor, elm, url) {
+ editor.focus();
+ editor.dom.setAttrib(elm, 'href', url);
+ collapseSelectionToEnd(editor);
+ };
+
+ var insertLink = function (editor, url) {
+ editor.execCommand('mceInsertLink', false, { href: url });
+ collapseSelectionToEnd(editor);
+ };
+
+ var updateOrInsertLink = function (editor, url) {
+ var elm = editor.dom.getParent(editor.selection.getStart(), 'a[href]');
+ elm ? changeHref(editor, elm, url) : insertLink(editor, url);
+ };
+
+ var createLink = function (editor, url) {
+ url.trim().length === 0 ? unlink(editor) : updateOrInsertLink(editor, url);
+ };
+
+ return {
+ insertTable: insertTable,
+ formatBlock: formatBlock,
+ insertBlob: insertBlob,
+ createLink: createLink,
+ unlink: unlink
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * EditorSettings.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * UrlType.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="cx" style="display: block; padding: 0 10px"> * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -976,71 +1313,30 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce/inlite/alien/EditorSettings', [
- 'tinymce/inlite/alien/Type'
-], function (Type) {
- var validDefaultOrDie = function (value, predicate) {
- if (predicate(value)) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.inlite.core.UrlType',
+ [
+ ],
+ function () {
+ var isDomainLike = function (href) {
+ return /^www\.|\.(com|org|edu|gov|uk|net|ca|de|jp|fr|au|us|ru|ch|it|nl|se|no|es|mil)$/i.test(href.trim());
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- throw new Error('Default value doesn\'t match requested type.');
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isAbsolute = function (href) {
+ return /^https?:\/\//.test(href.trim());
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getByTypeOr = function (predicate) {
- return function (editor, name, defaultValue) {
- var settings = editor.settings;
- validDefaultOrDie(defaultValue, predicate);
- return name in settings && predicate(settings[name]) ? settings[name] : defaultValue;
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ isDomainLike: isDomainLike,
+ isAbsolute: isAbsolute
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var splitNoEmpty = function (str, delim) {
- return str.split(delim).filter(function (item) {
- return item.length > 0;
- });
- };
</del><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var itemsToArray = function (value, defaultValue) {
- var stringToItemsArray = function (value) {
- return typeof value === 'string' ? splitNoEmpty(value, /[ ,]/) : value;
- };
</del><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var boolToItemsArray = function (value, defaultValue) {
- return value === false ? [ ] : defaultValue;
- };
-
- if (Type.isArray(value)) {
- return value;
- } else if (Type.isString(value)) {
- return stringToItemsArray(value);
- } else if (Type.isBoolean(value)) {
- return boolToItemsArray(value, defaultValue);
- }
-
- return defaultValue;
- };
-
- var getToolbarItemsOr = function (predicate) {
- return function (editor, name, defaultValue) {
- var value = name in editor.settings ? editor.settings[name] : defaultValue;
- validDefaultOrDie(defaultValue, predicate);
- return itemsToArray(value, defaultValue);
- };
- };
-
- return {
- // TODO: Add Option based getString, getBool if merged with core
- getStringOr: getByTypeOr(Type.isString),
- getBoolOr: getByTypeOr(Type.isBoolean),
- getNumberOr: getByTypeOr(Type.isNumber),
- getHandlerOr: getByTypeOr(Type.isFunction),
- getToolbarItemsOr: getToolbarItemsOr(Type.isArray)
- };
-});
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Panel.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Forms.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="cx" style="display: block; padding: 0 10px"> * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1049,240 +1345,236 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce/inlite/ui/Panel', [
- 'global!tinymce.util.Tools',
- 'global!tinymce.ui.Factory',
- 'global!tinymce.DOM',
- 'tinymce/inlite/ui/Toolbar',
- 'tinymce/inlite/ui/Forms',
- 'tinymce/inlite/core/Measure',
- 'tinymce/inlite/core/Layout',
- 'tinymce/inlite/alien/EditorSettings'
-], function (Tools, Factory, DOM, Toolbar, Forms, Measure, Layout, EditorSettings) {
- return function () {
- var DEFAULT_TEXT_SELECTION_ITEMS = ['bold', 'italic', '|', 'quicklink', 'h2', 'h3', 'blockquote'];
- var DEFAULT_INSERT_TOOLBAR_ITEMS = ['quickimage', 'quicktable'];
- var panel, currentRect;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.inlite.ui.Forms',
+ [
+ 'tinymce.core.util.Tools',
+ 'tinymce.core.ui.Factory',
+ 'tinymce.core.util.Promise',
+ 'tinymce.themes.inlite.core.Actions',
+ 'tinymce.themes.inlite.core.UrlType'
+ ],
+ function (Tools, Factory, Promise, Actions, UrlType) {
+ var focusFirstTextBox = function (form) {
+ form.find('textbox').eq(0).each(function (ctrl) {
+ ctrl.focus();
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var createToolbars = function (editor, toolbars) {
- return Tools.map(toolbars, function (toolbar) {
- return Toolbar.create(editor, toolbar.id, toolbar.items);
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createForm = function (name, spec) {
+ var form = Factory.create(
+ Tools.extend({
+ type: 'form',
+ layout: 'flex',
+ direction: 'row',
+ padding: 5,
+ name: name,
+ spacing: 3
+ }, spec)
+ );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getTextSelectionToolbarItems = function (editor) {
- return EditorSettings.getToolbarItemsOr(editor, 'selection_toolbar', DEFAULT_TEXT_SELECTION_ITEMS);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ form.on('show', function () {
+ focusFirstTextBox(form);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getInsertToolbarItems = function (editor) {
- return EditorSettings.getToolbarItemsOr(editor, 'insert_toolbar', DEFAULT_INSERT_TOOLBAR_ITEMS);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return form;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var hasToolbarItems = function (toolbar) {
- return toolbar.items().length > 0;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var toggleVisibility = function (ctrl, state) {
+ return state ? ctrl.show() : ctrl.hide();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var create = function (editor, toolbars) {
- var items = createToolbars(editor, toolbars).concat([
- Toolbar.create(editor, 'text', getTextSelectionToolbarItems(editor)),
- Toolbar.create(editor, 'insert', getInsertToolbarItems(editor)),
- Forms.createQuickLinkForm(editor, hide)
- ]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var askAboutPrefix = function (editor, href) {
+ return new Promise(function (resolve) {
+ editor.windowManager.confirm(
+ 'The URL you entered seems to be an external link. Do you want to add the required http:// prefix?',
+ function (result) {
+ var output = result === true ? 'http://' + href : href;
+ resolve(output);
+ }
+ );
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Factory.create({
- type: 'floatpanel',
- role: 'dialog',
- classes: 'tinymce tinymce-inline arrow',
- ariaLabel: 'Inline toolbar',
- layout: 'flex',
- direction: 'column',
- align: 'stretch',
- autohide: false,
- autofix: true,
- fixed: true,
- border: 1,
- items: Tools.grep(items, hasToolbarItems),
- oncancel: function() {
- editor.focus();
- }
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var convertLinkToAbsolute = function (editor, href) {
+ return !UrlType.isAbsolute(href) && UrlType.isDomainLike(href) ? askAboutPrefix(editor, href) : Promise.resolve(href);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var showPanel = function (panel) {
- if (panel) {
- panel.show();
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createQuickLinkForm = function (editor, hide) {
+ var attachState = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var movePanelTo = function (panel, pos) {
- panel.moveTo(pos.x, pos.y);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var unlink = function () {
+ editor.focus();
+ Actions.unlink(editor);
+ hide();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var togglePositionClass = function (panel, relPos) {
- relPos = relPos ? relPos.substr(0, 2) : '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var onChangeHandler = function (e) {
+ var meta = e.meta;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each({
- t: 'down',
- b: 'up',
- c: 'center'
- }, function(cls, pos) {
- panel.classes.toggle('arrow-' + cls, pos === relPos.substr(0, 1));
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (meta && meta.attach) {
+ attachState = {
+ href: this.value(),
+ attach: meta.attach
+ };
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (relPos === 'cr') {
- panel.classes.toggle('arrow-left', true);
- panel.classes.toggle('arrow-right', false);
- } else if (relPos === 'cl') {
- panel.classes.toggle('arrow-left', true);
- panel.classes.toggle('arrow-right', true);
- } else {
- Tools.each({
- l: 'left',
- r: 'right'
- }, function(cls, pos) {
- panel.classes.toggle('arrow-' + cls, pos === relPos.substr(1, 1));
- });
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var onShowHandler = function (e) {
+ if (e.control === this) {
+ var elm, linkurl = '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var showToolbar = function (panel, id) {
- var toolbars = panel.items().filter('#' + id);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elm = editor.dom.getParent(editor.selection.getStart(), 'a[href]');
+ if (elm) {
+ linkurl = editor.dom.getAttrib(elm, 'href');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (toolbars.length > 0) {
- toolbars[0].show();
- panel.reflow();
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.fromJSON({
+ linkurl: linkurl
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ toggleVisibility(this.find('#unlink'), elm);
+ this.find('#linkurl')[0].focus();
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var repositionPanelAt = function (panel, id, editor, targetRect) {
- var contentAreaRect, panelRect, result, userConstainHandler;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return createForm('quicklink', {
+ items: [
+ { type: 'button', name: 'unlink', icon: 'unlink', onclick: unlink, tooltip: 'Remove link' },
+ { type: 'filepicker', name: 'linkurl', placeholder: 'Paste or type a link', filetype: 'file', onchange: onChangeHandler },
+ { type: 'button', icon: 'checkmark', subtype: 'primary', tooltip: 'Ok', onclick: 'submit' }
+ ],
+ onshow: onShowHandler,
+ onsubmit: function (e) {
+ convertLinkToAbsolute(editor, e.data.linkurl).then(function (url) {
+ editor.undoManager.transact(function () {
+ if (url === attachState.href) {
+ attachState.attach();
+ attachState = {};
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- userConstainHandler = EditorSettings.getHandlerOr(editor, 'inline_toolbar_position_handler', Layout.defaultHandler);
- contentAreaRect = Measure.getContentAreaRect(editor);
- panelRect = DOM.getRect(panel.getEl());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Actions.createLink(editor, url);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (id === 'insert') {
- result = Layout.calcInsert(targetRect, contentAreaRect, panelRect);
- } else {
- result = Layout.calc(targetRect, contentAreaRect, panelRect);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ hide();
+ });
+ }
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (result) {
- panelRect = result.rect;
- currentRect = targetRect;
- movePanelTo(panel, Layout.userConstrain(userConstainHandler, targetRect, contentAreaRect, panelRect));
- togglePositionClass(panel, result.position);
- return true;
- } else {
- return false;
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ createQuickLinkForm: createQuickLinkForm
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var showPanelAt = function (panel, id, editor, targetRect) {
- showPanel(panel);
- panel.items().hide();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Layout.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!showToolbar(panel, id)) {
- hide(panel);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.inlite.core.Layout',
+ [
+ 'tinymce.core.geom.Rect',
+ 'tinymce.themes.inlite.core.Convert'
+ ],
+ function (Rect, Convert) {
+ var result = function (rect, position) {
+ return {
+ rect: rect,
+ position: position
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (repositionPanelAt(panel, id, editor, targetRect) === false) {
- hide(panel);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var moveTo = function (rect, toRect) {
+ return { x: toRect.x, y: toRect.y, w: rect.w, h: rect.h };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var hasFormVisible = function () {
- return panel.items().filter('form:visible').length > 0;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var calcByPositions = function (testPositions1, testPositions2, targetRect, contentAreaRect, panelRect) {
+ var relPos, relRect, outputPanelRect;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var showForm = function (editor, id) {
- if (panel) {
- panel.items().hide();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ relPos = Rect.findBestRelativePosition(panelRect, targetRect, contentAreaRect, testPositions1);
+ targetRect = Rect.clamp(targetRect, contentAreaRect);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!showToolbar(panel, id)) {
- hide(panel);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (relPos) {
+ relRect = Rect.relativePosition(panelRect, targetRect, relPos);
+ outputPanelRect = moveTo(panelRect, relRect);
+ return result(outputPanelRect, relPos);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var contentAreaRect, panelRect, result, userConstainHandler;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ targetRect = Rect.intersect(contentAreaRect, targetRect);
+ if (targetRect) {
+ relPos = Rect.findBestRelativePosition(panelRect, targetRect, contentAreaRect, testPositions2);
+ if (relPos) {
+ relRect = Rect.relativePosition(panelRect, targetRect, relPos);
+ outputPanelRect = moveTo(panelRect, relRect);
+ return result(outputPanelRect, relPos);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- showPanel(panel);
- panel.items().hide();
- showToolbar(panel, id);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ outputPanelRect = moveTo(panelRect, targetRect);
+ return result(outputPanelRect, relPos);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- userConstainHandler = EditorSettings.getHandlerOr(editor, 'inline_toolbar_position_handler', Layout.defaultHandler);
- contentAreaRect = Measure.getContentAreaRect(editor);
- panelRect = DOM.getRect(panel.getEl());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- result = Layout.calc(currentRect, contentAreaRect, panelRect);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var calcInsert = function (targetRect, contentAreaRect, panelRect) {
+ return calcByPositions(
+ ['cr-cl', 'cl-cr'],
+ ['bc-tc', 'bl-tl', 'br-tr'],
+ targetRect,
+ contentAreaRect,
+ panelRect
+ );
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (result) {
- panelRect = result.rect;
- movePanelTo(panel, Layout.userConstrain(userConstainHandler, currentRect, contentAreaRect, panelRect));
- togglePositionClass(panel, result.position);
- }
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var calc = function (targetRect, contentAreaRect, panelRect) {
+ return calcByPositions(
+ ['tc-bc', 'bc-tc', 'tl-bl', 'bl-tl', 'tr-br', 'br-tr'],
+ ['bc-tc', 'bl-tl', 'br-tr'],
+ targetRect,
+ contentAreaRect,
+ panelRect
+ );
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var show = function (editor, id, targetRect, toolbars) {
- if (!panel) {
- panel = create(editor, toolbars);
- panel.renderTo(document.body).reflow().moveTo(targetRect.x, targetRect.y);
- editor.nodeChanged();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var userConstrain = function (handler, targetRect, contentAreaRect, panelRect) {
+ var userConstrainedPanelRect;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- showPanelAt(panel, id, editor, targetRect);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof handler === 'function') {
+ userConstrainedPanelRect = handler({
+ elementRect: Convert.toClientRect(targetRect),
+ contentAreaRect: Convert.toClientRect(contentAreaRect),
+ panelRect: Convert.toClientRect(panelRect)
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var reposition = function (editor, id, targetRect) {
- if (panel) {
- repositionPanelAt(panel, id, editor, targetRect);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Convert.fromClientRect(userConstrainedPanelRect);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var hide = function () {
- if (panel) {
- panel.hide();
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return panelRect;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var focus = function () {
- if (panel) {
- panel.find('toolbar:visible').eq(0).each(function (item) {
- item.focus(true);
- });
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var defaultHandler = function (rects) {
+ return rects.panelRect;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var remove = function () {
- if (panel) {
- panel.remove();
- panel = null;
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ calcInsert: calcInsert,
+ calc: calc,
+ userConstrain: userConstrain,
+ defaultHandler: defaultHandler
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var inForm = function () {
- return panel && panel.visible() && hasFormVisible();
- };
-
- return {
- show: show,
- showForm: showForm,
- reposition: reposition,
- inForm: inForm,
- hide: hide,
- focus: focus,
- remove: remove
- };
- };
-});
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Conversions.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Panel.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="cx" style="display: block; padding: 0 10px"> * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1291,209 +1583,244 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce/inlite/file/Conversions', [
- 'global!tinymce.util.Promise'
-], function (Promise) {
- var blobToBase64 = function (blob) {
- return new Promise(function(resolve) {
- var reader = new FileReader();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.inlite.ui.Panel',
+ [
+ 'tinymce.core.util.Tools',
+ 'tinymce.core.ui.Factory',
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.themes.inlite.ui.Toolbar',
+ 'tinymce.themes.inlite.ui.Forms',
+ 'tinymce.themes.inlite.core.Measure',
+ 'tinymce.themes.inlite.core.Layout',
+ 'tinymce.themes.inlite.alien.EditorSettings'
+ ],
+ function (Tools, Factory, DOMUtils, Toolbar, Forms, Measure, Layout, EditorSettings) {
+ return function () {
+ var DEFAULT_TEXT_SELECTION_ITEMS = ['bold', 'italic', '|', 'quicklink', 'h2', 'h3', 'blockquote'];
+ var DEFAULT_INSERT_TOOLBAR_ITEMS = ['quickimage', 'quicktable'];
+ var panel, currentRect;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- reader.onloadend = function() {
- resolve(reader.result.split(',')[1]);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createToolbars = function (editor, toolbars) {
+ return Tools.map(toolbars, function (toolbar) {
+ return Toolbar.create(editor, toolbar.id, toolbar.items);
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- reader.readAsDataURL(blob);
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getTextSelectionToolbarItems = function (editor) {
+ return EditorSettings.getToolbarItemsOr(editor, 'selection_toolbar', DEFAULT_TEXT_SELECTION_ITEMS);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- blobToBase64: blobToBase64
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getInsertToolbarItems = function (editor) {
+ return EditorSettings.getToolbarItemsOr(editor, 'insert_toolbar', DEFAULT_INSERT_TOOLBAR_ITEMS);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var hasToolbarItems = function (toolbar) {
+ return toolbar.items().length > 0;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var create = function (editor, toolbars) {
+ var items = createToolbars(editor, toolbars).concat([
+ Toolbar.create(editor, 'text', getTextSelectionToolbarItems(editor)),
+ Toolbar.create(editor, 'insert', getInsertToolbarItems(editor)),
+ Forms.createQuickLinkForm(editor, hide)
+ ]);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Picker.js
- *
- * Released under LGPL License.
- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Factory.create({
+ type: 'floatpanel',
+ role: 'dialog',
+ classes: 'tinymce tinymce-inline arrow',
+ ariaLabel: 'Inline toolbar',
+ layout: 'flex',
+ direction: 'column',
+ align: 'stretch',
+ autohide: false,
+ autofix: true,
+ fixed: true,
+ border: 1,
+ items: Tools.grep(items, hasToolbarItems),
+ oncancel: function () {
+ editor.focus();
+ }
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce/inlite/file/Picker', [
- 'global!tinymce.util.Promise'
-], function (Promise) {
- var pickFile = function () {
- return new Promise(function (resolve) {
- var fileInput;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var showPanel = function (panel) {
+ if (panel) {
+ panel.show();
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- fileInput = document.createElement("input");
- fileInput.type = "file";
- fileInput.style.position = 'fixed';
- fileInput.style.left = 0;
- fileInput.style.top = 0;
- fileInput.style.opacity = 0.001;
- document.body.appendChild(fileInput);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var movePanelTo = function (panel, pos) {
+ panel.moveTo(pos.x, pos.y);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- fileInput.onchange = function(e) {
- resolve(Array.prototype.slice.call(e.target.files));
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var togglePositionClass = function (panel, relPos) {
+ relPos = relPos ? relPos.substr(0, 2) : '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- fileInput.click();
- fileInput.parentNode.removeChild(fileInput);
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each({
+ t: 'down',
+ b: 'up',
+ c: 'center'
+ }, function (cls, pos) {
+ panel.classes.toggle('arrow-' + cls, pos === relPos.substr(0, 1));
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- pickFile: pickFile
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (relPos === 'cr') {
+ panel.classes.toggle('arrow-left', true);
+ panel.classes.toggle('arrow-right', false);
+ } else if (relPos === 'cl') {
+ panel.classes.toggle('arrow-left', true);
+ panel.classes.toggle('arrow-right', true);
+ } else {
+ Tools.each({
+ l: 'left',
+ r: 'right'
+ }, function (cls, pos) {
+ panel.classes.toggle('arrow-' + cls, pos === relPos.substr(1, 1));
+ });
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var showToolbar = function (panel, id) {
+ var toolbars = panel.items().filter('#' + id);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (toolbars.length > 0) {
+ toolbars[0].show();
+ panel.reflow();
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Buttons.js
- *
- * Released under LGPL License.
- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce/inlite/ui/Buttons', [
- 'tinymce/inlite/ui/Panel',
- 'tinymce/inlite/file/Conversions',
- 'tinymce/inlite/file/Picker',
- 'tinymce/inlite/core/Actions'
-], function (Panel, Conversions, Picker, Actions) {
- var addHeaderButtons = function (editor) {
- var formatBlock = function (name) {
- return function () {
- Actions.formatBlock(editor, name);
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var repositionPanelAt = function (panel, id, editor, targetRect) {
+ var contentAreaRect, panelRect, result, userConstainHandler;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var i = 1; i < 6; i++) {
- var name = 'h' + i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ userConstainHandler = EditorSettings.getHandlerOr(editor, 'inline_toolbar_position_handler', Layout.defaultHandler);
+ contentAreaRect = Measure.getContentAreaRect(editor);
+ panelRect = DOMUtils.DOM.getRect(panel.getEl());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addButton(name, {
- text: name.toUpperCase(),
- tooltip: 'Heading ' + i,
- stateSelector: name,
- onclick: formatBlock(name),
- onPostRender: function () {
- // TODO: Remove this hack that produces bold H1-H6 when we have proper icons
- var span = this.getEl().firstChild.firstChild;
- span.style.fontWeight = 'bold';
- }
- });
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (id === 'insert') {
+ result = Layout.calcInsert(targetRect, contentAreaRect, panelRect);
+ } else {
+ result = Layout.calc(targetRect, contentAreaRect, panelRect);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var addToEditor = function (editor, panel) {
- editor.addButton('quicklink', {
- icon: 'link',
- tooltip: 'Insert/Edit link',
- stateSelector: 'a[href]',
- onclick: function () {
- panel.showForm(editor, 'quicklink');
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (result) {
+ panelRect = result.rect;
+ currentRect = targetRect;
+ movePanelTo(panel, Layout.userConstrain(userConstainHandler, targetRect, contentAreaRect, panelRect));
+ togglePositionClass(panel, result.position);
+ return true;
+ } else {
+ return false;
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addButton('quickimage', {
- icon: 'image',
- tooltip: 'Insert image',
- onclick: function () {
- Picker.pickFile().then(function (files) {
- var blob = files[0];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var showPanelAt = function (panel, id, editor, targetRect) {
+ showPanel(panel);
+ panel.items().hide();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Conversions.blobToBase64(blob).then(function (base64) {
- Actions.insertBlob(editor, base64, blob);
- });
- });
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!showToolbar(panel, id)) {
+ hide(panel);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addButton('quicktable', {
- icon: 'table',
- tooltip: 'Insert table',
- onclick: function () {
- panel.hide();
- Actions.insertTable(editor, 2, 2);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (repositionPanelAt(panel, id, editor, targetRect) === false) {
+ hide(panel);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- addHeaderButtons(editor);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var hasFormVisible = function () {
+ return panel.items().filter('form:visible').length > 0;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- addToEditor: addToEditor
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var showForm = function (editor, id) {
+ if (panel) {
+ panel.items().hide();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-defineGlobal("global!tinymce.EditorManager", tinymce.EditorManager);
-/**
- * SkinLoader.js
- *
- * Released under LGPL License.
- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!showToolbar(panel, id)) {
+ hide(panel);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce/inlite/core/SkinLoader', [
- 'global!tinymce.EditorManager',
- 'global!tinymce.DOM'
-], function (EditorManager, DOM) {
- var fireSkinLoaded = function (editor, callback) {
- var done = function () {
- editor._skinLoaded = true;
- editor.fire('SkinLoaded');
- callback();
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var contentAreaRect, panelRect, result, userConstainHandler;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.initialized) {
- done();
- } else {
- editor.on('init', done);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ showPanel(panel);
+ panel.items().hide();
+ showToolbar(panel, id);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var urlFromName = function (name) {
- var prefix = EditorManager.baseURL + '/skins/';
- return name ? prefix + name : prefix + 'lightgray';
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ userConstainHandler = EditorSettings.getHandlerOr(editor, 'inline_toolbar_position_handler', Layout.defaultHandler);
+ contentAreaRect = Measure.getContentAreaRect(editor);
+ panelRect = DOMUtils.DOM.getRect(panel.getEl());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var toAbsoluteUrl = function (editor, url) {
- return editor.documentBaseURI.toAbsolute(url);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ result = Layout.calc(currentRect, contentAreaRect, panelRect);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var load = function (editor, callback) {
- var settings = editor.settings;
- var skinUrl = settings.skin_url ? toAbsoluteUrl(editor, settings.skin_url) : urlFromName(settings.skin);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (result) {
+ panelRect = result.rect;
+ movePanelTo(panel, Layout.userConstrain(userConstainHandler, currentRect, contentAreaRect, panelRect));
+ togglePositionClass(panel, result.position);
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var done = function () {
- fireSkinLoaded(editor, callback);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var show = function (editor, id, targetRect, toolbars) {
+ if (!panel) {
+ panel = create(editor, toolbars);
+ panel.renderTo(document.body).reflow().moveTo(targetRect.x, targetRect.y);
+ editor.nodeChanged();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DOM.styleSheetLoader.load(skinUrl + '/skin.min.css', done);
- editor.contentCSS.push(skinUrl + '/content.inline.min.css');
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ showPanelAt(panel, id, editor, targetRect);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- load: load
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var reposition = function (editor, id, targetRect) {
+ if (panel) {
+ repositionPanelAt(panel, id, editor, targetRect);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var hide = function () {
+ if (panel) {
+ panel.hide();
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var focus = function () {
+ if (panel) {
+ panel.find('toolbar:visible').eq(0).each(function (item) {
+ item.focus(true);
+ });
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var remove = function () {
+ if (panel) {
+ panel.remove();
+ panel = null;
+ }
+ };
+
+ var inForm = function () {
+ return panel && panel.visible() && hasFormVisible();
+ };
+
+ return {
+ show: show,
+ showForm: showForm,
+ reposition: reposition,
+ inForm: inForm,
+ hide: hide,
+ focus: focus,
+ remove: remove
+ };
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Matcher.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Conversions.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="cx" style="display: block; padding: 0 10px"> * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1502,38 +1829,34 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce/inlite/core/Matcher', [
-], function () {
- // result :: String, Rect -> Matcher.result
- var result = function (id, rect) {
- return {
- id: id,
- rect: rect
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.inlite.file.Conversions',
+ [
+ 'tinymce.core.util.Promise'
+ ],
+ function (Promise) {
+ var blobToBase64 = function (blob) {
+ return new Promise(function (resolve) {
+ var reader = new FileReader();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // match :: Editor, [(Editor -> Matcher.result | Null)] -> Matcher.result | Null
- var match = function (editor, matchers) {
- for (var i = 0; i < matchers.length; i++) {
- var f = matchers[i];
- var result = f(editor);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ reader.onloadend = function () {
+ resolve(reader.result.split(',')[1]);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (result) {
- return result;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ reader.readAsDataURL(blob);
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ blobToBase64: blobToBase64
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- match: match,
- result: result
- };
-});
</del><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * SelectionMatcher.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Picker.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="cx" style="display: block; padding: 0 10px"> * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1542,54 +1865,43 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce/inlite/core/SelectionMatcher', [
- 'tinymce/inlite/core/Matcher',
- 'tinymce/inlite/core/Measure'
-], function (Matcher, Measure) {
- // textSelection :: String -> (Editor -> Matcher.result | Null)
- var textSelection = function (id) {
- return function (editor) {
- if (!editor.selection.isCollapsed()) {
- return Matcher.result(id, Measure.getSelectionRect(editor));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.inlite.file.Picker',
+ [
+ 'tinymce.core.util.Promise'
+ ],
+ function (Promise) {
+ var pickFile = function () {
+ return new Promise(function (resolve) {
+ var fileInput;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ fileInput = document.createElement("input");
+ fileInput.type = "file";
+ fileInput.style.position = 'fixed';
+ fileInput.style.left = 0;
+ fileInput.style.top = 0;
+ fileInput.style.opacity = 0.001;
+ document.body.appendChild(fileInput);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // emptyTextBlock :: [Elements], String -> (Editor -> Matcher.result | Null)
- var emptyTextBlock = function (elements, id) {
- return function (editor) {
- var i, textBlockElementsMap = editor.schema.getTextBlockElements();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ fileInput.onchange = function (e) {
+ resolve(Array.prototype.slice.call(e.target.files));
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0; i < elements.length; i++) {
- if (elements[i].nodeName === 'TABLE') {
- return null;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ fileInput.click();
+ fileInput.parentNode.removeChild(fileInput);
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0; i < elements.length; i++) {
- if (elements[i].nodeName in textBlockElementsMap) {
- if (editor.dom.isEmpty(elements[i])) {
- return Matcher.result(id, Measure.getSelectionRect(editor));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ pickFile: pickFile
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
- }
</del><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- };
- };
</del><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- textSelection: textSelection,
- emptyTextBlock: emptyTextBlock
- };
-});
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * ElementMatcher.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Buttons.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="cx" style="display: block; padding: 0 10px"> * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1598,100 +1910,81 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce/inlite/core/ElementMatcher', [
- 'tinymce/inlite/core/Matcher',
- 'tinymce/inlite/core/Measure'
-], function (Matcher, Measure) {
- // element :: Element, [PredicateId] -> (Editor -> Matcher.result | Null)
- var element = function (element, predicateIds) {
- return function (editor) {
- for (var i = 0; i < predicateIds.length; i++) {
- if (predicateIds[i].predicate(element)) {
- return Matcher.result(predicateIds[i].id, Measure.getElementRect(editor, element));
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.inlite.ui.Buttons',
+ [
+ 'tinymce.themes.inlite.ui.Panel',
+ 'tinymce.themes.inlite.file.Conversions',
+ 'tinymce.themes.inlite.file.Picker',
+ 'tinymce.themes.inlite.core.Actions'
+ ],
+ function (Panel, Conversions, Picker, Actions) {
+ var addHeaderButtons = function (editor) {
+ var formatBlock = function (name) {
+ return function () {
+ Actions.formatBlock(editor, name);
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (var i = 1; i < 6; i++) {
+ var name = 'h' + i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // parent :: [Elements], [PredicateId] -> (Editor -> Matcher.result | Null)
- var parent = function (elements, predicateIds) {
- return function (editor) {
- for (var i = 0; i < elements.length; i++) {
- for (var x = 0; x < predicateIds.length; x++) {
- if (predicateIds[x].predicate(elements[i])) {
- return Matcher.result(predicateIds[x].id, Measure.getElementRect(editor, elements[i]));
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addButton(name, {
+ text: name.toUpperCase(),
+ tooltip: 'Heading ' + i,
+ stateSelector: name,
+ onclick: formatBlock(name),
+ onPostRender: function () {
+ // TODO: Remove this hack that produces bold H1-H6 when we have proper icons
+ var span = this.getEl().firstChild.firstChild;
+ span.style.fontWeight = 'bold';
+ }
+ });
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var addToEditor = function (editor, panel) {
+ editor.addButton('quicklink', {
+ icon: 'link',
+ tooltip: 'Insert/Edit link',
+ stateSelector: 'a[href]',
+ onclick: function () {
+ panel.showForm(editor, 'quicklink');
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- element: element,
- parent: parent
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addButton('quickimage', {
+ icon: 'image',
+ tooltip: 'Insert image',
+ onclick: function () {
+ Picker.pickFile().then(function (files) {
+ var blob = files[0];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Arr.js
- *
- * Released under LGPL License.
- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Conversions.blobToBase64(blob).then(function (base64) {
+ Actions.insertBlob(editor, base64, blob);
+ });
+ });
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce/inlite/alien/Arr', [
-], function () {
- var flatten = function (arr) {
- return arr.reduce(function (results, item) {
- return Array.isArray(item) ? results.concat(flatten(item)) : results.concat(item);
- }, []);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addButton('quicktable', {
+ icon: 'table',
+ tooltip: 'Insert table',
+ onclick: function () {
+ panel.hide();
+ Actions.insertTable(editor, 2, 2);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- flatten: flatten
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ addHeaderButtons(editor);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * PredicateId.js
- *
- * Released under LGPL License.
- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ addToEditor: addToEditor
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce/inlite/core/PredicateId', [
- 'global!tinymce.util.Tools'
-], function (Tools) {
- var create = function (id, predicate) {
- return {
- id: id,
- predicate: predicate
- };
- };
-
- // fromContextToolbars :: [ContextToolbar] -> [PredicateId]
- var fromContextToolbars = function (toolbars) {
- return Tools.map(toolbars, function (toolbar) {
- return create(toolbar.id, toolbar.predicate);
- });
- };
-
- return {
- create: create,
- fromContextToolbars: fromContextToolbars
- };
-});
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Theme.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1702,157 +1995,167 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce/inlite/Theme', [
- 'global!tinymce.ThemeManager',
- 'global!tinymce.util.Delay',
- 'tinymce/inlite/ui/Panel',
- 'tinymce/inlite/ui/Buttons',
- 'tinymce/inlite/core/SkinLoader',
- 'tinymce/inlite/core/SelectionMatcher',
- 'tinymce/inlite/core/ElementMatcher',
- 'tinymce/inlite/core/Matcher',
- 'tinymce/inlite/alien/Arr',
- 'tinymce/inlite/alien/EditorSettings',
- 'tinymce/inlite/core/PredicateId'
-], function(ThemeManager, Delay, Panel, Buttons, SkinLoader, SelectionMatcher, ElementMatcher, Matcher, Arr, EditorSettings, PredicateId) {
- var getSelectionElements = function (editor) {
- var node = editor.selection.getNode();
- var elms = editor.dom.getParents(node);
- return elms;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.inlite.Theme',
+ [
+ 'tinymce.core.ThemeManager',
+ 'tinymce.core.ui.Api',
+ 'tinymce.core.util.Delay',
+ 'tinymce.themes.inlite.alien.Arr',
+ 'tinymce.themes.inlite.alien.EditorSettings',
+ 'tinymce.themes.inlite.core.ElementMatcher',
+ 'tinymce.themes.inlite.core.Matcher',
+ 'tinymce.themes.inlite.core.PredicateId',
+ 'tinymce.themes.inlite.core.SelectionMatcher',
+ 'tinymce.themes.inlite.core.SkinLoader',
+ 'tinymce.themes.inlite.ui.Buttons',
+ 'tinymce.themes.inlite.ui.Panel'
+ ],
+ function (
+ ThemeManager, Api, Delay, Arr, EditorSettings, ElementMatcher, Matcher,
+ PredicateId, SelectionMatcher, SkinLoader, Buttons, Panel
+ ) {
+ var getSelectionElements = function (editor) {
+ var node = editor.selection.getNode();
+ var elms = editor.dom.getParents(node);
+ return elms;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var createToolbar = function (editor, selector, id, items) {
- var selectorPredicate = function (elm) {
- return editor.dom.is(elm, selector);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createToolbar = function (editor, selector, id, items) {
+ var selectorPredicate = function (elm) {
+ return editor.dom.is(elm, selector);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- predicate: selectorPredicate,
- id: id,
- items: items
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ predicate: selectorPredicate,
+ id: id,
+ items: items
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getToolbars = function (editor) {
- var contextToolbars = editor.contextToolbars;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getToolbars = function (editor) {
+ var contextToolbars = editor.contextToolbars;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Arr.flatten([
- contextToolbars ? contextToolbars : [],
- createToolbar(editor, 'img', 'image', 'alignleft aligncenter alignright')
- ]);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Arr.flatten([
+ contextToolbars ? contextToolbars : [],
+ createToolbar(editor, 'img', 'image', 'alignleft aligncenter alignright')
+ ]);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var findMatchResult = function (editor, toolbars) {
- var result, elements, contextToolbarsPredicateIds;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var findMatchResult = function (editor, toolbars) {
+ var result, elements, contextToolbarsPredicateIds;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elements = getSelectionElements(editor);
- contextToolbarsPredicateIds = PredicateId.fromContextToolbars(toolbars);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elements = getSelectionElements(editor);
+ contextToolbarsPredicateIds = PredicateId.fromContextToolbars(toolbars);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- result = Matcher.match(editor, [
- ElementMatcher.element(elements[0], contextToolbarsPredicateIds),
- SelectionMatcher.textSelection('text'),
- SelectionMatcher.emptyTextBlock(elements, 'insert'),
- ElementMatcher.parent(elements, contextToolbarsPredicateIds)
- ]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ result = Matcher.match(editor, [
+ ElementMatcher.element(elements[0], contextToolbarsPredicateIds),
+ SelectionMatcher.textSelection('text'),
+ SelectionMatcher.emptyTextBlock(elements, 'insert'),
+ ElementMatcher.parent(elements, contextToolbarsPredicateIds)
+ ]);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return result && result.rect ? result : null;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return result && result.rect ? result : null;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var togglePanel = function (editor, panel) {
- var toggle = function () {
- var toolbars = getToolbars(editor);
- var result = findMatchResult(editor, toolbars);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var togglePanel = function (editor, panel) {
+ var toggle = function () {
+ var toolbars = getToolbars(editor);
+ var result = findMatchResult(editor, toolbars);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (result) {
- panel.show(editor, result.id, result.rect, toolbars);
- } else {
- panel.hide();
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (result) {
+ panel.show(editor, result.id, result.rect, toolbars);
+ } else {
+ panel.hide();
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function () {
- if (!editor.removed) {
- toggle();
- }
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function () {
+ if (!editor.removed) {
+ toggle();
+ }
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var repositionPanel = function (editor, panel) {
- return function () {
- var toolbars = getToolbars(editor);
- var result = findMatchResult(editor, toolbars);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var repositionPanel = function (editor, panel) {
+ return function () {
+ var toolbars = getToolbars(editor);
+ var result = findMatchResult(editor, toolbars);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (result) {
- panel.reposition(editor, result.id, result.rect);
- }
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (result) {
+ panel.reposition(editor, result.id, result.rect);
+ }
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var ignoreWhenFormIsVisible = function (panel, f) {
- return function () {
- if (!panel.inForm()) {
- f();
- }
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var ignoreWhenFormIsVisible = function (editor, panel, f) {
+ return function () {
+ if (!editor.removed && !panel.inForm()) {
+ f();
+ }
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var bindContextualToolbarsEvents = function (editor, panel) {
- var throttledTogglePanel = Delay.throttle(togglePanel(editor, panel), 0);
- var throttledTogglePanelWhenNotInForm = Delay.throttle(ignoreWhenFormIsVisible(panel, togglePanel(editor, panel)), 0);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var bindContextualToolbarsEvents = function (editor, panel) {
+ var throttledTogglePanel = Delay.throttle(togglePanel(editor, panel), 0);
+ var throttledTogglePanelWhenNotInForm = Delay.throttle(ignoreWhenFormIsVisible(editor, panel, togglePanel(editor, panel)), 0);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('blur hide ObjectResizeStart', panel.hide);
- editor.on('click', throttledTogglePanel);
- editor.on('nodeChange mouseup', throttledTogglePanelWhenNotInForm);
- editor.on('ResizeEditor keyup', throttledTogglePanel);
- editor.on('ResizeWindow', repositionPanel(editor, panel));
- editor.on('remove', panel.remove);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('blur hide ObjectResizeStart', panel.hide);
+ editor.on('click', throttledTogglePanel);
+ editor.on('nodeChange mouseup', throttledTogglePanelWhenNotInForm);
+ editor.on('ResizeEditor keyup', throttledTogglePanel);
+ editor.on('ResizeWindow', repositionPanel(editor, panel));
+ editor.on('remove', panel.remove);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.shortcuts.add('Alt+F10', '', panel.focus);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.shortcuts.add('Alt+F10', '', panel.focus);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var overrideLinkShortcut = function (editor, panel) {
- editor.shortcuts.remove('meta+k');
- editor.shortcuts.add('meta+k', '', function () {
- var toolbars = getToolbars(editor);
- var result = result = Matcher.match(editor, [
- SelectionMatcher.textSelection('quicklink')
- ]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var overrideLinkShortcut = function (editor, panel) {
+ editor.shortcuts.remove('meta+k');
+ editor.shortcuts.add('meta+k', '', function () {
+ var toolbars = getToolbars(editor);
+ var result = result = Matcher.match(editor, [
+ SelectionMatcher.textSelection('quicklink')
+ ]);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (result) {
- panel.show(editor, result.id, result.rect, toolbars);
- }
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (result) {
+ panel.show(editor, result.id, result.rect, toolbars);
+ }
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var renderInlineUI = function (editor, panel) {
- SkinLoader.load(editor, function () {
- bindContextualToolbarsEvents(editor, panel);
- overrideLinkShortcut(editor, panel);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var renderInlineUI = function (editor, panel) {
+ SkinLoader.load(editor, function () {
+ bindContextualToolbarsEvents(editor, panel);
+ overrideLinkShortcut(editor, panel);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {};
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {};
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var fail = function (message) {
- throw new Error(message);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var fail = function (message) {
+ throw new Error(message);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ThemeManager.add('inlite', function (editor) {
- var panel = new Panel();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ThemeManager.add('inlite', function (editor) {
+ var panel = new Panel();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Buttons.addToEditor(editor, panel);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Buttons.addToEditor(editor, panel);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var renderUI = function () {
- return editor.inline ? renderInlineUI(editor, panel) : fail('inlite theme only supports inline mode.');
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var renderUI = function () {
+ return editor.inline ? renderInlineUI(editor, panel) : fail('inlite theme only supports inline mode.');
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- renderUI: renderUI
- };
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ renderUI: renderUI
+ };
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function() {};
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Api.appendTo(window.tinymce ? window.tinymce : {});
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-dem('tinymce/inlite/Theme')();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function () { };
+ }
+);
+
+dem('tinymce.themes.inlite.Theme')();
</ins><span class="cx" style="display: block; padding: 0 10px"> })();
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcethemesinlitethememinjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/themes/inlite/theme.min.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/themes/inlite/theme.min.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/themes/inlite/theme.min.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1 +1 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-!function(){var e={},t=function(t){for(var n=e[t],i=n.deps,o=n.defn,a=i.length,s=new Array(a),l=0;l<a;++l)s[l]=r(i[l]);var u=o.apply(null,s);if(void 0===u)throw"module ["+t+"] returned undefined";n.instance=u},n=function(t,n,r){if("string"!=typeof t)throw"module id must be a string";if(void 0===n)throw"no dependencies for "+t;if(void 0===r)throw"no definition function for "+t;e[t]={deps:n,defn:r,instance:void 0}},r=function(n){var r=e[n];if(void 0===r)throw"module ["+n+"] was undefined";return void 0===r.instance&&t(n),r.instance},i=function(e,t){for(var n=e.length,i=new Array(n),o=0;o<n;++o)i.push(r(e[o]));t.apply(null,t)},o={};o.bolt={module:{api:{define:n,require:i,demand:r}}};var a=n,s=function(e,t){a(e,[],function(){return t})};s("1",tinymce.ThemeManager),s("2",tinymce.u
til.Delay),s("c",tinymce.util.Tools),s("d",tinymce.ui.Factory),s("e",tinymce.DOM),a("j",[],function(){var e=function(e){return function(t){return typeof t===e}},t=function(e){return Array.isArray(e)},n=function(e){return null===e},r=function(e){return function(r){return!n(r)&&!t(r)&&e(r)}};return{isString:e("string"),isNumber:e("number"),isBoolean:e("boolean"),isFunction:e("function"),isObject:r(e("object")),isNull:n,isArray:t}}),a("f",["c","d","j"],function(e,t,n){var r=function(e,t){var n=function(e,t){return{selector:e,handler:t}},r=function(e){t.active(e)},i=function(e){t.disabled(e)};return t.settings.stateSelector?n(t.settings.stateSelector,r):t.settings.disabledStateSelector?n(t.settings.disabledStateSelector,i):null},i=function(e,t,n){return function(){var i=r(t,n);null!==i&&e.selection.selectorChanged(i.selector,i.handler)
}},o=function(e){return n.isArray(e)?e:n.isString(e)?e.split(/[ ,]/):[]},a=function(n,r,a){var s,l=[];if(a)return e.each(o(a),function(e){var r;"|"==e?s=null:t.has(e)?(e={type:e},l.push(e),s=null):n.buttons[e]&&(s||(s={type:"buttongroup",items:[]},l.push(s)),r=e,e=n.buttons[r],"function"==typeof e&&(e=e()),e.type=e.type||"button",e=t.create(e),e.on("postRender",i(n,r,e)),s.items.push(e))}),t.create({type:"toolbar",layout:"flow",name:r,items:l})};return{create:a}}),s("o",tinymce.util.Promise),a("p",[],function(){var e=0,t=function(){var e=function(){return Math.round(4294967295*Math.random()).toString(36)};return"s"+Date.now().toString(36)+e()+e()+e()},n=function(n){return n+e++ +t()};return{uuid:n}}),a("u",[],function(){var e=function(e,t){function n(n){var i,o,a;o=t[n?"startContainer":"endContainer"],a=t[n?"startOffset":"en
dOffset"],1==o.nodeType&&(i=e.create("span",{"data-mce-type":"bookmark"}),o.hasChildNodes()?(a=Math.min(a,o.childNodes.length-1),n?o.insertBefore(i,o.childNodes[a]):e.insertAfter(i,o.childNodes[a])):o.appendChild(i),o=i,a=0),r[n?"startContainer":"endContainer"]=o,r[n?"startOffset":"endOffset"]=a}var r={};return n(!0),t.collapsed||n(),r},t=function(e,t){function n(n){function r(e){for(var t=e.parentNode.firstChild,n=0;t;){if(t==e)return n;1==t.nodeType&&"bookmark"==t.getAttribute("data-mce-type")||n++,t=t.nextSibling}return-1}var i,o,a;i=a=t[n?"startContainer":"endContainer"],o=t[n?"startOffset":"endOffset"],i&&(1==i.nodeType&&(o=r(i),i=i.parentNode,e.remove(a)),t[n?"startContainer":"endContainer"]=i,t[n?"startOffset":"endOffset"]=o)}n(!0),n();var r=e.createRng();return r.setStart
(t.startContainer,t.startOffset),t.endContainer&&r.setEnd(t.endContainer,t.endOffset),r};return{create:e,resolve:t}}),s("v",tinymce.dom.TreeWalker),s("w",tinymce.dom.RangeUtils),a("q",["u","c","v","w"],function(e,t,n,r){var i=function(e,t,r){var i,o,a=[];for(i=new n(t,e),o=t;o&&(1===o.nodeType&&a.push(o),o!==r);o=i.next());return a},o=function(n,r){var i,o,a;o=n.dom,a=n.selection,i=e.create(o,a.getRng()),t.each(r,function(e){n.dom.remove(e,!0)}),a.setRng(e.resolve(o,i))},a=function(e){return"A"===e.nodeName&&e.hasAttribute("href")},s=function(e,t){var n=e.getParent(t,a);return n?n:t},l=function(e){var n,o,l,u,c,d,f;return c=e.selection,d=e.dom,f=c.getRng(),n=s(d,r.getNode(f.startContainer,f.startOffset)),o=r.getNode(f.endContainer,f.endOffset),l=e.getBody(),u=t.grep(i(l,n,o),a)},u=function(e){o(e,l(e))};return{unlinkSelection:u}}),a("m",["p",&
quot;q"],function(e,t){var n=function(e,t){var n,r,i;for(i='<table data-mce-id="mce" style="width: 100%">',i+="<tbody>",r=0;r<t;r++){for(i+="<tr>",n=0;n<e;n++)i+="<td><br></td>";i+="</tr>"}return i+="</tbody>",i+="</table>"},r=function(e){var t=e.dom.select("*[data-mce-id]");return t[0]},i=function(e,t,i){e.undoManager.transact(function(){var o,a;e.insertContent(n(t,i)),o=r(e),o.removeAttribute("data-mce-id"),a=e.dom.select("td,th",o),e.selection.setCursorLocation(a[0],0)})},o=function(e,t){e.execCommand("FormatBlock",!1,t)},a=function(t,n,r){var i,o;i=t.editorUpload.blobCache,o=i.create(e.uuid("mceu"),r,n),i.add(o),t.insertContent(t.dom.createHTML("img",{src:o.blobUri()}))},s=function(e){e.selection.collapse(!1)},l=function(e){e.focus(),t.unlinkSelection(e),s(e)},u=function(e,t,n)
{e.focus(),e.dom.setAttrib(t,"href",n),s(e)},c=function(e,t){e.execCommand("mceInsertLink",!1,{href:t}),s(e)},d=function(e,t){var n=e.dom.getParent(e.selection.getStart(),"a[href]");n?u(e,n,t):c(e,t)},f=function(e,t){0===t.trim().length?l(e):d(e,t)};return{insertTable:i,formatBlock:o,insertBlob:a,createLink:f,unlink:l}}),a("r",[],function(){var e=function(e){return/^www\.|\.(com|org|edu|gov|uk|net|ca|de|jp|fr|au|us|ru|ch|it|nl|se|no|es|mil)$/i.test(e.trim())},t=function(e){return/^https?:\/\//.test(e.trim())};return{isDomainLike:e,isAbsolute:t}}),a("g",["c","d","o","m","r"],function(e,t,n,r,i){var o=function(e){e.find("textbox").eq(0).each(function(e){e.focus()})},a=function(n,r){var i=t.create(e.extend({type:"form",layout:"flex",direction:"row",padding:5,name:n,spacing:3},r));return i.on("show",function(){o(i)}),i},s=function(e,t){ret
urn t?e.show():e.hide()},l=function(e,t){return new n(function(n){e.windowManager.confirm("The URL you entered seems to be an external link. Do you want to add the required http:// prefix?",function(e){var r=e===!0?"http://"+t:t;n(r)})})},u=function(e,t){return!i.isAbsolute(t)&&i.isDomainLike(t)?l(e,t):n.resolve(t)},c=function(e,t){var n={},i=function(){e.focus(),r.unlink(e),t()},o=function(e){var t=e.meta;t&&t.attach&&(n={href:this.value(),attach:t.attach})},l=function(t){if(t.control===this){var n,r="";n=e.dom.getParent(e.selection.getStart(),"a[href]"),n&&(r=e.dom.getAttrib(n,"href")),this.fromJSON({linkurl:r}),s(this.find("#unlink"),n),this.find("#linkurl")[0].focus()}};return a("quicklink",{items:[{type:"button",name:"unlink",icon:"unlink",onclick:i,tooltip:"Remove link"},{type:"filepicker",name:"linkurl",pla
ceholder:"Paste or type a link",filetype:"file",onchange:o},{type:"button",icon:"checkmark",subtype:"primary",tooltip:"Ok",onclick:"submit"}],onshow:l,onsubmit:function(i){u(e,i.data.linkurl).then(function(i){e.undoManager.transact(function(){i===n.href&&(n.attach(),n={}),r.createLink(e,i)}),t()})}})};return{createQuickLinkForm:c}}),s("s",tinymce.geom.Rect),a("t",[],function(){var e=function(e){return{x:e.left,y:e.top,w:e.width,h:e.height}},t=function(e){return{left:e.x,top:e.y,width:e.w,height:e.h,right:e.x+e.w,bottom:e.y+e.h}};return{fromClientRect:e,toClientRect:t}}),a("h",["e","s","t"],function(e,t,n){var r=function(t){var n=e.getViewPort();return{x:t.x+n.x,y:t.y+n.y,w:t.w,h:t.h}},i=function(e){var t=e.getBoundingClientRect();return r({x:t.left,y:t.top,w:Math.max(e.clientWidth,e.offsetWidth),h:Math.max(e.clientHeight,e.offsetHeight)})},o=funct
ion(e,t){return i(t)},a=function(e){return i(e.getElement().ownerDocument.body)},s=function(e){return i(e.getContentAreaContainer()||e.getBody())},l=function(e){var t=e.selection.getBoundingClientRect();return t?r(n.fromClientRect(t)):null};return{getElementRect:o,getPageAreaRect:a,getContentAreaRect:s,getSelectionRect:l}}),a("i",["s","t"],function(e,t){var n=function(e,t){return{rect:e,position:t}},r=function(e,t){return{x:t.x,y:t.y,w:e.w,h:e.h}},i=function(t,i,o,a,s){var l,u,c;return l=e.findBestRelativePosition(s,o,a,t),o=e.clamp(o,a),l?(u=e.relativePosition(s,o,l),c=r(s,u),n(c,l)):(o=e.intersect(a,o),o?(l=e.findBestRelativePosition(s,o,a,i))?(u=e.relativePosition(s,o,l),c=r(s,u),n(c,l)):(c=r(s,o),n(c,l)):null)},o=function(e,t,n){return i(["cr-cl","cl-cr"],["bc-tc","bl-tl","br-tr"],e,t,n)},a=function(e,t,n){return i(["tc-bc","bc-tc","tl-bl","bl-tl","tr-br&q
uot;,"br-tr"],["bc-tc","bl-tl","br-tr"],e,t,n)},s=function(e,n,r,i){var o;return"function"==typeof e?(o=e({elementRect:t.toClientRect(n),contentAreaRect:t.toClientRect(r),panelRect:t.toClientRect(i)}),t.fromClientRect(o)):i},l=function(e){return e.panelRect};return{calcInsert:o,calc:a,userConstrain:s,defaultHandler:l}}),a("a",["j"],function(e){var t=function(e,t){if(t(e))return!0;throw new Error("Default value doesn't match requested type.")},n=function(e){return function(n,r,i){var o=n.settings;return t(i,e),r in o&&e(o[r])?o[r]:i}},r=function(e,t){return e.split(t).filter(function(e){return e.length>0})},i=function(t,n){var i=function(e){return"string"==typeof e?r(e,/[ ,]/):e},o=function(e,t){return e===!1?[]:t};return e.isArray(t)?t:e.isString(t)?i(t):e.isBoolean(t)?o(t,n):n},o=function(e){return function(n,r,o){var a=r in n.settings?n.settings[r]:o;return t(o,e),i(a,o)}};return{g
etStringOr:n(e.isString),getBoolOr:n(e.isBoolean),getNumberOr:n(e.isNumber),getHandlerOr:n(e.isFunction),getToolbarItemsOr:o(e.isArray)}}),a("3",["c","d","e","f","g","h","i","a"],function(e,t,n,r,i,o,a,s){return function(){var l,u,c=["bold","italic","|","quicklink","h2","h3","blockquote"],d=["quickimage","quicktable"],f=function(t,n){return e.map(n,function(e){return r.create(t,e.id,e.items)})},p=function(e){return s.getToolbarItemsOr(e,"selection_toolbar",c)},h=function(e){return s.getToolbarItemsOr(e,"insert_toolbar",d)},m=function(e){return e.items().length>0},g=function(n,o){var a=f(n,o).concat([r.create(n,"text",p(n)),r.create(n,"insert",h(n)),i.createQuickLinkForm(n,k)]);return t.create({type:"floatpanel",role:"dialog",classes:"tinym
ce tinymce-inline arrow",ariaLabel:"Inline toolbar",layout:"flex",direction:"column",align:"stretch",autohide:!1,autofix:!0,fixed:!0,border:1,items:e.grep(a,m),oncancel:function(){n.focus()}})},v=function(e){e&&e.show()},y=function(e,t){e.moveTo(t.x,t.y)},b=function(t,n){n=n?n.substr(0,2):"",e.each({t:"down",b:"up",c:"center"},function(e,r){t.classes.toggle("arrow-"+e,r===n.substr(0,1))}),"cr"===n?(t.classes.toggle("arrow-left",!0),t.classes.toggle("arrow-right",!1)):"cl"===n?(t.classes.toggle("arrow-left",!0),t.classes.toggle("arrow-right",!0)):e.each({l:"left",r:"right"},function(e,r){t.classes.toggle("arrow-"+e,r===n.substr(1,1))})},C=function(e,t){var n=e.items().filter("#"+t);return n.length>0&&(n[0].show(),e.reflow(),!0)},x=function(e,t,r,i){var l,c,d,f;return f=s.ge
tHandlerOr(r,"inline_toolbar_position_handler",a.defaultHandler),l=o.getContentAreaRect(r),c=n.getRect(e.getEl()),d="insert"===t?a.calcInsert(i,l,c):a.calc(i,l,c),!!d&&(c=d.rect,u=i,y(e,a.userConstrain(f,i,l,c)),b(e,d.position),!0)},w=function(e,t,n,r){return v(e),e.items().hide(),C(e,t)?void(x(e,t,n,r)===!1&&k(e)):void k(e)},E=function(){return l.items().filter("form:visible").length>0},N=function(e,t){if(l){if(l.items().hide(),!C(l,t))return void k(l);var r,i,c,d;v(l),l.items().hide(),C(l,t),d=s.getHandlerOr(e,"inline_toolbar_position_handler",a.defaultHandler),r=o.getContentAreaRect(e),i=n.getRect(l.getEl()),c=a.calc(u,r,i),c&&(i=c.rect,y(l,a.userConstrain(d,u,r,i)),b(l,c.position))}},_=function(e,t,n,r){l||(l=g(e,r),l.renderTo(document.body).reflow().moveTo(n.x,n.y),e.nodeChanged()),w(l,t,e,n)},S=function(e,t,n){l&&x(l,t,e,n)},k=function(){l&&l.hide()},T=function(){l&&l.find("toolbar:
visible").eq(0).each(function(e){e.focus(!0)})},R=function(){l&&(l.remove(),l=null)},A=function(){return l&&l.visible()&&E()};return{show:_,showForm:N,reposition:S,inForm:A,hide:k,focus:T,remove:R}}}),a("k",["o"],function(e){var t=function(t){return new e(function(e){var n=new FileReader;n.onloadend=function(){e(n.result.split(",")[1])},n.readAsDataURL(t)})};return{blobToBase64:t}}),a("l",["o"],function(e){var t=function(){return new e(function(e){var t;t=document.createElement("input"),t.type="file",t.style.position="fixed",t.style.left=0,t.style.top=0,t.style.opacity=.001,document.body.appendChild(t),t.onchange=function(t){e(Array.prototype.slice.call(t.target.files))},t.click(),t.parentNode.removeChild(t)})};return{pickFile:t}}),a("4",["3","k","l","m"],function(e,t,n,r){var i=function(e){for(var t=function(t){return functio
n(){r.formatBlock(e,t)}},n=1;n<6;n++){var i="h"+n;e.addButton(i,{text:i.toUpperCase(),tooltip:"Heading "+n,stateSelector:i,onclick:t(i),onPostRender:function(){var e=this.getEl().firstChild.firstChild;e.style.fontWeight="bold"}})}},o=function(e,o){e.addButton("quicklink",{icon:"link",tooltip:"Insert/Edit link",stateSelector:"a[href]",onclick:function(){o.showForm(e,"quicklink")}}),e.addButton("quickimage",{icon:"image",tooltip:"Insert image",onclick:function(){n.pickFile().then(function(n){var i=n[0];t.blobToBase64(i).then(function(t){r.insertBlob(e,t,i)})})}}),e.addButton("quicktable",{icon:"table",tooltip:"Insert table",onclick:function(){o.hide(),r.insertTable(e,2,2)}}),i(e)};return{addToEditor:o}}),s("n",tinymce.EditorManager),a("5",["n","e"],function(e,t){var n=function(e,t){var n=function(){e._ski
nLoaded=!0,e.fire("SkinLoaded"),t()};e.initialized?n():e.on("init",n)},r=function(t){var n=e.baseURL+"/skins/";return t?n+t:n+"lightgray"},i=function(e,t){return e.documentBaseURI.toAbsolute(t)},o=function(e,o){var a=e.settings,s=a.skin_url?i(e,a.skin_url):r(a.skin),l=function(){n(e,o)};t.styleSheetLoader.load(s+"/skin.min.css",l),e.contentCSS.push(s+"/content.inline.min.css")};return{load:o}}),a("8",[],function(){var e=function(e,t){return{id:e,rect:t}},t=function(e,t){for(var n=0;n<t.length;n++){var r=t[n],i=r(e);if(i)return i}return null};return{match:t,result:e}}),a("6",["8","h"],function(e,t){var n=function(n){return function(r){return r.selection.isCollapsed()?null:e.result(n,t.getSelectionRect(r))}},r=function(n,r){return function(i){var o,a=i.schema.getTextBlockElements();for(o=0;o<n.length;o++)if("TABLE"===n[o].nodeName)return null;for(o=0;o<n.length;o++)if
(n[o].nodeName in a)return i.dom.isEmpty(n[o])?e.result(r,t.getSelectionRect(i)):null;return null}};return{textSelection:n,emptyTextBlock:r}}),a("7",["8","h"],function(e,t){var n=function(n,r){return function(i){for(var o=0;o<r.length;o++)if(r[o].predicate(n))return e.result(r[o].id,t.getElementRect(i,n));return null}},r=function(n,r){return function(i){for(var o=0;o<n.length;o++)for(var a=0;a<r.length;a++)if(r[a].predicate(n[o]))return e.result(r[a].id,t.getElementRect(i,n[o]));return null}};return{element:n,parent:r}}),a("9",[],function(){var e=function(t){return t.reduce(function(t,n){return Array.isArray(n)?t.concat(e(n)):t.concat(n)},[])};return{flatten:e}}),a("b",["c"],function(e){var t=function(e,t){return{id:e,predicate:t}},n=function(n){return e.map(n,function(e){return t(e.id,e.predicate)})};return{create:t,fromContextToolbars:n}}),a("0",["1","2","3","4",&
quot;5","6","7","8","9","a","b"],function(e,t,n,r,i,o,a,s,l,u,c){var d=function(e){var t=e.selection.getNode(),n=e.dom.getParents(t);return n},f=function(e,t,n,r){var i=function(n){return e.dom.is(n,t)};return{predicate:i,id:n,items:r}},p=function(e){var t=e.contextToolbars;return l.flatten([t?t:[],f(e,"img","image","alignleft aligncenter alignright")])},h=function(e,t){var n,r,i;return r=d(e),i=c.fromContextToolbars(t),n=s.match(e,[a.element(r[0],i),o.textSelection("text"),o.emptyTextBlock(r,"insert"),a.parent(r,i)]),n&&n.rect?n:null},m=function(e,t){var n=function(){var n=p(e),r=h(e,n);r?t.show(e,r.id,r.rect,n):t.hide()};return function(){e.removed||n()}},g=function(e,t){return function(){var n=p(e),r=h(e,n);r&&t.reposition(e,r.id,r.rect)}},v=function(e,t){return function(){e.inForm()||t()}},y=function(e,n){var r=t.throttle(m(e,n),0),i=t.throttle(v(n,m
(e,n)),0);e.on("blur hide ObjectResizeStart",n.hide),e.on("click",r),e.on("nodeChange mouseup",i),e.on("ResizeEditor keyup",r),e.on("ResizeWindow",g(e,n)),e.on("remove",n.remove),e.shortcuts.add("Alt+F10","",n.focus)},b=function(e,t){e.shortcuts.remove("meta+k"),e.shortcuts.add("meta+k","",function(){var n=p(e),r=r=s.match(e,[o.textSelection("quicklink")]);r&&t.show(e,r.id,r.rect,n)})},C=function(e,t){return i.load(e,function(){y(e,t),b(e,t)}),{}},x=function(e){throw new Error(e)};return e.add("inlite",function(e){var t=new n;r.addToEditor(e,t);var i=function(){return e.inline?C(e,t):x("inlite theme only supports inline mode.")};return{renderUI:i}}),function(){}}),r("0")()}();
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+!function(){var a={},b=function(b){for(var c=a[b],e=c.deps,f=c.defn,g=e.length,h=new Array(g),i=0;i<g;++i)h[i]=d(e[i]);var j=f.apply(null,h);if(void 0===j)throw"module ["+b+"] returned undefined";c.instance=j},c=function(b,c,d){if("string"!=typeof b)throw"module id must be a string";if(void 0===c)throw"no dependencies for "+b;if(void 0===d)throw"no definition function for "+b;a[b]={deps:c,defn:d,instance:void 0}},d=function(c){var d=a[c];if(void 0===d)throw"module ["+c+"] was undefined";return void 0===d.instance&&b(c),d.instance},e=function(a,b){for(var c=a.length,e=new Array(c),f=0;f<c;++f)e.push(d(a[f]));b.apply(null,b)},f={};f.bolt={module:{api:{define:c,require:e,demand:d}}};var g=c,h=function(a,b){g(a,[],function(){return b})};h("d",tinymce.util.Tools.resolve),g("1",[&q
uot;d"],function(a){return a("tinymce.ThemeManager")}),g("2",["d"],function(a){return a("tinymce.ui.Api")}),g("3",["d"],function(a){return a("tinymce.util.Delay")}),g("4",[],function(){var a=function(b){return b.reduce(function(b,c){return Array.isArray(c)?b.concat(a(c)):b.concat(c)},[])};return{flatten:a}}),g("e",[],function(){var a=function(a){return function(b){return typeof b===a}},b=function(a){return Array.isArray(a)},c=function(a){return null===a},d=function(a){return function(d){return!c(d)&&!b(d)&&a(d)}};return{isString:a("string"),isNumber:a("number"),isBoolean:a("boolean"),isFunction:a("function"),isObject:d(a("object")),isNull:c,isArray:b}}),g("5",["e"],function(a){var b=function(a,b){if(b(a))return!0;throw new Error("Default value doesn't match requested type.")},c=function(a){retur
n function(c,d,e){var f=c.settings;return b(e,a),d in f&&a(f[d])?f[d]:e}},d=function(a,b){return a.split(b).filter(function(a){return a.length>0})},e=function(b,c){var e=function(a){return"string"==typeof a?d(a,/[ ,]/):a},f=function(a,b){return a===!1?[]:b};return a.isArray(b)?b:a.isString(b)?e(b):a.isBoolean(b)?f(b,c):c},f=function(a){return function(c,d,f){var g=d in c.settings?c.settings[d]:f;return b(f,a),e(g,f)}};return{getStringOr:c(a.isString),getBoolOr:c(a.isBoolean),getNumberOr:c(a.isNumber),getHandlerOr:c(a.isFunction),getToolbarItemsOr:f(a.isArray)}}),g("7",[],function(){var a=function(a,b){return{id:a,rect:b}},b=function(a,b){for(var c=0;c<b.length;c++){var d=b[c],e=d(a);if(e)return e}return null};return{match:b,result:a}}),g("i",["d"],function(a){return a("tinymce.dom.DOMUtils")}),g("q",["d"],function(a){return a("tinymce.geom.Rect")}),g("r",[],function(){var a=functi
on(a){return{x:a.left,y:a.top,w:a.width,h:a.height}},b=function(a){return{left:a.x,top:a.y,width:a.w,height:a.h,right:a.x+a.w,bottom:a.y+a.h}};return{fromClientRect:a,toClientRect:b}}),g("f",["i","q","r"],function(a,b,c){var d=function(b){var c=a.DOM.getViewPort();return{x:b.x+c.x,y:b.y+c.y,w:b.w,h:b.h}},e=function(a){var b=a.getBoundingClientRect();return d({x:b.left,y:b.top,w:Math.max(a.clientWidth,a.offsetWidth),h:Math.max(a.clientHeight,a.offsetHeight)})},f=function(a,b){return e(b)},g=function(a){return e(a.getElement().ownerDocument.body)},h=function(a){return e(a.getContentAreaContainer()||a.getBody())},i=function(a){var b=a.selection.getBoundingClientRect();return b?d(c.fromClientRect(b)):null};return{getElementRect:f,getPageAreaRect:g,getContentAreaRect:h,getSelectionRect:i}}),g("6",["7","f"],function(a,b){var c=function(c,d){return function(e){for(var f=0;f<d.length;f++)if(d[f].predicate(c))return a.r
esult(d[f].id,b.getElementRect(e,c));return null}},d=function(c,d){return function(e){for(var f=0;f<c.length;f++)for(var g=0;g<d.length;g++)if(d[g].predicate(c[f]))return a.result(d[g].id,b.getElementRect(e,c[f]));return null}};return{element:c,parent:d}}),g("g",["d"],function(a){return a("tinymce.util.Tools")}),g("8",["g"],function(a){var b=function(a,b){return{id:a,predicate:b}},c=function(c){return a.map(c,function(a){return b(a.id,a.predicate)})};return{create:b,fromContextToolbars:c}}),g("9",["7","f"],function(a,b){var c=function(c){return function(d){return d.selection.isCollapsed()?null:a.result(c,b.getSelectionRect(d))}},d=function(c,d){return function(e){var f,g=e.schema.getTextBlockElements();for(f=0;f<c.length;f++)if("TABLE"===c[f].nodeName)return null;for(f=0;f<c.length;f++)if(c[f].nodeName in g)return e.dom.isEmpty(c[f])?a.result(d,b.getSelectionRect(e)):null;return nul
l}};return{textSelection:c,emptyTextBlock:d}}),g("h",["d"],function(a){return a("tinymce.EditorManager")}),g("a",["h","i"],function(a,b){var c=function(a,b){var c=function(){a._skinLoaded=!0,a.fire("SkinLoaded"),b()};a.initialized?c():a.on("init",c)},d=function(b){var c=a.baseURL+"/skins/";return b?c+b:c+"lightgray"},e=function(a,b){return a.documentBaseURI.toAbsolute(b)},f=function(a,f){var g=a.settings,h=g.skin_url?e(a,g.skin_url):d(g.skin),i=function(){c(a,f)};b.DOM.styleSheetLoader.load(h+"/skin.min.css",i),a.contentCSS.push(h+"/content.inline.min.css")};return{load:f}}),g("j",["d"],function(a){return a("tinymce.ui.Factory")}),g("k",["g","j","e"],function(a,b,c){var d=function(a,b){var c=function(a,b){return{selector:a,handler:b}},d=function(a){b.active(a)},e=function(a){b.disabled(a)};return
b.settings.stateSelector?c(b.settings.stateSelector,d):b.settings.disabledStateSelector?c(b.settings.disabledStateSelector,e):null},e=function(a,b,c){return function(){var e=d(b,c);null!==e&&a.selection.selectorChanged(e.selector,e.handler)}},f=function(a){return c.isArray(a)?a:c.isString(a)?a.split(/[ ,]/):[]},g=function(c,d,g){var h,i=[];if(g)return a.each(f(g),function(a){var d;"|"==a?h=null:c.buttons[a]&&(h||(h={type:"buttongroup",items:[]},i.push(h)),d=a,a=c.buttons[d],"function"==typeof a&&(a=a()),a.type=a.type||"button",a=b.create(a),a.on("postRender",e(c,d,a)),h.items.push(a))}),b.create({type:"toolbar",layout:"flow",name:d,items:i})};return{create:g}}),g("s",["d"],function(a){return a("tinymce.util.Promise")}),g("t",[],function(){var a=0,b=function(){var a=function(){return Math.round(4294967295*Math.random()).toString(36)};return"s&quo
t;+Date.now().toString(36)+a()+a()+a()},c=function(c){return c+a++ +b()};return{uuid:c}}),g("w",[],function(){var a=function(a,b){function c(c){var e,f,g;f=b[c?"startContainer":"endContainer"],g=b[c?"startOffset":"endOffset"],1==f.nodeType&&(e=a.create("span",{"data-mce-type":"bookmark"}),f.hasChildNodes()?(g=Math.min(g,f.childNodes.length-1),c?f.insertBefore(e,f.childNodes[g]):a.insertAfter(e,f.childNodes[g])):f.appendChild(e),f=e,g=0),d[c?"startContainer":"endContainer"]=f,d[c?"startOffset":"endOffset"]=g}var d={};return c(!0),b.collapsed||c(),d},b=function(a,b){function c(c){function d(a){for(var b=a.parentNode.firstChild,c=0;b;){if(b==a)return c;1==b.nodeType&&"bookmark"==b.getAttribute("data-mce-type")||c++,b=b.nextSibling}return-1}var e,f,g;e=g=b[c?"startContainer":"endContainer"],f=b[c?"startOffset
":"endOffset"],e&&(1==e.nodeType&&(f=d(e),e=e.parentNode,a.remove(g)),b[c?"startContainer":"endContainer"]=e,b[c?"startOffset":"endOffset"]=f)}c(!0),c();var d=a.createRng();return d.setStart(b.startContainer,b.startOffset),b.endContainer&&d.setEnd(b.endContainer,b.endOffset),d};return{create:a,resolve:b}}),g("x",["d"],function(a){return a("tinymce.dom.TreeWalker")}),g("y",["d"],function(a){return a("tinymce.dom.RangeUtils")}),g("u",["w","g","x","y"],function(a,b,c,d){var e=function(a,b,d){var e,f,g=[];for(e=new c(b,a),f=b;f&&(1===f.nodeType&&g.push(f),f!==d);f=e.next());return g},f=function(c,d){var e,f,g;f=c.dom,g=c.selection,e=a.create(f,g.getRng()),b.each(d,function(a){c.dom.remove(a,!0)}),g.setRng(a.resolve(f,e))},g=function(a){return"A"===a.nodeName&&a.hasAtt
ribute("href")},h=function(a,b){var c=a.getParent(b,g);return c?c:b},i=function(a){var c,f,i,j,k,l,m;return k=a.selection,l=a.dom,m=k.getRng(),c=h(l,d.getNode(m.startContainer,m.startOffset)),f=d.getNode(m.endContainer,m.endOffset),i=a.getBody(),j=b.grep(e(i,c,f),g)},j=function(a){f(a,i(a))};return{unlinkSelection:j}}),g("p",["t","u"],function(a,b){var c=function(a,b){var c,d,e;for(e='<table data-mce-id="mce" style="width: 100%">',e+="<tbody>",d=0;d<b;d++){for(e+="<tr>",c=0;c<a;c++)e+="<td><br></td>";e+="</tr>"}return e+="</tbody>",e+="</table>"},d=function(a){var b=a.dom.select("*[data-mce-id]");return b[0]},e=function(a,b,e){a.undoManager.transact(function(){var f,g;a.insertContent(c(b,e)),f=d(a),f.removeAttribute("data-mce-id"),g=a.dom.select("td,th",f),a.selection.setCurso
rLocation(g[0],0)})},f=function(a,b){a.execCommand("FormatBlock",!1,b)},g=function(b,c,d){var e,f;e=b.editorUpload.blobCache,f=e.create(a.uuid("mceu"),d,c),e.add(f),b.insertContent(b.dom.createHTML("img",{src:f.blobUri()}))},h=function(a){a.selection.collapse(!1)},i=function(a){a.focus(),b.unlinkSelection(a),h(a)},j=function(a,b,c){a.focus(),a.dom.setAttrib(b,"href",c),h(a)},k=function(a,b){a.execCommand("mceInsertLink",!1,{href:b}),h(a)},l=function(a,b){var c=a.dom.getParent(a.selection.getStart(),"a[href]");c?j(a,c,b):k(a,b)},m=function(a,b){0===b.trim().length?i(a):l(a,b)};return{insertTable:e,formatBlock:f,insertBlob:g,createLink:m,unlink:i}}),g("v",[],function(){var a=function(a){return/^www\.|\.(com|org|edu|gov|uk|net|ca|de|jp|fr|au|us|ru|ch|it|nl|se|no|es|mil)$/i.test(a.trim())},b=function(a){return/^https?:\/\//.test(a.trim())};return{isDomainLike:a,isAbsolute:b}}),g("l",["g","j&qu
ot;,"s","p","v"],function(a,b,c,d,e){var f=function(a){a.find("textbox").eq(0).each(function(a){a.focus()})},g=function(c,d){var e=b.create(a.extend({type:"form",layout:"flex",direction:"row",padding:5,name:c,spacing:3},d));return e.on("show",function(){f(e)}),e},h=function(a,b){return b?a.show():a.hide()},i=function(a,b){return new c(function(c){a.windowManager.confirm("The URL you entered seems to be an external link. Do you want to add the required http:// prefix?",function(a){var d=a===!0?"http://"+b:b;c(d)})})},j=function(a,b){return!e.isAbsolute(b)&&e.isDomainLike(b)?i(a,b):c.resolve(b)},k=function(a,b){var c={},e=function(){a.focus(),d.unlink(a),b()},f=function(a){var b=a.meta;b&&b.attach&&(c={href:this.value(),attach:b.attach})},i=function(b){if(b.control===this){var c,d="";c=a.dom.getParent(a.selection.getStart(),"a[href]"),c&&a
mp;(d=a.dom.getAttrib(c,"href")),this.fromJSON({linkurl:d}),h(this.find("#unlink"),c),this.find("#linkurl")[0].focus()}};return g("quicklink",{items:[{type:"button",name:"unlink",icon:"unlink",onclick:e,tooltip:"Remove link"},{type:"filepicker",name:"linkurl",placeholder:"Paste or type a link",filetype:"file",onchange:f},{type:"button",icon:"checkmark",subtype:"primary",tooltip:"Ok",onclick:"submit"}],onshow:i,onsubmit:function(e){j(a,e.data.linkurl).then(function(e){a.undoManager.transact(function(){e===c.href&&(c.attach(),c={}),d.createLink(a,e)}),b()})}})};return{createQuickLinkForm:k}}),g("m",["q","r"],function(a,b){var c=function(a,b){return{rect:a,position:b}},d=function(a,b){return{x:b.x,y:b.y,w:a.w,h:a.h}},e=function(b,e,f,g,h){var i,j,k;return i=a.findBestRelativePositi
on(h,f,g,b),f=a.clamp(f,g),i?(j=a.relativePosition(h,f,i),k=d(h,j),c(k,i)):(f=a.intersect(g,f),f?(i=a.findBestRelativePosition(h,f,g,e))?(j=a.relativePosition(h,f,i),k=d(h,j),c(k,i)):(k=d(h,f),c(k,i)):null)},f=function(a,b,c){return e(["cr-cl","cl-cr"],["bc-tc","bl-tl","br-tr"],a,b,c)},g=function(a,b,c){return e(["tc-bc","bc-tc","tl-bl","bl-tl","tr-br","br-tr"],["bc-tc","bl-tl","br-tr"],a,b,c)},h=function(a,c,d,e){var f;return"function"==typeof a?(f=a({elementRect:b.toClientRect(c),contentAreaRect:b.toClientRect(d),panelRect:b.toClientRect(e)}),b.fromClientRect(f)):e},i=function(a){return a.panelRect};return{calcInsert:f,calc:g,userConstrain:h,defaultHandler:i}}),g("c",["g","j","i","k","l","f","m","5"],function(a,b,c,d,e,f,g,h){return function(){v
ar i,j,k=["bold","italic","|","quicklink","h2","h3","blockquote"],l=["quickimage","quicktable"],m=function(b,c){return a.map(c,function(a){return d.create(b,a.id,a.items)})},n=function(a){return h.getToolbarItemsOr(a,"selection_toolbar",k)},o=function(a){return h.getToolbarItemsOr(a,"insert_toolbar",l)},p=function(a){return a.items().length>0},q=function(c,f){var g=m(c,f).concat([d.create(c,"text",n(c)),d.create(c,"insert",o(c)),e.createQuickLinkForm(c,B)]);return b.create({type:"floatpanel",role:"dialog",classes:"tinymce tinymce-inline arrow",ariaLabel:"Inline toolbar",layout:"flex",direction:"column",align:"stretch",autohide:!1,autofix:!0,fixed:!0,border:1,items:a.grep(g,p),oncancel:function(){c.focus()}})},r=function(a){a&&a.show()},s=function(a,b){a.moveTo(b.x,b.y)},t=fun
ction(b,c){c=c?c.substr(0,2):"",a.each({t:"down",b:"up",c:"center"},function(a,d){b.classes.toggle("arrow-"+a,d===c.substr(0,1))}),"cr"===c?(b.classes.toggle("arrow-left",!0),b.classes.toggle("arrow-right",!1)):"cl"===c?(b.classes.toggle("arrow-left",!0),b.classes.toggle("arrow-right",!0)):a.each({l:"left",r:"right"},function(a,d){b.classes.toggle("arrow-"+a,d===c.substr(1,1))})},u=function(a,b){var c=a.items().filter("#"+b);return c.length>0&&(c[0].show(),a.reflow(),!0)},v=function(a,b,d,e){var i,k,l,m;return m=h.getHandlerOr(d,"inline_toolbar_position_handler",g.defaultHandler),i=f.getContentAreaRect(d),k=c.DOM.getRect(a.getEl()),l="insert"===b?g.calcInsert(e,i,k):g.calc(e,i,k),!!l&&(k=l.rect,j=e,s(a,g.userConstrain(m,e,i,k)),t(a,l.position),!0)},w=function(a,b,c,d){return r(a),a.items().hide(),
u(a,b)?void(v(a,b,c,d)===!1&&B(a)):void B(a)},x=function(){return i.items().filter("form:visible").length>0},y=function(a,b){if(i){if(i.items().hide(),!u(i,b))return void B(i);var d,e,k,l;r(i),i.items().hide(),u(i,b),l=h.getHandlerOr(a,"inline_toolbar_position_handler",g.defaultHandler),d=f.getContentAreaRect(a),e=c.DOM.getRect(i.getEl()),k=g.calc(j,d,e),k&&(e=k.rect,s(i,g.userConstrain(l,j,d,e)),t(i,k.position))}},z=function(a,b,c,d){i||(i=q(a,d),i.renderTo(document.body).reflow().moveTo(c.x,c.y),a.nodeChanged()),w(i,b,a,c)},A=function(a,b,c){i&&v(i,b,a,c)},B=function(){i&&i.hide()},C=function(){i&&i.find("toolbar:visible").eq(0).each(function(a){a.focus(!0)})},D=function(){i&&(i.remove(),i=null)},E=function(){return i&&i.visible()&&x()};return{show:z,showForm:y,reposition:A,inForm:E,hide:B,focus:C,remove:D}}}),g("n",["s"],function(a){var b=function(b){return new a(f
unction(a){var c=new FileReader;c.onloadend=function(){a(c.result.split(",")[1])},c.readAsDataURL(b)})};return{blobToBase64:b}}),g("o",["s"],function(a){var b=function(){return new a(function(a){var b;b=document.createElement("input"),b.type="file",b.style.position="fixed",b.style.left=0,b.style.top=0,b.style.opacity=.001,document.body.appendChild(b),b.onchange=function(b){a(Array.prototype.slice.call(b.target.files))},b.click(),b.parentNode.removeChild(b)})};return{pickFile:b}}),g("b",["c","n","o","p"],function(a,b,c,d){var e=function(a){for(var b=function(b){return function(){d.formatBlock(a,b)}},c=1;c<6;c++){var e="h"+c;a.addButton(e,{text:e.toUpperCase(),tooltip:"Heading "+c,stateSelector:e,onclick:b(e),onPostRender:function(){var a=this.getEl().firstChild.firstChild;a.style.fontWeight="bold"}})}},f=function(a,f){a.addButton("quickli
nk",{icon:"link",tooltip:"Insert/Edit link",stateSelector:"a[href]",onclick:function(){f.showForm(a,"quicklink")}}),a.addButton("quickimage",{icon:"image",tooltip:"Insert image",onclick:function(){c.pickFile().then(function(c){var e=c[0];b.blobToBase64(e).then(function(b){d.insertBlob(a,b,e)})})}}),a.addButton("quicktable",{icon:"table",tooltip:"Insert table",onclick:function(){f.hide(),d.insertTable(a,2,2)}}),e(a)};return{addToEditor:f}}),g("0",["1","2","3","4","5","6","7","8","9","a","b","c"],function(a,b,c,d,e,f,g,h,i,j,k,l){var m=function(a){var b=a.selection.getNode(),c=a.dom.getParents(b);return c},n=function(a,b,c,d){var e=function(c){return a.dom.is(c,b)};return{predicate:e,id:c,items:d}},o=function(a){var b=a.contextToolbars;return d.flatten([
b?b:[],n(a,"img","image","alignleft aligncenter alignright")])},p=function(a,b){var c,d,e;return d=m(a),e=h.fromContextToolbars(b),c=g.match(a,[f.element(d[0],e),i.textSelection("text"),i.emptyTextBlock(d,"insert"),f.parent(d,e)]),c&&c.rect?c:null},q=function(a,b){var c=function(){var c=o(a),d=p(a,c);d?b.show(a,d.id,d.rect,c):b.hide()};return function(){a.removed||c()}},r=function(a,b){return function(){var c=o(a),d=p(a,c);d&&b.reposition(a,d.id,d.rect)}},s=function(a,b,c){return function(){a.removed||b.inForm()||c()}},t=function(a,b){var d=c.throttle(q(a,b),0),e=c.throttle(s(a,b,q(a,b)),0);a.on("blur hide ObjectResizeStart",b.hide),a.on("click",d),a.on("nodeChange mouseup",e),a.on("ResizeEditor keyup",d),a.on("ResizeWindow",r(a,b)),a.on("remove",b.remove),a.shortcuts.add("Alt+F10","",b.focus)},u=function(a,b){a.shortcuts.remove("meta
+k"),a.shortcuts.add("meta+k","",function(){var c=o(a),d=d=g.match(a,[i.textSelection("quicklink")]);d&&b.show(a,d.id,d.rect,c)})},v=function(a,b){return j.load(a,function(){t(a,b),u(a,b)}),{}},w=function(a){throw new Error(a)};return a.add("inlite",function(a){var b=new l;k.addToEditor(a,b);var c=function(){return a.inline?v(a,b):w("inlite theme only supports inline mode.")};return{renderUI:c}}),b.appendTo(window.tinymce?window.tinymce:{}),function(){}}),d("0")()}();
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcethemesmodernthemejs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/themes/modern/theme.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/themes/modern/theme.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/themes/modern/theme.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -81,296 +81,435 @@
</span><span class="cx" style="display: block; padding: 0 10px"> define(id, [], function () { return ref; });
</span><span class="cx" style="display: block; padding: 0 10px"> };
</span><span class="cx" style="display: block; padding: 0 10px"> /*jsc
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-["tinymce.modern.Theme","global!tinymce.Env","global!tinymce.EditorManager","global!tinymce.ThemeManager","tinymce.modern.modes.Iframe","tinymce.modern.modes.Inline","tinymce.modern.ui.Resize","tinymce.modern.ui.ProgressState","global!tinymce.util.Tools","global!tinymce.ui.Factory","global!tinymce.DOM","tinymce.modern.ui.Toolbar","tinymce.modern.ui.Menubar","tinymce.modern.ui.ContextToolbars","tinymce.modern.ui.A11y","tinymce.modern.ui.Sidebar","tinymce.modern.ui.SkinLoaded","global!tinymce.ui.FloatPanel","global!tinymce.ui.Throbber","global!tinymce.util.Delay","global!tinymce.geom.Rect"]
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+["tinymce.themes.modern.Theme","global!window","tinymce.core.AddOnManager","tinymce.core.EditorManager","tinymce.core.Env","tinymce.core.ui.Api","tinymce.themes.modern.modes.Iframe","tinymce.themes.modern.modes.Inline","tinymce.themes.modern.ui.ProgressState","tinymce.themes.modern.ui.Resize","global!tinymce.util.Tools.resolve","tinymce.core.dom.DOMUtils","tinymce.core.ui.Factory","tinymce.core.util.Tools","tinymce.themes.modern.ui.A11y","tinymce.themes.modern.ui.Branding","tinymce.themes.modern.ui.ContextToolbars","tinymce.themes.modern.ui.Menubar","tinymce.themes.modern.ui.Sidebar","tinymce.themes.modern.ui.SkinLoaded","tinymce.themes.modern.ui.Toolbar","tinymce.core.ui.Float
Panel","tinymce.core.ui.Throbber","tinymce.core.util.Delay","tinymce.core.geom.Rect"]
</ins><span class="cx" style="display: block; padding: 0 10px"> jsc*/
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-defineGlobal("global!tinymce.Env", tinymce.Env);
-defineGlobal("global!tinymce.EditorManager", tinymce.EditorManager);
-defineGlobal("global!tinymce.ThemeManager", tinymce.ThemeManager);
-defineGlobal("global!tinymce.util.Tools", tinymce.util.Tools);
-defineGlobal("global!tinymce.ui.Factory", tinymce.ui.Factory);
-defineGlobal("global!tinymce.DOM", tinymce.DOM);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+defineGlobal("global!window", window);
+defineGlobal("global!tinymce.util.Tools.resolve", tinymce.util.Tools.resolve);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Toolbar.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ResolveGlobal.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce.modern.ui.Toolbar', [
- 'global!tinymce.util.Tools',
- 'global!tinymce.ui.Factory'
-], function (Tools, Factory) {
- var defaultToolbar = "undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | " +
- "bullist numlist outdent indent | link image";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.AddOnManager',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.AddOnManager');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var createToolbar = function (editor, items, size) {
- var toolbarItems = [], buttonGroup;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!items) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.EditorManager',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.EditorManager');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(items.split(/[ ,]/), function(item) {
- var itemName;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var bindSelectorChanged = function () {
- var selection = editor.selection;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.Env',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.Env');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (item.settings.stateSelector) {
- selection.selectorChanged(item.settings.stateSelector, function(state) {
- item.active(state);
- }, true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (item.settings.disabledStateSelector) {
- selection.selectorChanged(item.settings.disabledStateSelector, function(state) {
- item.disabled(state);
- });
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Api',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.ui.Api');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (item == "|") {
- buttonGroup = null;
- } else {
- if (Factory.has(item)) {
- item = {type: item, size: size};
- toolbarItems.push(item);
- buttonGroup = null;
- } else {
- if (!buttonGroup) {
- buttonGroup = {type: 'buttongroup', items: []};
- toolbarItems.push(buttonGroup);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.buttons[item]) {
- // TODO: Move control creation to some UI class
- itemName = item;
- item = editor.buttons[itemName];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.DOMUtils',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.dom.DOMUtils');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof item == "function") {
- item = item();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- item.type = item.type || 'button';
- item.size = size;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Factory',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.ui.Factory');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- item = Factory.create(item);
- buttonGroup.items.push(item);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.initialized) {
- bindSelectorChanged();
- } else {
- editor.on('init', bindSelectorChanged);
- }
- }
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.Tools',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.util.Tools');
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- type: 'toolbar',
- layout: 'flow',
- items: toolbarItems
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * A11y.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates the toolbars from config and returns a toolbar array.
- *
- * @param {String} size Optional toolbar item size.
- * @return {Array} Array with toolbars.
- */
- var createToolbars = function (editor, size) {
- var toolbars = [], settings = editor.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.modern.ui.A11y',
+ [
+ ],
+ function () {
+ var focus = function (panel, type) {
+ return function () {
+ var item = panel.find(type)[0];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var addToolbar = function (items) {
- if (items) {
- toolbars.push(createToolbar(editor, items, size));
- return true;
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (item) {
+ item.focus(true);
+ }
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Convert toolbar array to multiple options
- if (Tools.isArray(settings.toolbar)) {
- // Empty toolbar array is the same as a disabled toolbar
- if (settings.toolbar.length === 0) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var addKeys = function (editor, panel) {
+ editor.shortcuts.add('Alt+F9', '', focus(panel, 'menubar'));
+ editor.shortcuts.add('Alt+F10,F10', '', focus(panel, 'toolbar'));
+ editor.shortcuts.add('Alt+F11', '', focus(panel, 'elementpath'));
+ panel.on('cancel', function () {
+ editor.focus();
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(settings.toolbar, function(toolbar, i) {
- settings["toolbar" + (i + 1)] = toolbar;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ addKeys: addKeys
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- delete settings.toolbar;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Branding.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Generate toolbar<n>
- for (var i = 1; i < 10; i++) {
- if (!addToolbar(settings["toolbar" + i])) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.modern.ui.Branding',
+ [
+ 'tinymce.core.dom.DOMUtils'
+ ],
+ function (DOMUtils) {
+ var DOM = DOMUtils.DOM;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Generate toolbar or default toolbar unless it's disabled
- if (!toolbars.length && settings.toolbar !== false) {
- addToolbar(settings.toolbar || defaultToolbar);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var reposition = function (editor, poweredByElm) {
+ return function () {
+ var iframeWidth = editor.getContentAreaContainer().querySelector('iframe').offsetWidth;
+ var scrollbarWidth = Math.max(iframeWidth - editor.getDoc().documentElement.offsetWidth, 0);
+ var statusbarElm = editor.getContainer().querySelector('.mce-statusbar');
+ var statusbarHeight = statusbarElm ? statusbarElm.offsetHeight : 1;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (toolbars.length) {
- return {
- type: 'panel',
- layout: 'stack',
- classes: "toolbar-grp",
- ariaRoot: true,
- ariaRemember: true,
- items: toolbars
- };
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOM.setStyles(poweredByElm, {
+ right: scrollbarWidth + 'px',
+ bottom: statusbarHeight + 'px'
+ });
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- createToolbar: createToolbar,
- createToolbars: createToolbars
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var hide = function (poweredByElm) {
+ return function () {
+ DOM.hide(poweredByElm);
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var setupEventListeners = function (editor) {
+ editor.on('SkinLoaded', function () {
+ var poweredByElm = DOM.create('div', { 'class': 'mce-branding-powered-by' });
+ editor.getContainer().appendChild(poweredByElm);
+ DOM.bind(poweredByElm, 'click', hide(poweredByElm));
+ editor.on('NodeChange ResizeEditor', reposition(editor, poweredByElm));
+ });
+ };
+
+ var setup = function (editor) {
+ if (editor.settings.branding !== false) {
+ setupEventListeners(editor);
+ }
+ };
+
+ return {
+ setup: setup
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Menubar.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ResolveGlobal.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.core.util.Delay',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.util.Delay');
+ }
+);
+
+/**
+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.core.geom.Rect',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.geom.Rect');
+ }
+);
+
+/**
+ * Toolbar.js
+ *
+ * Released under LGPL License.
</ins><span class="cx" style="display: block; padding: 0 10px"> * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce.modern.ui.Menubar', [
- 'global!tinymce.util.Tools'
-], function (Tools) {
- var defaultMenus = {
- file: {title: 'File', items: 'newdocument'},
- edit: {title: 'Edit', items: 'undo redo | cut copy paste pastetext | selectall'},
- insert: {title: 'Insert', items: '|'},
- view: {title: 'View', items: 'visualaid |'},
- format: {title: 'Format', items: 'bold italic underline strikethrough superscript subscript | formats | removeformat'},
- table: {title: 'Table'},
- tools: {title: 'Tools'}
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.modern.ui.Toolbar',
+ [
+ 'tinymce.core.util.Tools',
+ 'tinymce.core.ui.Factory'
+ ],
+ function (Tools, Factory) {
+ var defaultToolbar = "undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | " +
+ "bullist numlist outdent indent | link image";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var createMenuItem = function (menuItems, name) {
- var menuItem;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createToolbar = function (editor, items, size) {
+ var toolbarItems = [], buttonGroup;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name == '|') {
- return {text: '|'};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!items) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- menuItem = menuItems[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(items.split(/[ ,]/), function (item) {
+ var itemName;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return menuItem;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var bindSelectorChanged = function () {
+ var selection = editor.selection;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var createMenu = function (editorMenuItems, settings, context) {
- var menuButton, menu, menuItems, isUserDefined, removedMenuItems;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (item.settings.stateSelector) {
+ selection.selectorChanged(item.settings.stateSelector, function (state) {
+ item.active(state);
+ }, true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- removedMenuItems = Tools.makeMap((settings.removed_menuitems || '').split(/[ ,]/));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (item.settings.disabledStateSelector) {
+ selection.selectorChanged(item.settings.disabledStateSelector, function (state) {
+ item.disabled(state);
+ });
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // User defined menu
- if (settings.menu) {
- menu = settings.menu[context];
- isUserDefined = true;
- } else {
- menu = defaultMenus[context];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (item == "|") {
+ buttonGroup = null;
+ } else {
+ if (!buttonGroup) {
+ buttonGroup = { type: 'buttongroup', items: [] };
+ toolbarItems.push(buttonGroup);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (menu) {
- menuButton = {text: menu.title};
- menuItems = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.buttons[item]) {
+ // TODO: Move control creation to some UI class
+ itemName = item;
+ item = editor.buttons[itemName];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Default/user defined items
- Tools.each((menu.items || '').split(/[ ,]/), function(item) {
- var menuItem = createMenuItem(editorMenuItems, item);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof item == "function") {
+ item = item();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (menuItem && !removedMenuItems[item]) {
- menuItems.push(createMenuItem(editorMenuItems, item));
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ item.type = item.type || 'button';
+ item.size = size;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Added though context
- if (!isUserDefined) {
- Tools.each(editorMenuItems, function(menuItem) {
- if (menuItem.context == context) {
- if (menuItem.separator == 'before') {
- menuItems.push({text: '|'});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ item = Factory.create(item);
+ buttonGroup.items.push(item);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (menuItem.prependToContext) {
- menuItems.unshift(menuItem);
- } else {
- menuItems.push(menuItem);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.initialized) {
+ bindSelectorChanged();
+ } else {
+ editor.on('init', bindSelectorChanged);
+ }
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (menuItem.separator == 'after') {
- menuItems.push({text: '|'});
- }
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ type: 'toolbar',
+ layout: 'flow',
+ items: toolbarItems
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var i = 0; i < menuItems.length; i++) {
- if (menuItems[i].text == '|') {
- if (i === 0 || i == menuItems.length - 1) {
- menuItems.splice(i, 1);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates the toolbars from config and returns a toolbar array.
+ *
+ * @param {String} size Optional toolbar item size.
+ * @return {Array} Array with toolbars.
+ */
+ var createToolbars = function (editor, size) {
+ var toolbars = [], settings = editor.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- menuButton.menu = menuItems;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var addToolbar = function (items) {
+ if (items) {
+ toolbars.push(createToolbar(editor, items, size));
+ return true;
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!menuButton.menu.length) {
- return null;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Convert toolbar array to multiple options
+ if (Tools.isArray(settings.toolbar)) {
+ // Empty toolbar array is the same as a disabled toolbar
+ if (settings.toolbar.length === 0) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return menuButton;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(settings.toolbar, function (toolbar, i) {
+ settings["toolbar" + (i + 1)] = toolbar;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var createMenuButtons = function (editor) {
- var name, menuButtons = [], settings = editor.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ delete settings.toolbar;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var defaultMenuBar = [];
- if (settings.menu) {
- for (name in settings.menu) {
- defaultMenuBar.push(name);
- }
- } else {
- for (name in defaultMenus) {
- defaultMenuBar.push(name);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Generate toolbar<n>
+ for (var i = 1; i < 10; i++) {
+ if (!addToolbar(settings["toolbar" + i])) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var enabledMenuNames = typeof settings.menubar == "string" ? settings.menubar.split(/[ ,]/) : defaultMenuBar;
- for (var i = 0; i < enabledMenuNames.length; i++) {
- var menu = enabledMenuNames[i];
- menu = createMenu(editor.menuItems, editor.settings, menu);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Generate toolbar or default toolbar unless it's disabled
+ if (!toolbars.length && settings.toolbar !== false) {
+ addToolbar(settings.toolbar || defaultToolbar);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (menu) {
- menuButtons.push(menu);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (toolbars.length) {
+ return {
+ type: 'panel',
+ layout: 'stack',
+ classes: "toolbar-grp",
+ ariaRoot: true,
+ ariaRemember: true,
+ items: toolbars
+ };
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return menuButtons;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ createToolbar: createToolbar,
+ createToolbars: createToolbars
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- createMenuButtons: createMenuButtons
- };
-});
-
-defineGlobal("global!tinymce.util.Delay", tinymce.util.Delay);
-defineGlobal("global!tinymce.geom.Rect", tinymce.geom.Rect);
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * ContextToolbars.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -381,319 +520,325 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce.modern.ui.ContextToolbars', [
- 'global!tinymce.DOM',
- 'global!tinymce.util.Tools',
- 'global!tinymce.util.Delay',
- 'tinymce.modern.ui.Toolbar',
- 'global!tinymce.ui.Factory',
- 'global!tinymce.geom.Rect'
-], function (DOM, Tools, Delay, Toolbar, Factory, Rect) {
- var toClientRect = function (geomRect) {
- return {
- left: geomRect.x,
- top: geomRect.y,
- width: geomRect.w,
- height: geomRect.h,
- right: geomRect.x + geomRect.w,
- bottom: geomRect.y + geomRect.h
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.modern.ui.ContextToolbars',
+ [
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.core.util.Tools',
+ 'tinymce.core.util.Delay',
+ 'tinymce.core.ui.Factory',
+ 'tinymce.core.geom.Rect',
+ 'tinymce.themes.modern.ui.Toolbar'
+ ],
+ function (DOMUtils, Tools, Delay, Factory, Rect, Toolbar) {
+ var DOM = DOMUtils.DOM;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var hideAllFloatingPanels = function (editor) {
- Tools.each(editor.contextToolbars, function(toolbar) {
- if (toolbar.panel) {
- toolbar.panel.hide();
- }
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var toClientRect = function (geomRect) {
+ return {
+ left: geomRect.x,
+ top: geomRect.y,
+ width: geomRect.w,
+ height: geomRect.h,
+ right: geomRect.x + geomRect.w,
+ bottom: geomRect.y + geomRect.h
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var movePanelTo = function (panel, pos) {
- panel.moveTo(pos.left, pos.top);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var hideAllFloatingPanels = function (editor) {
+ Tools.each(editor.contextToolbars, function (toolbar) {
+ if (toolbar.panel) {
+ toolbar.panel.hide();
+ }
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var togglePositionClass = function (panel, relPos, predicate) {
- relPos = relPos ? relPos.substr(0, 2) : '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var movePanelTo = function (panel, pos) {
+ panel.moveTo(pos.left, pos.top);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each({
- t: 'down',
- b: 'up'
- }, function(cls, pos) {
- panel.classes.toggle('arrow-' + cls, predicate(pos, relPos.substr(0, 1)));
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var togglePositionClass = function (panel, relPos, predicate) {
+ relPos = relPos ? relPos.substr(0, 2) : '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each({
- l: 'left',
- r: 'right'
- }, function(cls, pos) {
- panel.classes.toggle('arrow-' + cls, predicate(pos, relPos.substr(1, 1)));
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each({
+ t: 'down',
+ b: 'up'
+ }, function (cls, pos) {
+ panel.classes.toggle('arrow-' + cls, predicate(pos, relPos.substr(0, 1)));
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var userConstrain = function (handler, x, y, elementRect, contentAreaRect, panelRect) {
- panelRect = toClientRect({x: x, y: y, w: panelRect.w, h: panelRect.h});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each({
+ l: 'left',
+ r: 'right'
+ }, function (cls, pos) {
+ panel.classes.toggle('arrow-' + cls, predicate(pos, relPos.substr(1, 1)));
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (handler) {
- panelRect = handler({
- elementRect: toClientRect(elementRect),
- contentAreaRect: toClientRect(contentAreaRect),
- panelRect: panelRect
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var userConstrain = function (handler, x, y, elementRect, contentAreaRect, panelRect) {
+ panelRect = toClientRect({ x: x, y: y, w: panelRect.w, h: panelRect.h });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return panelRect;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (handler) {
+ panelRect = handler({
+ elementRect: toClientRect(elementRect),
+ contentAreaRect: toClientRect(contentAreaRect),
+ panelRect: panelRect
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var addContextualToolbars = function (editor) {
- var scrollContainer, settings = editor.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return panelRect;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getContextToolbars = function () {
- return editor.contextToolbars || [];
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var addContextualToolbars = function (editor) {
+ var scrollContainer, settings = editor.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getElementRect = function (elm) {
- var pos, targetRect, root;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getContextToolbars = function () {
+ return editor.contextToolbars || [];
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- pos = DOM.getPos(editor.getContentAreaContainer());
- targetRect = editor.dom.getRect(elm);
- root = editor.dom.getRoot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getElementRect = function (elm) {
+ var pos, targetRect, root;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Adjust targetPos for scrolling in the editor
- if (root.nodeName === 'BODY') {
- targetRect.x -= root.ownerDocument.documentElement.scrollLeft || root.scrollLeft;
- targetRect.y -= root.ownerDocument.documentElement.scrollTop || root.scrollTop;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ pos = DOM.getPos(editor.getContentAreaContainer());
+ targetRect = editor.dom.getRect(elm);
+ root = editor.dom.getRoot();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- targetRect.x += pos.x;
- targetRect.y += pos.y;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Adjust targetPos for scrolling in the editor
+ if (root.nodeName === 'BODY') {
+ targetRect.x -= root.ownerDocument.documentElement.scrollLeft || root.scrollLeft;
+ targetRect.y -= root.ownerDocument.documentElement.scrollTop || root.scrollTop;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return targetRect;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ targetRect.x += pos.x;
+ targetRect.y += pos.y;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var reposition = function (match, shouldShow) {
- var relPos, panelRect, elementRect, contentAreaRect, panel, relRect, testPositions, smallElementWidthThreshold;
- var handler = settings.inline_toolbar_position_handler;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return targetRect;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.removed) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var reposition = function (match, shouldShow) {
+ var relPos, panelRect, elementRect, contentAreaRect, panel, relRect, testPositions, smallElementWidthThreshold;
+ var handler = settings.inline_toolbar_position_handler;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!match || !match.toolbar.panel) {
- hideAllFloatingPanels(editor);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.removed) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- testPositions = [
- 'bc-tc', 'tc-bc',
- 'tl-bl', 'bl-tl',
- 'tr-br', 'br-tr'
- ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!match || !match.toolbar.panel) {
+ hideAllFloatingPanels(editor);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- panel = match.toolbar.panel;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ testPositions = [
+ 'bc-tc', 'tc-bc',
+ 'tl-bl', 'bl-tl',
+ 'tr-br', 'br-tr'
+ ];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Only show the panel on some events not for example nodeChange since that fires when context menu is opened
- if (shouldShow) {
- panel.show();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ panel = match.toolbar.panel;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elementRect = getElementRect(match.element);
- panelRect = DOM.getRect(panel.getEl());
- contentAreaRect = DOM.getRect(editor.getContentAreaContainer() || editor.getBody());
- smallElementWidthThreshold = 25;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Only show the panel on some events not for example nodeChange since that fires when context menu is opened
+ if (shouldShow) {
+ panel.show();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (DOM.getStyle(match.element, 'display', true) !== 'inline') {
- // We need to use these instead of the rect values since the style
- // size properites might not be the same as the real size for a table
- elementRect.w = match.element.clientWidth;
- elementRect.h = match.element.clientHeight;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elementRect = getElementRect(match.element);
+ panelRect = DOM.getRect(panel.getEl());
+ contentAreaRect = DOM.getRect(editor.getContentAreaContainer() || editor.getBody());
+ smallElementWidthThreshold = 25;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!editor.inline) {
- contentAreaRect.w = editor.getDoc().documentElement.offsetWidth;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (DOM.getStyle(match.element, 'display', true) !== 'inline') {
+ // We need to use these instead of the rect values since the style
+ // size properites might not be the same as the real size for a table
+ elementRect.w = match.element.clientWidth;
+ elementRect.h = match.element.clientHeight;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Inflate the elementRect so it doesn't get placed above resize handles
- if (editor.selection.controlSelection.isResizable(match.element) && elementRect.w < smallElementWidthThreshold) {
- elementRect = Rect.inflate(elementRect, 0, 8);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!editor.inline) {
+ contentAreaRect.w = editor.getDoc().documentElement.offsetWidth;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- relPos = Rect.findBestRelativePosition(panelRect, elementRect, contentAreaRect, testPositions);
- elementRect = Rect.clamp(elementRect, contentAreaRect);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Inflate the elementRect so it doesn't get placed above resize handles
+ if (editor.selection.controlSelection.isResizable(match.element) && elementRect.w < smallElementWidthThreshold) {
+ elementRect = Rect.inflate(elementRect, 0, 8);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (relPos) {
- relRect = Rect.relativePosition(panelRect, elementRect, relPos);
- movePanelTo(panel, userConstrain(handler, relRect.x, relRect.y, elementRect, contentAreaRect, panelRect));
- } else {
- // Allow overflow below the editor to avoid placing toolbars ontop of tables
- contentAreaRect.h += panelRect.h;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ relPos = Rect.findBestRelativePosition(panelRect, elementRect, contentAreaRect, testPositions);
+ elementRect = Rect.clamp(elementRect, contentAreaRect);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elementRect = Rect.intersect(contentAreaRect, elementRect);
- if (elementRect) {
- relPos = Rect.findBestRelativePosition(panelRect, elementRect, contentAreaRect, [
- 'bc-tc', 'bl-tl', 'br-tr'
- ]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (relPos) {
+ relRect = Rect.relativePosition(panelRect, elementRect, relPos);
+ movePanelTo(panel, userConstrain(handler, relRect.x, relRect.y, elementRect, contentAreaRect, panelRect));
+ } else {
+ // Allow overflow below the editor to avoid placing toolbars ontop of tables
+ contentAreaRect.h += panelRect.h;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (relPos) {
- relRect = Rect.relativePosition(panelRect, elementRect, relPos);
- movePanelTo(panel, userConstrain(handler, relRect.x, relRect.y, elementRect, contentAreaRect, panelRect));
- } else {
- movePanelTo(panel, userConstrain(handler, elementRect.x, elementRect.y, elementRect, contentAreaRect, panelRect));
- }
- } else {
- panel.hide();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elementRect = Rect.intersect(contentAreaRect, elementRect);
+ if (elementRect) {
+ relPos = Rect.findBestRelativePosition(panelRect, elementRect, contentAreaRect, [
+ 'bc-tc', 'bl-tl', 'br-tr'
+ ]);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- togglePositionClass(panel, relPos, function(pos1, pos2) {
- return pos1 === pos2;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (relPos) {
+ relRect = Rect.relativePosition(panelRect, elementRect, relPos);
+ movePanelTo(panel, userConstrain(handler, relRect.x, relRect.y, elementRect, contentAreaRect, panelRect));
+ } else {
+ movePanelTo(panel, userConstrain(handler, elementRect.x, elementRect.y, elementRect, contentAreaRect, panelRect));
+ }
+ } else {
+ panel.hide();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- //drawRect(contentAreaRect, 'blue');
- //drawRect(elementRect, 'red');
- //drawRect(panelRect, 'green');
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ togglePositionClass(panel, relPos, function (pos1, pos2) {
+ return pos1 === pos2;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var repositionHandler = function (show) {
- return function () {
- var execute = function () {
- if (editor.selection) {
- reposition(findFrontMostMatch(editor.selection.getNode()), show);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ //drawRect(contentAreaRect, 'blue');
+ //drawRect(elementRect, 'red');
+ //drawRect(panelRect, 'green');
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Delay.requestAnimationFrame(execute);
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var repositionHandler = function (show) {
+ return function () {
+ var execute = function () {
+ if (editor.selection) {
+ reposition(findFrontMostMatch(editor.selection.getNode()), show);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var bindScrollEvent = function () {
- if (!scrollContainer) {
- scrollContainer = editor.selection.getScrollContainer() || editor.getWin();
- DOM.bind(scrollContainer, 'scroll', repositionHandler(true));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Delay.requestAnimationFrame(execute);
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('remove', function() {
- DOM.unbind(scrollContainer, 'scroll');
- });
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var bindScrollEvent = function () {
+ if (!scrollContainer) {
+ scrollContainer = editor.selection.getScrollContainer() || editor.getWin();
+ DOM.bind(scrollContainer, 'scroll', repositionHandler(true));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var showContextToolbar = function (match) {
- var panel;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('remove', function () {
+ DOM.unbind(scrollContainer, 'scroll');
+ });
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (match.toolbar.panel) {
- match.toolbar.panel.show();
- reposition(match);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var showContextToolbar = function (match) {
+ var panel;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bindScrollEvent();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (match.toolbar.panel) {
+ match.toolbar.panel.show();
+ reposition(match);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- panel = Factory.create({
- type: 'floatpanel',
- role: 'dialog',
- classes: 'tinymce tinymce-inline arrow',
- ariaLabel: 'Inline toolbar',
- layout: 'flex',
- direction: 'column',
- align: 'stretch',
- autohide: false,
- autofix: true,
- fixed: true,
- border: 1,
- items: Toolbar.createToolbar(editor, match.toolbar.items),
- oncancel: function() {
- editor.focus();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bindScrollEvent();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- match.toolbar.panel = panel;
- panel.renderTo(document.body).reflow();
- reposition(match);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ panel = Factory.create({
+ type: 'floatpanel',
+ role: 'dialog',
+ classes: 'tinymce tinymce-inline arrow',
+ ariaLabel: 'Inline toolbar',
+ layout: 'flex',
+ direction: 'column',
+ align: 'stretch',
+ autohide: false,
+ autofix: true,
+ fixed: true,
+ border: 1,
+ items: Toolbar.createToolbar(editor, match.toolbar.items),
+ oncancel: function () {
+ editor.focus();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var hideAllContextToolbars = function () {
- Tools.each(getContextToolbars(), function(toolbar) {
- if (toolbar.panel) {
- toolbar.panel.hide();
- }
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ match.toolbar.panel = panel;
+ panel.renderTo(document.body).reflow();
+ reposition(match);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var findFrontMostMatch = function (targetElm) {
- var i, y, parentsAndSelf, toolbars = getContextToolbars();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var hideAllContextToolbars = function () {
+ Tools.each(getContextToolbars(), function (toolbar) {
+ if (toolbar.panel) {
+ toolbar.panel.hide();
+ }
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parentsAndSelf = editor.$(targetElm).parents().add(targetElm);
- for (i = parentsAndSelf.length - 1; i >= 0; i--) {
- for (y = toolbars.length - 1; y >= 0; y--) {
- if (toolbars[y].predicate(parentsAndSelf[i])) {
- return {
- toolbar: toolbars[y],
- element: parentsAndSelf[i]
- };
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var findFrontMostMatch = function (targetElm) {
+ var i, y, parentsAndSelf, toolbars = getContextToolbars();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parentsAndSelf = editor.$(targetElm).parents().add(targetElm);
+ for (i = parentsAndSelf.length - 1; i >= 0; i--) {
+ for (y = toolbars.length - 1; y >= 0; y--) {
+ if (toolbars[y].predicate(parentsAndSelf[i])) {
+ return {
+ toolbar: toolbars[y],
+ element: parentsAndSelf[i]
+ };
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('click keyup setContent ObjectResized', function(e) {
- // Only act on partial inserts
- if (e.type === 'setcontent' && !e.selection) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Needs to be delayed to avoid Chrome img focus out bug
- Delay.setEditorTimeout(editor, function() {
- var match;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('click keyup setContent ObjectResized', function (e) {
+ // Only act on partial inserts
+ if (e.type === 'setcontent' && !e.selection) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- match = findFrontMostMatch(editor.selection.getNode());
- if (match) {
- hideAllContextToolbars();
- showContextToolbar(match);
- } else {
- hideAllContextToolbars();
- }
- });
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Needs to be delayed to avoid Chrome img focus out bug
+ Delay.setEditorTimeout(editor, function () {
+ var match;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('blur hide contextmenu', hideAllContextToolbars);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ match = findFrontMostMatch(editor.selection.getNode());
+ if (match) {
+ hideAllContextToolbars();
+ showContextToolbar(match);
+ } else {
+ hideAllContextToolbars();
+ }
+ });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('ObjectResizeStart', function() {
- var match = findFrontMostMatch(editor.selection.getNode());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('blur hide contextmenu', hideAllContextToolbars);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (match && match.toolbar.panel) {
- match.toolbar.panel.hide();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('ObjectResizeStart', function () {
+ var match = findFrontMostMatch(editor.selection.getNode());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('ResizeEditor ResizeWindow', repositionHandler(true));
- editor.on('nodeChange', repositionHandler(false));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (match && match.toolbar.panel) {
+ match.toolbar.panel.hide();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('remove', function() {
- Tools.each(getContextToolbars(), function(toolbar) {
- if (toolbar.panel) {
- toolbar.panel.remove();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('ResizeEditor ResizeWindow', repositionHandler(true));
+ editor.on('nodeChange', repositionHandler(false));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.contextToolbars = {};
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('remove', function () {
+ Tools.each(getContextToolbars(), function (toolbar) {
+ if (toolbar.panel) {
+ toolbar.panel.remove();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.shortcuts.add('ctrl+shift+e > ctrl+shift+p', '', function() {
- var match = findFrontMostMatch(editor.selection.getNode());
- if (match && match.toolbar.panel) {
- match.toolbar.panel.items()[0].focus();
- }
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.contextToolbars = {};
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- addContextualToolbars: addContextualToolbars
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.shortcuts.add('ctrl+shift+e > ctrl+shift+p', '', function () {
+ var match = findFrontMostMatch(editor.selection.getNode());
+ if (match && match.toolbar.panel) {
+ match.toolbar.panel.items()[0].focus();
+ }
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ addContextualToolbars: addContextualToolbars
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * A11y.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Menubar.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="cx" style="display: block; padding: 0 10px"> * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -702,168 +847,134 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce.modern.ui.A11y', [
-], function () {
- var focus = function (panel, type) {
- return function () {
- var item = panel.find(type)[0];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.modern.ui.Menubar',
+ [
+ 'tinymce.core.util.Tools'
+ ],
+ function (Tools) {
+ var defaultMenus = {
+ file: { title: 'File', items: 'newdocument' },
+ edit: { title: 'Edit', items: 'undo redo | cut copy paste pastetext | selectall' },
+ insert: { title: 'Insert', items: '|' },
+ view: { title: 'View', items: 'visualaid |' },
+ format: { title: 'Format', items: 'bold italic underline strikethrough superscript subscript | formats | removeformat' },
+ table: { title: 'Table' },
+ tools: { title: 'Tools' }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (item) {
- item.focus(true);
- }
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createMenuItem = function (menuItems, name) {
+ var menuItem;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var addKeys = function (editor, panel) {
- editor.shortcuts.add('Alt+F9', '', focus(panel, 'menubar'));
- editor.shortcuts.add('Alt+F10,F10', '', focus(panel, 'toolbar'));
- editor.shortcuts.add('Alt+F11', '', focus(panel, 'elementpath'));
- panel.on('cancel', function() {
- editor.focus();
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name == '|') {
+ return { text: '|' };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- addKeys: addKeys
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ menuItem = menuItems[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Sidebar.js
- *
- * Released under LGPL License.
- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return menuItem;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce.modern.ui.Sidebar', [
- 'global!tinymce.util.Tools',
- 'global!tinymce.ui.Factory',
- 'global!tinymce.Env'
-], function (Tools, Factory, Env) {
- var api = function (elm) {
- return {
- element: function () {
- return elm;
- }
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createMenu = function (editorMenuItems, settings, context) {
+ var menuButton, menu, menuItems, isUserDefined, removedMenuItems;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var trigger = function (sidebar, panel, callbackName) {
- var callback = sidebar.settings[callbackName];
- if (callback) {
- callback(api(panel.getEl('body')));
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ removedMenuItems = Tools.makeMap((settings.removed_menuitems || '').split(/[ ,]/));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var hidePanels = function (name, container, sidebars) {
- Tools.each(sidebars, function (sidebar) {
- var panel = container.items().filter('#' + sidebar.name)[0];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // User defined menu
+ if (settings.menu) {
+ menu = settings.menu[context];
+ isUserDefined = true;
+ } else {
+ menu = defaultMenus[context];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (panel && panel.visible() && sidebar.name !== name) {
- trigger(sidebar, panel, 'onhide');
- panel.visible(false);
- }
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (menu) {
+ menuButton = { text: menu.title };
+ menuItems = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var deactivateButtons = function (toolbar) {
- toolbar.items().each(function (ctrl) {
- ctrl.active(false);
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Default/user defined items
+ Tools.each((menu.items || '').split(/[ ,]/), function (item) {
+ var menuItem = createMenuItem(editorMenuItems, item);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var findSidebar = function (sidebars, name) {
- return Tools.grep(sidebars, function (sidebar) {
- return sidebar.name === name;
- })[0];
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (menuItem && !removedMenuItems[item]) {
+ menuItems.push(createMenuItem(editorMenuItems, item));
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var showPanel = function (editor, name, sidebars) {
- return function (e) {
- var btnCtrl = e.control;
- var container = btnCtrl.parents().filter('panel')[0];
- var panel = container.find('#' + name)[0];
- var sidebar = findSidebar(sidebars, name);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Added though context
+ if (!isUserDefined) {
+ Tools.each(editorMenuItems, function (menuItem) {
+ if (menuItem.context == context) {
+ if (menuItem.separator == 'before') {
+ menuItems.push({ text: '|' });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- hidePanels(name, container, sidebars);
- deactivateButtons(btnCtrl.parent());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (menuItem.prependToContext) {
+ menuItems.unshift(menuItem);
+ } else {
+ menuItems.push(menuItem);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (panel && panel.visible()) {
- trigger(sidebar, panel, 'onhide');
- panel.hide();
- btnCtrl.active(false);
- } else {
- if (panel) {
- panel.show();
- trigger(sidebar, panel, 'onshow');
- } else {
- panel = Factory.create({
- type: 'container',
- name: name,
- layout: 'stack',
- classes: 'sidebar-panel',
- html: ''
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (menuItem.separator == 'after') {
+ menuItems.push({ text: '|' });
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container.prepend(panel);
- trigger(sidebar, panel, 'onrender');
- trigger(sidebar, panel, 'onshow');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (var i = 0; i < menuItems.length; i++) {
+ if (menuItems[i].text == '|') {
+ if (i === 0 || i == menuItems.length - 1) {
+ menuItems.splice(i, 1);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- btnCtrl.active(true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ menuButton.menu = menuItems;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.fire('ResizeEditor');
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!menuButton.menu.length) {
+ return null;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isModernBrowser = function () {
- return !Env.ie || Env.ie >= 11;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return menuButton;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var hasSidebar = function (editor) {
- return isModernBrowser() && editor.sidebars ? editor.sidebars.length > 0 : false;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createMenuButtons = function (editor) {
+ var name, menuButtons = [], settings = editor.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var createSidebar = function (editor) {
- var buttons = Tools.map(editor.sidebars, function (sidebar) {
- var settings = sidebar.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var defaultMenuBar = [];
+ if (settings.menu) {
+ for (name in settings.menu) {
+ defaultMenuBar.push(name);
+ }
+ } else {
+ for (name in defaultMenus) {
+ defaultMenuBar.push(name);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- type: 'button',
- icon: settings.icon,
- image: settings.image,
- tooltip: settings.tooltip,
- onclick: showPanel(editor, sidebar.name, editor.sidebars)
- };
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var enabledMenuNames = typeof settings.menubar == "string" ? settings.menubar.split(/[ ,]/) : defaultMenuBar;
+ for (var i = 0; i < enabledMenuNames.length; i++) {
+ var menu = enabledMenuNames[i];
+ menu = createMenu(editor.menuItems, editor.settings, menu);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- type: 'panel',
- name: 'sidebar',
- layout: 'stack',
- classes: 'sidebar',
- items: [
- {
- type: 'toolbar',
- layout: 'stack',
- classes: 'sidebar-toolbar',
- items: buttons
- }
- ]
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (menu) {
+ menuButtons.push(menu);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- hasSidebar: hasSidebar,
- createSidebar: createSidebar
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return menuButtons;
+ };
+
+ return {
+ createMenuButtons: createMenuButtons
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * SkinLoaded.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Resize.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="cx" style="display: block; padding: 0 10px"> * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -872,30 +983,57 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce.modern.ui.SkinLoaded', [
-], function () {
- var fireSkinLoaded = function (editor) {
- var done = function () {
- editor._skinLoaded = true;
- editor.fire('SkinLoaded');
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.modern.ui.Resize',
+ [
+ 'tinymce.core.dom.DOMUtils'
+ ],
+ function (DOMUtils) {
+ var DOM = DOMUtils.DOM;
+ var getSize = function (elm) {
+ return {
+ width: elm.clientWidth,
+ height: elm.clientHeight
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function() {
- if (editor.initialized) {
- done();
- } else {
- editor.on('init', done);
- }
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var resizeTo = function (editor, width, height) {
+ var containerElm, iframeElm, containerSize, iframeSize, settings = editor.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- fireSkinLoaded: fireSkinLoaded
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ containerElm = editor.getContainer();
+ iframeElm = editor.getContentAreaContainer().firstChild;
+ containerSize = getSize(containerElm);
+ iframeSize = getSize(iframeElm);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (width !== null) {
+ width = Math.max(settings.min_width || 100, width);
+ width = Math.min(settings.max_width || 0xFFFF, width);
+
+ DOM.setStyle(containerElm, 'width', width + (containerSize.width - iframeSize.width));
+ DOM.setStyle(iframeElm, 'width', width);
+ }
+
+ height = Math.max(settings.min_height || 100, height);
+ height = Math.min(settings.max_height || 0xFFFF, height);
+ DOM.setStyle(iframeElm, 'height', height);
+
+ editor.fire('ResizeEditor');
+ };
+
+ var resizeBy = function (editor, dw, dh) {
+ var elm = editor.getContentAreaContainer();
+ resizeTo(editor, elm.clientWidth + dw, elm.clientHeight + dh);
+ };
+
+ return {
+ resizeTo: resizeTo,
+ resizeBy: resizeBy
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Resize.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Sidebar.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="cx" style="display: block; padding: 0 10px"> * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -904,51 +1042,170 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce.modern.ui.Resize', [
- 'global!tinymce.DOM'
-], function (DOM) {
- var getSize = function (elm) {
- return {
- width: elm.clientWidth,
- height: elm.clientHeight
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.modern.ui.Sidebar',
+ [
+ 'tinymce.core.util.Tools',
+ 'tinymce.core.ui.Factory',
+ 'tinymce.core.Env'
+ ],
+ function (Tools, Factory, Env) {
+ var api = function (elm) {
+ return {
+ element: function () {
+ return elm;
+ }
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var resizeTo = function (editor, width, height) {
- var containerElm, iframeElm, containerSize, iframeSize, settings = editor.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var trigger = function (sidebar, panel, callbackName) {
+ var callback = sidebar.settings[callbackName];
+ if (callback) {
+ callback(api(panel.getEl('body')));
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- containerElm = editor.getContainer();
- iframeElm = editor.getContentAreaContainer().firstChild;
- containerSize = getSize(containerElm);
- iframeSize = getSize(iframeElm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var hidePanels = function (name, container, sidebars) {
+ Tools.each(sidebars, function (sidebar) {
+ var panel = container.items().filter('#' + sidebar.name)[0];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (width !== null) {
- width = Math.max(settings.min_width || 100, width);
- width = Math.min(settings.max_width || 0xFFFF, width);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (panel && panel.visible() && sidebar.name !== name) {
+ trigger(sidebar, panel, 'onhide');
+ panel.visible(false);
+ }
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DOM.setStyle(containerElm, 'width', width + (containerSize.width - iframeSize.width));
- DOM.setStyle(iframeElm, 'width', width);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var deactivateButtons = function (toolbar) {
+ toolbar.items().each(function (ctrl) {
+ ctrl.active(false);
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- height = Math.max(settings.min_height || 100, height);
- height = Math.min(settings.max_height || 0xFFFF, height);
- DOM.setStyle(iframeElm, 'height', height);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var findSidebar = function (sidebars, name) {
+ return Tools.grep(sidebars, function (sidebar) {
+ return sidebar.name === name;
+ })[0];
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.fire('ResizeEditor');
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var showPanel = function (editor, name, sidebars) {
+ return function (e) {
+ var btnCtrl = e.control;
+ var container = btnCtrl.parents().filter('panel')[0];
+ var panel = container.find('#' + name)[0];
+ var sidebar = findSidebar(sidebars, name);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var resizeBy = function (editor, dw, dh) {
- var elm = editor.getContentAreaContainer();
- resizeTo(editor, elm.clientWidth + dw, elm.clientHeight + dh);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ hidePanels(name, container, sidebars);
+ deactivateButtons(btnCtrl.parent());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- resizeTo: resizeTo,
- resizeBy: resizeBy
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (panel && panel.visible()) {
+ trigger(sidebar, panel, 'onhide');
+ panel.hide();
+ btnCtrl.active(false);
+ } else {
+ if (panel) {
+ panel.show();
+ trigger(sidebar, panel, 'onshow');
+ } else {
+ panel = Factory.create({
+ type: 'container',
+ name: name,
+ layout: 'stack',
+ classes: 'sidebar-panel',
+ html: ''
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container.prepend(panel);
+ trigger(sidebar, panel, 'onrender');
+ trigger(sidebar, panel, 'onshow');
+ }
+
+ btnCtrl.active(true);
+ }
+
+ editor.fire('ResizeEditor');
+ };
+ };
+
+ var isModernBrowser = function () {
+ return !Env.ie || Env.ie >= 11;
+ };
+
+ var hasSidebar = function (editor) {
+ return isModernBrowser() && editor.sidebars ? editor.sidebars.length > 0 : false;
+ };
+
+ var createSidebar = function (editor) {
+ var buttons = Tools.map(editor.sidebars, function (sidebar) {
+ var settings = sidebar.settings;
+
+ return {
+ type: 'button',
+ icon: settings.icon,
+ image: settings.image,
+ tooltip: settings.tooltip,
+ onclick: showPanel(editor, sidebar.name, editor.sidebars)
+ };
+ });
+
+ return {
+ type: 'panel',
+ name: 'sidebar',
+ layout: 'stack',
+ classes: 'sidebar',
+ items: [
+ {
+ type: 'toolbar',
+ layout: 'stack',
+ classes: 'sidebar-toolbar',
+ items: buttons
+ }
+ ]
+ };
+ };
+
+ return {
+ hasSidebar: hasSidebar,
+ createSidebar: createSidebar
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * SkinLoaded.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.themes.modern.ui.SkinLoaded', [
+ ],
+ function () {
+ var fireSkinLoaded = function (editor) {
+ var done = function () {
+ editor._skinLoaded = true;
+ editor.fire('SkinLoaded');
+ };
+
+ return function () {
+ if (editor.initialized) {
+ done();
+ } else {
+ editor.on('init', done);
+ }
+ };
+ };
+
+ return {
+ fireSkinLoaded: fireSkinLoaded
+ };
+ }
+);
+
+/**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Iframe.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -958,136 +1215,165 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce.modern.modes.Iframe', [
- 'global!tinymce.util.Tools',
- 'global!tinymce.ui.Factory',
- 'global!tinymce.DOM',
- 'tinymce.modern.ui.Toolbar',
- 'tinymce.modern.ui.Menubar',
- 'tinymce.modern.ui.ContextToolbars',
- 'tinymce.modern.ui.A11y',
- 'tinymce.modern.ui.Sidebar',
- 'tinymce.modern.ui.SkinLoaded',
- 'tinymce.modern.ui.Resize'
-], function (Tools, Factory, DOM, Toolbar, Menubar, ContextToolbars, A11y, Sidebar, SkinLoaded, Resize) {
- var switchMode = function (panel) {
- return function(e) {
- panel.find('*').disabled(e.mode === 'readonly');
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.modern.modes.Iframe',
+ [
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.core.ui.Factory',
+ 'tinymce.core.util.Tools',
+ 'tinymce.themes.modern.ui.A11y',
+ 'tinymce.themes.modern.ui.Branding',
+ 'tinymce.themes.modern.ui.ContextToolbars',
+ 'tinymce.themes.modern.ui.Menubar',
+ 'tinymce.themes.modern.ui.Resize',
+ 'tinymce.themes.modern.ui.Sidebar',
+ 'tinymce.themes.modern.ui.SkinLoaded',
+ 'tinymce.themes.modern.ui.Toolbar'
+ ],
+ function (DOMUtils, Factory, Tools, A11y, Branding, ContextToolbars, Menubar, Resize, Sidebar, SkinLoaded, Toolbar) {
+ var DOM = DOMUtils.DOM;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var editArea = function (border) {
- return {
- type: 'panel',
- name: 'iframe',
- layout: 'stack',
- classes: 'edit-area',
- border: border,
- html: ''
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var switchMode = function (panel) {
+ return function (e) {
+ panel.find('*').disabled(e.mode === 'readonly');
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var editAreaContainer = function (editor) {
- return {
- type: 'panel',
- layout: 'stack',
- classes: 'edit-aria-container',
- border: '1 0 0 0',
- items: [
- editArea('0'),
- Sidebar.createSidebar(editor)
- ]
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var editArea = function (border) {
+ return {
+ type: 'panel',
+ name: 'iframe',
+ layout: 'stack',
+ classes: 'edit-area',
+ border: border,
+ html: ''
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var render = function (editor, theme, args) {
- var panel, resizeHandleCtrl, startSize, settings = editor.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var editAreaContainer = function (editor) {
+ return {
+ type: 'panel',
+ layout: 'stack',
+ classes: 'edit-aria-container',
+ border: '1 0 0 0',
+ items: [
+ editArea('0'),
+ Sidebar.createSidebar(editor)
+ ]
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (args.skinUiCss) {
- DOM.styleSheetLoader.load(args.skinUiCss, SkinLoaded.fireSkinLoaded(editor));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var render = function (editor, theme, args) {
+ var panel, resizeHandleCtrl, startSize, settings = editor.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- panel = theme.panel = Factory.create({
- type: 'panel',
- role: 'application',
- classes: 'tinymce',
- style: 'visibility: hidden',
- layout: 'stack',
- border: 1,
- items: [
- settings.menubar === false ? null : {type: 'menubar', border: '0 0 1 0', items: Menubar.createMenuButtons(editor)},
- Toolbar.createToolbars(editor, settings.toolbar_items_size),
- Sidebar.hasSidebar(editor) ? editAreaContainer(editor) : editArea('1 0 0 0')
- ]
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (args.skinUiCss) {
+ DOM.styleSheetLoader.load(args.skinUiCss, SkinLoaded.fireSkinLoaded(editor));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.resize !== false) {
- resizeHandleCtrl = {
- type: 'resizehandle',
- direction: settings.resize,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ panel = theme.panel = Factory.create({
+ type: 'panel',
+ role: 'application',
+ classes: 'tinymce',
+ style: 'visibility: hidden',
+ layout: 'stack',
+ border: 1,
+ items: [
+ settings.menubar === false ? null : { type: 'menubar', border: '0 0 1 0', items: Menubar.createMenuButtons(editor) },
+ Toolbar.createToolbars(editor, settings.toolbar_items_size),
+ Sidebar.hasSidebar(editor) ? editAreaContainer(editor) : editArea('1 0 0 0')
+ ]
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- onResizeStart: function() {
- var elm = editor.getContentAreaContainer().firstChild;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.resize !== false) {
+ resizeHandleCtrl = {
+ type: 'resizehandle',
+ direction: settings.resize,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- startSize = {
- width: elm.clientWidth,
- height: elm.clientHeight
- };
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ onResizeStart: function () {
+ var elm = editor.getContentAreaContainer().firstChild;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- onResize: function(e) {
- if (settings.resize === 'both') {
- Resize.resizeTo(editor, startSize.width + e.deltaX, startSize.height + e.deltaY);
- } else {
- Resize.resizeTo(editor, null, startSize.height + e.deltaY);
- }
- }
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ startSize = {
+ width: elm.clientWidth,
+ height: elm.clientHeight
+ };
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add statusbar if needed
- if (settings.statusbar !== false) {
- panel.add({type: 'panel', name: 'statusbar', classes: 'statusbar', layout: 'flow', border: '1 0 0 0', ariaRoot: true, items: [
- {type: 'elementpath', editor: editor},
- resizeHandleCtrl
- ]});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ onResize: function (e) {
+ if (settings.resize === 'both') {
+ Resize.resizeTo(editor, startSize.width + e.deltaX, startSize.height + e.deltaY);
+ } else {
+ Resize.resizeTo(editor, null, startSize.height + e.deltaY);
+ }
+ }
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.fire('BeforeRenderUI');
- editor.on('SwitchMode', switchMode(panel));
- panel.renderBefore(args.targetNode).reflow();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add statusbar if needed
+ if (settings.statusbar !== false) {
+ panel.add({
+ type: 'panel', name: 'statusbar', classes: 'statusbar', layout: 'flow', border: '1 0 0 0', ariaRoot: true, items: [
+ { type: 'elementpath', editor: editor },
+ resizeHandleCtrl
+ ]
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.readonly) {
- editor.setMode('readonly');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.fire('BeforeRenderUI');
+ editor.on('SwitchMode', switchMode(panel));
+ panel.renderBefore(args.targetNode).reflow();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.width) {
- DOM.setStyle(panel.getEl(), 'width', settings.width);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.readonly) {
+ editor.setMode('readonly');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove the panel when the editor is removed
- editor.on('remove', function() {
- panel.remove();
- panel = null;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (args.width) {
+ DOM.setStyle(panel.getEl(), 'width', args.width);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add accesibility shortcuts
- A11y.addKeys(editor, panel);
- ContextToolbars.addContextualToolbars(editor);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove the panel when the editor is removed
+ editor.on('remove', function () {
+ panel.remove();
+ panel = null;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- iframeContainer: panel.find('#iframe')[0].getEl(),
- editorContainer: panel.getEl()
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add accesibility shortcuts
+ A11y.addKeys(editor, panel);
+ ContextToolbars.addContextualToolbars(editor);
+ Branding.setup(editor);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- render: render
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ iframeContainer: panel.find('#iframe')[0].getEl(),
+ editorContainer: panel.getEl()
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-defineGlobal("global!tinymce.ui.FloatPanel", tinymce.ui.FloatPanel);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ render: render
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.core.ui.FloatPanel',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.ui.FloatPanel');
+ }
+);
+
+/**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Inline.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1097,145 +1383,169 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce.modern.modes.Inline', [
- 'global!tinymce.util.Tools',
- 'global!tinymce.ui.Factory',
- 'global!tinymce.DOM',
- 'global!tinymce.ui.FloatPanel',
- 'tinymce.modern.ui.Toolbar',
- 'tinymce.modern.ui.Menubar',
- 'tinymce.modern.ui.ContextToolbars',
- 'tinymce.modern.ui.A11y',
- 'tinymce.modern.ui.SkinLoaded'
-], function (Tools, Factory, DOM, FloatPanel, Toolbar, Menubar, ContextToolbars, A11y, SkinLoaded) {
- var render = function (editor, theme, args) {
- var panel, inlineToolbarContainer, settings = editor.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.modern.modes.Inline',
+ [
+ 'tinymce.core.util.Tools',
+ 'tinymce.core.ui.Factory',
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.core.ui.FloatPanel',
+ 'tinymce.themes.modern.ui.Toolbar',
+ 'tinymce.themes.modern.ui.Menubar',
+ 'tinymce.themes.modern.ui.ContextToolbars',
+ 'tinymce.themes.modern.ui.A11y',
+ 'tinymce.themes.modern.ui.SkinLoaded'
+ ],
+ function (Tools, Factory, DOMUtils, FloatPanel, Toolbar, Menubar, ContextToolbars, A11y, SkinLoaded) {
+ var render = function (editor, theme, args) {
+ var panel, inlineToolbarContainer, settings = editor.settings;
+ var DOM = DOMUtils.DOM;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.fixed_toolbar_container) {
- inlineToolbarContainer = DOM.select(settings.fixed_toolbar_container)[0];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.fixed_toolbar_container) {
+ inlineToolbarContainer = DOM.select(settings.fixed_toolbar_container)[0];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var reposition = function () {
- if (panel && panel.moveRel && panel.visible() && !panel._fixed) {
- // TODO: This is kind of ugly and doesn't handle multiple scrollable elements
- var scrollContainer = editor.selection.getScrollContainer(), body = editor.getBody();
- var deltaX = 0, deltaY = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var reposition = function () {
+ if (panel && panel.moveRel && panel.visible() && !panel._fixed) {
+ // TODO: This is kind of ugly and doesn't handle multiple scrollable elements
+ var scrollContainer = editor.selection.getScrollContainer(), body = editor.getBody();
+ var deltaX = 0, deltaY = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (scrollContainer) {
- var bodyPos = DOM.getPos(body), scrollContainerPos = DOM.getPos(scrollContainer);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (scrollContainer) {
+ var bodyPos = DOM.getPos(body), scrollContainerPos = DOM.getPos(scrollContainer);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- deltaX = Math.max(0, scrollContainerPos.x - bodyPos.x);
- deltaY = Math.max(0, scrollContainerPos.y - bodyPos.y);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ deltaX = Math.max(0, scrollContainerPos.x - bodyPos.x);
+ deltaY = Math.max(0, scrollContainerPos.y - bodyPos.y);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- panel.fixed(false).moveRel(body, editor.rtl ? ['tr-br', 'br-tr'] : ['tl-bl', 'bl-tl', 'tr-br']).moveBy(deltaX, deltaY);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ panel.fixed(false).moveRel(body, editor.rtl ? ['tr-br', 'br-tr'] : ['tl-bl', 'bl-tl', 'tr-br']).moveBy(deltaX, deltaY);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var show = function () {
- if (panel) {
- panel.show();
- reposition();
- DOM.addClass(editor.getBody(), 'mce-edit-focus');
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var show = function () {
+ if (panel) {
+ panel.show();
+ reposition();
+ DOM.addClass(editor.getBody(), 'mce-edit-focus');
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var hide = function () {
- if (panel) {
- // We require two events as the inline float panel based toolbar does not have autohide=true
- panel.hide();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var hide = function () {
+ if (panel) {
+ // We require two events as the inline float panel based toolbar does not have autohide=true
+ panel.hide();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // All other autohidden float panels will be closed below.
- FloatPanel.hideAll();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // All other autohidden float panels will be closed below.
+ FloatPanel.hideAll();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DOM.removeClass(editor.getBody(), 'mce-edit-focus');
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOM.removeClass(editor.getBody(), 'mce-edit-focus');
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var render = function () {
- if (panel) {
- if (!panel.visible()) {
- show();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var render = function () {
+ if (panel) {
+ if (!panel.visible()) {
+ show();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Render a plain panel inside the inlineToolbarContainer if it's defined
- panel = theme.panel = Factory.create({
- type: inlineToolbarContainer ? 'panel' : 'floatpanel',
- role: 'application',
- classes: 'tinymce tinymce-inline',
- layout: 'flex',
- direction: 'column',
- align: 'stretch',
- autohide: false,
- autofix: true,
- fixed: !!inlineToolbarContainer,
- border: 1,
- items: [
- settings.menubar === false ? null : {type: 'menubar', border: '0 0 1 0', items: Menubar.createMenuButtons(editor)},
- Toolbar.createToolbars(editor, settings.toolbar_items_size)
- ]
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Render a plain panel inside the inlineToolbarContainer if it's defined
+ panel = theme.panel = Factory.create({
+ type: inlineToolbarContainer ? 'panel' : 'floatpanel',
+ role: 'application',
+ classes: 'tinymce tinymce-inline',
+ layout: 'flex',
+ direction: 'column',
+ align: 'stretch',
+ autohide: false,
+ autofix: true,
+ fixed: !!inlineToolbarContainer,
+ border: 1,
+ items: [
+ settings.menubar === false ? null : { type: 'menubar', border: '0 0 1 0', items: Menubar.createMenuButtons(editor) },
+ Toolbar.createToolbars(editor, settings.toolbar_items_size)
+ ]
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add statusbar
- /*if (settings.statusbar !== false) {
- panel.add({type: 'panel', classes: 'statusbar', layout: 'flow', border: '1 0 0 0', items: [
- {type: 'elementpath'}
- ]});
- }*/
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add statusbar
+ /*if (settings.statusbar !== false) {
+ panel.add({type: 'panel', classes: 'statusbar', layout: 'flow', border: '1 0 0 0', items: [
+ {type: 'elementpath'}
+ ]});
+ }*/
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.fire('BeforeRenderUI');
- panel.renderTo(inlineToolbarContainer || document.body).reflow();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.fire('BeforeRenderUI');
+ panel.renderTo(inlineToolbarContainer || document.body).reflow();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- A11y.addKeys(editor, panel);
- show();
- ContextToolbars.addContextualToolbars(editor);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ A11y.addKeys(editor, panel);
+ show();
+ ContextToolbars.addContextualToolbars(editor);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('nodeChange', reposition);
- editor.on('activate', show);
- editor.on('deactivate', hide);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('nodeChange', reposition);
+ editor.on('activate', show);
+ editor.on('deactivate', hide);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.nodeChanged();
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.nodeChanged();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- settings.content_editable = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ settings.content_editable = true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('focus', function() {
- // Render only when the CSS file has been loaded
- if (args.skinUiCss) {
- DOM.styleSheetLoader.load(args.skinUiCss, render, render);
- } else {
- render();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('focus', function () {
+ // Render only when the CSS file has been loaded
+ if (args.skinUiCss) {
+ DOM.styleSheetLoader.load(args.skinUiCss, render, render);
+ } else {
+ render();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('blur hide', hide);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('blur hide', hide);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove the panel when the editor is removed
- editor.on('remove', function() {
- if (panel) {
- panel.remove();
- panel = null;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove the panel when the editor is removed
+ editor.on('remove', function () {
+ if (panel) {
+ panel.remove();
+ panel = null;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Preload skin css
- if (args.skinUiCss) {
- DOM.styleSheetLoader.load(args.skinUiCss, SkinLoaded.fireSkinLoaded(editor));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Preload skin css
+ if (args.skinUiCss) {
+ DOM.styleSheetLoader.load(args.skinUiCss, SkinLoaded.fireSkinLoaded(editor));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {};
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {};
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- render: render
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ render: render
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-defineGlobal("global!tinymce.ui.Throbber", tinymce.ui.Throbber);
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ResolveGlobal.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.core.ui.Throbber',
+ [
+ 'global!tinymce.util.Tools.resolve'
+ ],
+ function (resolve) {
+ return resolve('tinymce.ui.Throbber');
+ }
+);
+
+/**
</ins><span class="cx" style="display: block; padding: 0 10px"> * ProgressState.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1245,27 +1555,31 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce.modern.ui.ProgressState', [
- 'global!tinymce.ui.Throbber'
-], function (Throbber) {
- var setup = function (editor, theme) {
- var throbber;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.modern.ui.ProgressState',
+ [
+ 'tinymce.core.ui.Throbber'
+ ],
+ function (Throbber) {
+ var setup = function (editor, theme) {
+ var throbber;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('ProgressState', function(e) {
- throbber = throbber || new Throbber(theme.panel.getEl('body'));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('ProgressState', function (e) {
+ throbber = throbber || new Throbber(theme.panel.getEl('body'));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.state) {
- throbber.show(e.time);
- } else {
- throbber.hide();
- }
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.state) {
+ throbber.show(e.time);
+ } else {
+ throbber.hide();
+ }
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- setup: setup
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ setup: setup
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Theme.js
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1277,66 +1591,70 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce.modern.Theme', [
- 'global!tinymce.Env',
- 'global!tinymce.EditorManager',
- 'global!tinymce.ThemeManager',
- 'tinymce.modern.modes.Iframe',
- 'tinymce.modern.modes.Inline',
- 'tinymce.modern.ui.Resize',
- 'tinymce.modern.ui.ProgressState'
-], function (Env, EditorManager, ThemeManager, Iframe, Inline, Resize, ProgressState) {
- var renderUI = function(editor, theme, args) {
- var settings = editor.settings;
- var skin = settings.skin !== false ? settings.skin || 'lightgray' : false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.themes.modern.Theme',
+ [
+ 'global!window',
+ 'tinymce.core.AddOnManager',
+ 'tinymce.core.EditorManager',
+ 'tinymce.core.Env',
+ 'tinymce.core.ui.Api',
+ 'tinymce.themes.modern.modes.Iframe',
+ 'tinymce.themes.modern.modes.Inline',
+ 'tinymce.themes.modern.ui.ProgressState',
+ 'tinymce.themes.modern.ui.Resize'
+ ],
+ function (window, AddOnManager, EditorManager, Env, Api, Iframe, Inline, ProgressState, Resize) {
+ var ThemeManager = AddOnManager.ThemeManager;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (skin) {
- var skinUrl = settings.skin_url;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Api.appendTo(window.tinymce ? window.tinymce : {});
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (skinUrl) {
- skinUrl = editor.documentBaseURI.toAbsolute(skinUrl);
- } else {
- skinUrl = EditorManager.baseURL + '/skins/' + skin;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var renderUI = function (editor, theme, args) {
+ var settings = editor.settings;
+ var skin = settings.skin !== false ? settings.skin || 'lightgray' : false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Load special skin for IE7
- // TODO: Remove this when we drop IE7 support
- if (Env.documentMode <= 7) {
- args.skinUiCss = skinUrl + '/skin.ie7.min.css';
- } else {
- args.skinUiCss = skinUrl + '/skin.min.css';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (skin) {
+ var skinUrl = settings.skin_url;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Load content.min.css or content.inline.min.css
- editor.contentCSS.push(skinUrl + '/content' + (editor.inline ? '.inline' : '') + '.min.css');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (skinUrl) {
+ skinUrl = editor.documentBaseURI.toAbsolute(skinUrl);
+ } else {
+ skinUrl = EditorManager.baseURL + '/skins/' + skin;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ProgressState.setup(editor, theme);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args.skinUiCss = skinUrl + '/skin.min.css';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.inline) {
- return Inline.render(editor, theme, args);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Load content.min.css or content.inline.min.css
+ editor.contentCSS.push(skinUrl + '/content' + (editor.inline ? '.inline' : '') + '.min.css');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Iframe.render(editor, theme, args);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ProgressState.setup(editor, theme);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ThemeManager.add('modern', function (editor) {
- return {
- renderUI: function (args) {
- return renderUI(editor, this, args);
- },
- resizeTo: function (w, h) {
- return Resize.resizeTo(editor, w, h);
- },
- resizeBy: function (dw, dh) {
- return Resize.resizeBy(editor, dw, dh);
- }
- };
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.inline) {
+ return Inline.render(editor, theme, args);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function () {
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Iframe.render(editor, theme, args);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-dem('tinymce.modern.Theme')();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ThemeManager.add('modern', function (editor) {
+ return {
+ renderUI: function (args) {
+ return renderUI(editor, this, args);
+ },
+ resizeTo: function (w, h) {
+ return Resize.resizeTo(editor, w, h);
+ },
+ resizeBy: function (dw, dh) {
+ return Resize.resizeBy(editor, dw, dh);
+ }
+ };
+ });
+
+ return function () {
+ };
+ }
+);
+
+dem('tinymce.themes.modern.Theme')();
</ins><span class="cx" style="display: block; padding: 0 10px"> })();
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcethemesmodernthememinjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/themes/modern/theme.min.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/themes/modern/theme.min.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/themes/modern/theme.min.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1 +1 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-!function(){var e={},t=function(t){for(var n=e[t],i=n.deps,o=n.defn,a=i.length,s=new Array(a),l=0;l<a;++l)s[l]=r(i[l]);var u=o.apply(null,s);if(void 0===u)throw"module ["+t+"] returned undefined";n.instance=u},n=function(t,n,r){if("string"!=typeof t)throw"module id must be a string";if(void 0===n)throw"no dependencies for "+t;if(void 0===r)throw"no definition function for "+t;e[t]={deps:n,defn:r,instance:void 0}},r=function(n){var r=e[n];if(void 0===r)throw"module ["+n+"] was undefined";return void 0===r.instance&&t(n),r.instance},i=function(e,t){for(var n=e.length,i=new Array(n),o=0;o<n;++o)i.push(r(e[o]));t.apply(null,t)},o={};o.bolt={module:{api:{define:n,require:i,demand:r}}};var a=n,s=function(e,t){a(e,[],function(){return t})};s("1",tinymce.Env),s("2",tinymce.EditorMana
ger),s("3",tinymce.ThemeManager),s("8",tinymce.util.Tools),s("9",tinymce.ui.Factory),s("a",tinymce.DOM),a("b",["8","9"],function(e,t){var n="undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image",r=function(n,r,i){var o,a=[];if(r)return e.each(r.split(/[ ,]/),function(e){var r,s=function(){var t=n.selection;e.settings.stateSelector&&t.selectorChanged(e.settings.stateSelector,function(t){e.active(t)},!0),e.settings.disabledStateSelector&&t.selectorChanged(e.settings.disabledStateSelector,function(t){e.disabled(t)})};"|"==e?o=null:t.has(e)?(e={type:e,size:i},a.push(e),o=null):(o||(o={type:"buttongroup",items:[]},a.push(o)),n.buttons[e]&&(r=e,e=n.buttons[r],"function"==typeof e&&(e=e()),e.type=e.type||"button",e.size=i,e=t.create(e),o.items.push(e),n.initializ
ed?s():n.on("init",s)))}),{type:"toolbar",layout:"flow",items:a}},i=function(t,i){var o=[],a=t.settings,s=function(e){if(e)return o.push(r(t,e,i)),!0};if(e.isArray(a.toolbar)){if(0===a.toolbar.length)return;e.each(a.toolbar,function(e,t){a["toolbar"+(t+1)]=e}),delete a.toolbar}for(var l=1;l<10&&s(a["toolbar"+l]);l++);if(o.length||a.toolbar===!1||s(a.toolbar||n),o.length)return{type:"panel",layout:"stack",classes:"toolbar-grp",ariaRoot:!0,ariaRemember:!0,items:o}};return{createToolbar:r,createToolbars:i}}),a("c",["8"],function(e){var t={file:{title:"File",items:"newdocument"},edit:{title:"Edit",items:"undo redo | cut copy paste pastetext | selectall"},insert:{title:"Insert",items:"|"},view:{title:"View",items:"visualaid |"},format:{title:"Format",items:"bold italic underline strike
through superscript subscript | formats | removeformat"},table:{title:"Table"},tools:{title:"Tools"}},n=function(e,t){var n;return"|"==t?{text:"|"}:n=e[t]},r=function(r,i,o){var a,s,l,u,c;if(c=e.makeMap((i.removed_menuitems||"").split(/[ ,]/)),i.menu?(s=i.menu[o],u=!0):s=t[o],s){a={text:s.title},l=[],e.each((s.items||"").split(/[ ,]/),function(e){var t=n(r,e);t&&!c[e]&&l.push(n(r,e))}),u||e.each(r,function(e){e.context==o&&("before"==e.separator&&l.push({text:"|"}),e.prependToContext?l.unshift(e):l.push(e),"after"==e.separator&&l.push({text:"|"}))});for(var d=0;d<l.length;d++)"|"==l[d].text&&(0!==d&&d!=l.length-1||l.splice(d,1));if(a.menu=l,!a.menu.length)return null}return a},i=function(e){var n,i=[],o=e.settings,a=[];if(o.menu)for(n in o.menu)a.push(n);else for(n in t)a.push(n);for(var s="string"==ty
peof o.menubar?o.menubar.split(/[ ,]/):a,l=0;l<s.length;l++){var u=s[l];u=r(e.menuItems,e.settings,u),u&&i.push(u)}return i};return{createMenuButtons:i}}),s("j",tinymce.util.Delay),s("k",tinymce.geom.Rect),a("d",["a","8","j","b","9","k"],function(e,t,n,r,i,o){var a=function(e){return{left:e.x,top:e.y,width:e.w,height:e.h,right:e.x+e.w,bottom:e.y+e.h}},s=function(e){t.each(e.contextToolbars,function(e){e.panel&&e.panel.hide()})},l=function(e,t){e.moveTo(t.left,t.top)},u=function(e,n,r){n=n?n.substr(0,2):"",t.each({t:"down",b:"up"},function(t,i){e.classes.toggle("arrow-"+t,r(i,n.substr(0,1)))}),t.each({l:"left",r:"right"},function(t,i){e.classes.toggle("arrow-"+t,r(i,n.substr(1,1)))})},c=function(e,t,n,r,i,o){return o=a({x:t,y:n,w:o.w,h:o.h}),e&&(o=e({elementRect:a(r),contentAreaRect:a(i),panelRect:o}
)),o},d=function(a){var d,f=a.settings,p=function(){return a.contextToolbars||[]},h=function(t){var n,r,i;return n=e.getPos(a.getContentAreaContainer()),r=a.dom.getRect(t),i=a.dom.getRoot(),"BODY"===i.nodeName&&(r.x-=i.ownerDocument.documentElement.scrollLeft||i.scrollLeft,r.y-=i.ownerDocument.documentElement.scrollTop||i.scrollTop),r.x+=n.x,r.y+=n.y,r},m=function(t,n){var r,i,d,p,m,g,v,y,b=f.inline_toolbar_position_handler;if(!a.removed){if(!t||!t.toolbar.panel)return void s(a);v=["bc-tc","tc-bc","tl-bl","bl-tl","tr-br","br-tr"],m=t.toolbar.panel,n&&m.show(),d=h(t.element),i=e.getRect(m.getEl()),p=e.getRect(a.getContentAreaContainer()||a.getBody()),y=25,"inline"!==e.getStyle(t.element,"display",!0)&&(d.w=t.element.clientWidth,d.h=t.element.clientHeight),a.inline||(p.w=a.getDoc().documentElement.offsetWidth),a.selection.controlSelection.isResizable(t.element)&&d.
w<y&&(d=o.inflate(d,0,8)),r=o.findBestRelativePosition(i,d,p,v),d=o.clamp(d,p),r?(g=o.relativePosition(i,d,r),l(m,c(b,g.x,g.y,d,p,i))):(p.h+=i.h,d=o.intersect(p,d),d?(r=o.findBestRelativePosition(i,d,p,["bc-tc","bl-tl","br-tr"]),r?(g=o.relativePosition(i,d,r),l(m,c(b,g.x,g.y,d,p,i))):l(m,c(b,d.x,d.y,d,p,i))):m.hide()),u(m,r,function(e,t){return e===t})}},g=function(e){return function(){var t=function(){a.selection&&m(C(a.selection.getNode()),e)};n.requestAnimationFrame(t)}},v=function(){d||(d=a.selection.getScrollContainer()||a.getWin(),e.bind(d,"scroll",g(!0)),a.on("remove",function(){e.unbind(d,"scroll")}))},y=function(e){var t;return e.toolbar.panel?(e.toolbar.panel.show(),void m(e)):(v(),t=i.create({type:"floatpanel",role:"dialog",classes:"tinymce tinymce-inline arrow",ariaLabel:"Inline toolbar",layout:"flex",direction:"column",align:"st
retch",autohide:!1,autofix:!0,fixed:!0,border:1,items:r.createToolbar(a,e.toolbar.items),oncancel:function(){a.focus()}}),e.toolbar.panel=t,t.renderTo(document.body).reflow(),void m(e))},b=function(){t.each(p(),function(e){e.panel&&e.panel.hide()})},C=function(e){var t,n,r,i=p();for(r=a.$(e).parents().add(e),t=r.length-1;t>=0;t--)for(n=i.length-1;n>=0;n--)if(i[n].predicate(r[t]))return{toolbar:i[n],element:r[t]};return null};a.on("click keyup setContent ObjectResized",function(e){("setcontent"!==e.type||e.selection)&&n.setEditorTimeout(a,function(){var e;e=C(a.selection.getNode()),e?(b(),y(e)):b()})}),a.on("blur hide contextmenu",b),a.on("ObjectResizeStart",function(){var e=C(a.selection.getNode());e&&e.toolbar.panel&&e.toolbar.panel.hide()}),a.on("ResizeEditor ResizeWindow",g(!0)),a.on("nodeChange",g(!1)),a.on("remove",function(){t.each(p(),function(e){e.panel&&e
.panel.remove()}),a.contextToolbars={}}),a.shortcuts.add("ctrl+shift+e > ctrl+shift+p","",function(){var e=C(a.selection.getNode());e&&e.toolbar.panel&&e.toolbar.panel.items()[0].focus()})};return{addContextualToolbars:d}}),a("e",[],function(){var e=function(e,t){return function(){var n=e.find(t)[0];n&&n.focus(!0)}},t=function(t,n){t.shortcuts.add("Alt+F9","",e(n,"menubar")),t.shortcuts.add("Alt+F10,F10","",e(n,"toolbar")),t.shortcuts.add("Alt+F11","",e(n,"elementpath")),n.on("cancel",function(){t.focus()})};return{addKeys:t}}),a("f",["8","9","1"],function(e,t,n){var r=function(e){return{element:function(){return e}}},i=function(e,t,n){var i=e.settings[n];i&&i(r(t.getEl("body")))},o=function(t,n,r){e.each(r,function(e){var r=n.items().filter("#"+e.name)[0];r&
;&r.visible()&&e.name!==t&&(i(e,r,"onhide"),r.visible(!1))})},a=function(e){e.items().each(function(e){e.active(!1)})},s=function(t,n){return e.grep(t,function(e){return e.name===n})[0]},l=function(e,n,r){return function(l){var u=l.control,c=u.parents().filter("panel")[0],d=c.find("#"+n)[0],f=s(r,n);o(n,c,r),a(u.parent()),d&&d.visible()?(i(f,d,"onhide"),d.hide(),u.active(!1)):(d?(d.show(),i(f,d,"onshow")):(d=t.create({type:"container",name:n,layout:"stack",classes:"sidebar-panel",html:""}),c.prepend(d),i(f,d,"onrender"),i(f,d,"onshow")),u.active(!0)),e.fire("ResizeEditor")}},u=function(){return!n.ie||n.ie>=11},c=function(e){return!(!u()||!e.sidebars)&&e.sidebars.length>0},d=function(t){var n=e.map(t.sidebars,function(e){var n=e.settings;return{type:"button",icon:n.icon,image:n.image,tooltip:n.tooltip,onclick:l(t,e
.name,t.sidebars)}});return{type:"panel",name:"sidebar",layout:"stack",classes:"sidebar",items:[{type:"toolbar",layout:"stack",classes:"sidebar-toolbar",items:n}]}};return{hasSidebar:c,createSidebar:d}}),a("g",[],function(){var e=function(e){var t=function(){e._skinLoaded=!0,e.fire("SkinLoaded")};return function(){e.initialized?t():e.on("init",t)}};return{fireSkinLoaded:e}}),a("6",["a"],function(e){var t=function(e){return{width:e.clientWidth,height:e.clientHeight}},n=function(n,r,i){var o,a,s,l,u=n.settings;o=n.getContainer(),a=n.getContentAreaContainer().firstChild,s=t(o),l=t(a),null!==r&&(r=Math.max(u.min_width||100,r),r=Math.min(u.max_width||65535,r),e.setStyle(o,"width",r+(s.width-l.width)),e.setStyle(a,"width",r)),i=Math.max(u.min_height||100,i),i=Math.min(u.max_height||65535,i),e.setStyle(a,"height",i),n.fire("Resiz
eEditor")},r=function(e,t,r){var i=e.getContentAreaContainer();n(e,i.clientWidth+t,i.clientHeight+r)};return{resizeTo:n,resizeBy:r}}),a("4",["8","9","a","b","c","d","e","f","g","6"],function(e,t,n,r,i,o,a,s,l,u){var c=function(e){return function(t){e.find("*").disabled("readonly"===t.mode)}},d=function(e){return{type:"panel",name:"iframe",layout:"stack",classes:"edit-area",border:e,html:""}},f=function(e){return{type:"panel",layout:"stack",classes:"edit-aria-container",border:"1 0 0 0",items:[d("0"),s.createSidebar(e)]}},p=function(e,p,h){var m,g,v,y=e.settings;return h.skinUiCss&&n.styleSheetLoader.load(h.skinUiCss,l.fireSkinLoaded(e)),m=p.panel=t.create({type:"panel",role:"application",classes:"tinymce",style:&qu
ot;visibility: hidden",layout:"stack",border:1,items:[y.menubar===!1?null:{type:"menubar",border:"0 0 1 0",items:i.createMenuButtons(e)},r.createToolbars(e,y.toolbar_items_size),s.hasSidebar(e)?f(e):d("1 0 0 0")]}),y.resize!==!1&&(g={type:"resizehandle",direction:y.resize,onResizeStart:function(){var t=e.getContentAreaContainer().firstChild;v={width:t.clientWidth,height:t.clientHeight}},onResize:function(t){"both"===y.resize?u.resizeTo(e,v.width+t.deltaX,v.height+t.deltaY):u.resizeTo(e,null,v.height+t.deltaY)}}),y.statusbar!==!1&&m.add({type:"panel",name:"statusbar",classes:"statusbar",layout:"flow",border:"1 0 0 0",ariaRoot:!0,items:[{type:"elementpath",editor:e},g]}),e.fire("BeforeRenderUI"),e.on("SwitchMode",c(m)),m.renderBefore(h.targetNode).reflow(),y.readonly&&e.setMode("readonly"),y.width&&n.
setStyle(m.getEl(),"width",y.width),e.on("remove",function(){m.remove(),m=null}),a.addKeys(e,m),o.addContextualToolbars(e),{iframeContainer:m.find("#iframe")[0].getEl(),editorContainer:m.getEl()}};return{render:p}}),s("h",tinymce.ui.FloatPanel),a("5",["8","9","a","h","b","c","d","e","g"],function(e,t,n,r,i,o,a,s,l){var u=function(e,u,c){var d,f,p=e.settings;p.fixed_toolbar_container&&(f=n.select(p.fixed_toolbar_container)[0]);var h=function(){if(d&&d.moveRel&&d.visible()&&!d._fixed){var t=e.selection.getScrollContainer(),r=e.getBody(),i=0,o=0;if(t){var a=n.getPos(r),s=n.getPos(t);i=Math.max(0,s.x-a.x),o=Math.max(0,s.y-a.y)}d.fixed(!1).moveRel(r,e.rtl?["tr-br","br-tr"]:["tl-bl","bl-tl","tr-br"]).moveBy(i,o)}},m=function(){d&&(d.show(),h(),n.addClass(e.getBod
y(),"mce-edit-focus"))},g=function(){d&&(d.hide(),r.hideAll(),n.removeClass(e.getBody(),"mce-edit-focus"))},v=function(){return d?void(d.visible()||m()):(d=u.panel=t.create({type:f?"panel":"floatpanel",role:"application",classes:"tinymce tinymce-inline",layout:"flex",direction:"column",align:"stretch",autohide:!1,autofix:!0,fixed:!!f,border:1,items:[p.menubar===!1?null:{type:"menubar",border:"0 0 1 0",items:o.createMenuButtons(e)},i.createToolbars(e,p.toolbar_items_size)]}),e.fire("BeforeRenderUI"),d.renderTo(f||document.body).reflow(),s.addKeys(e,d),m(),a.addContextualToolbars(e),e.on("nodeChange",h),e.on("activate",m),e.on("deactivate",g),void e.nodeChanged())};return p.content_editable=!0,e.on("focus",function(){c.skinUiCss?n.styleSheetLoader.load(c.skinUiCss,v,v):v()}),e.on("blur hide",g),e.on("remo
ve",function(){d&&(d.remove(),d=null)}),c.skinUiCss&&n.styleSheetLoader.load(c.skinUiCss,l.fireSkinLoaded(e)),{}};return{render:u}}),s("i",tinymce.ui.Throbber),a("7",["i"],function(e){var t=function(t,n){var r;t.on("ProgressState",function(t){r=r||new e(n.panel.getEl("body")),t.state?r.show(t.time):r.hide()})};return{setup:t}}),a("0",["1","2","3","4","5","6","7"],function(e,t,n,r,i,o,a){var s=function(n,o,s){var l=n.settings,u=l.skin!==!1&&(l.skin||"lightgray");if(u){var c=l.skin_url;c=c?n.documentBaseURI.toAbsolute(c):t.baseURL+"/skins/"+u,e.documentMode<=7?s.skinUiCss=c+"/skin.ie7.min.css":s.skinUiCss=c+"/skin.min.css",n.contentCSS.push(c+"/content"+(n.inline?".inline":"")+".min.css")}return a.setup(n,o),l.inline?i.render(n,o,s):r.render(n,o,s
)};return n.add("modern",function(e){return{renderUI:function(t){return s(e,this,t)},resizeTo:function(t,n){return o.resizeTo(e,t,n)},resizeBy:function(t,n){return o.resizeBy(e,t,n)}}}),function(){}}),r("0")()}();
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+!function(){var a={},b=function(b){for(var c=a[b],e=c.deps,f=c.defn,g=e.length,h=new Array(g),i=0;i<g;++i)h[i]=d(e[i]);var j=f.apply(null,h);if(void 0===j)throw"module ["+b+"] returned undefined";c.instance=j},c=function(b,c,d){if("string"!=typeof b)throw"module id must be a string";if(void 0===c)throw"no dependencies for "+b;if(void 0===d)throw"no definition function for "+b;a[b]={deps:c,defn:d,instance:void 0}},d=function(c){var d=a[c];if(void 0===d)throw"module ["+c+"] was undefined";return void 0===d.instance&&b(c),d.instance},e=function(a,b){for(var c=a.length,e=new Array(c),f=0;f<c;++f)e.push(d(a[f]));b.apply(null,b)},f={};f.bolt={module:{api:{define:c,require:e,demand:d}}};var g=c,h=function(a,b){g(a,[],function(){return b})};h("1",window),h("a",tinymce.util.Tools.reso
lve),g("2",["a"],function(a){return a("tinymce.AddOnManager")}),g("3",["a"],function(a){return a("tinymce.EditorManager")}),g("4",["a"],function(a){return a("tinymce.Env")}),g("5",["a"],function(a){return a("tinymce.ui.Api")}),g("b",["a"],function(a){return a("tinymce.dom.DOMUtils")}),g("c",["a"],function(a){return a("tinymce.ui.Factory")}),g("d",["a"],function(a){return a("tinymce.util.Tools")}),g("e",[],function(){var a=function(a,b){return function(){var c=a.find(b)[0];c&&c.focus(!0)}},b=function(b,c){b.shortcuts.add("Alt+F9","",a(c,"menubar")),b.shortcuts.add("Alt+F10,F10","",a(c,"toolbar")),b.shortcuts.add("Alt+F11","",a(c,"elementpath")),c.on("cancel",fun
ction(){b.focus()})};return{addKeys:b}}),g("f",["b"],function(a){var b=a.DOM,c=function(a,c){return function(){var d=a.getContentAreaContainer().querySelector("iframe").offsetWidth,e=Math.max(d-a.getDoc().documentElement.offsetWidth,0),f=a.getContainer().querySelector(".mce-statusbar"),g=f?f.offsetHeight:1;b.setStyles(c,{right:e+"px",bottom:g+"px"})}},d=function(a){return function(){b.hide(a)}},e=function(a){a.on("SkinLoaded",function(){var e=b.create("div",{"class":"mce-branding-powered-by"});a.getContainer().appendChild(e),b.bind(e,"click",d(e)),a.on("NodeChange ResizeEditor",c(a,e))})},f=function(a){a.settings.branding!==!1&&e(a)};return{setup:f}}),g("n",["a"],function(a){return a("tinymce.util.Delay")}),g("o",["a"],function(a){return a("tinymce.geom.Rect")}),g("k",["d","
;c"],function(a,b){var c="undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image",d=function(c,d,e){var f,g=[];if(d)return a.each(d.split(/[ ,]/),function(a){var d,h=function(){var b=c.selection;a.settings.stateSelector&&b.selectorChanged(a.settings.stateSelector,function(b){a.active(b)},!0),a.settings.disabledStateSelector&&b.selectorChanged(a.settings.disabledStateSelector,function(b){a.disabled(b)})};"|"==a?f=null:(f||(f={type:"buttongroup",items:[]},g.push(f)),c.buttons[a]&&(d=a,a=c.buttons[d],"function"==typeof a&&(a=a()),a.type=a.type||"button",a.size=e,a=b.create(a),f.items.push(a),c.initialized?h():c.on("init",h)))}),{type:"toolbar",layout:"flow",items:g}},e=function(b,e){var f=[],g=b.settings,h=function(a){if(a)return f.push(d(b,a,e)),!0};if(a.isArray(g.toolbar)){if(0===g.toolbar.len
gth)return;a.each(g.toolbar,function(a,b){g["toolbar"+(b+1)]=a}),delete g.toolbar}for(var i=1;i<10&&h(g["toolbar"+i]);i++);if(f.length||g.toolbar===!1||h(g.toolbar||c),f.length)return{type:"panel",layout:"stack",classes:"toolbar-grp",ariaRoot:!0,ariaRemember:!0,items:f}};return{createToolbar:d,createToolbars:e}}),g("g",["b","d","n","c","o","k"],function(a,b,c,d,e,f){var g=a.DOM,h=function(a){return{left:a.x,top:a.y,width:a.w,height:a.h,right:a.x+a.w,bottom:a.y+a.h}},i=function(a){b.each(a.contextToolbars,function(a){a.panel&&a.panel.hide()})},j=function(a,b){a.moveTo(b.left,b.top)},k=function(a,c,d){c=c?c.substr(0,2):"",b.each({t:"down",b:"up"},function(b,e){a.classes.toggle("arrow-"+b,d(e,c.substr(0,1)))}),b.each({l:"left",r:"right"},function(b,e){a.classes.toggle("arrow-"+b,d
(e,c.substr(1,1)))})},l=function(a,b,c,d,e,f){return f=h({x:b,y:c,w:f.w,h:f.h}),a&&(f=a({elementRect:h(d),contentAreaRect:h(e),panelRect:f})),f},m=function(a){var h,m=a.settings,n=function(){return a.contextToolbars||[]},o=function(b){var c,d,e;return c=g.getPos(a.getContentAreaContainer()),d=a.dom.getRect(b),e=a.dom.getRoot(),"BODY"===e.nodeName&&(d.x-=e.ownerDocument.documentElement.scrollLeft||e.scrollLeft,d.y-=e.ownerDocument.documentElement.scrollTop||e.scrollTop),d.x+=c.x,d.y+=c.y,d},p=function(b,c){var d,f,h,n,p,q,r,s,t=m.inline_toolbar_position_handler;if(!a.removed){if(!b||!b.toolbar.panel)return void i(a);r=["bc-tc","tc-bc","tl-bl","bl-tl","tr-br","br-tr"],p=b.toolbar.panel,c&&p.show(),h=o(b.element),f=g.getRect(p.getEl()),n=g.getRect(a.getContentAreaContainer()||a.getBody()),s=25,"inline"!==g.getStyle(b.element,"display",!0)&&(h.w=b.element.clientWidth
,h.h=b.element.clientHeight),a.inline||(n.w=a.getDoc().documentElement.offsetWidth),a.selection.controlSelection.isResizable(b.element)&&h.w<s&&(h=e.inflate(h,0,8)),d=e.findBestRelativePosition(f,h,n,r),h=e.clamp(h,n),d?(q=e.relativePosition(f,h,d),j(p,l(t,q.x,q.y,h,n,f))):(n.h+=f.h,h=e.intersect(n,h),h?(d=e.findBestRelativePosition(f,h,n,["bc-tc","bl-tl","br-tr"]),d?(q=e.relativePosition(f,h,d),j(p,l(t,q.x,q.y,h,n,f))):j(p,l(t,h.x,h.y,h,n,f))):p.hide()),k(p,d,function(a,b){return a===b})}},q=function(b){return function(){var d=function(){a.selection&&p(u(a.selection.getNode()),b)};c.requestAnimationFrame(d)}},r=function(){h||(h=a.selection.getScrollContainer()||a.getWin(),g.bind(h,"scroll",q(!0)),a.on("remove",function(){g.unbind(h,"scroll")}))},s=function(b){var c;return b.toolbar.panel?(b.toolbar.panel.show(),void p(b)):(r(),c=d.create({type:"floatpanel",role:"dialog",classe
s:"tinymce tinymce-inline arrow",ariaLabel:"Inline toolbar",layout:"flex",direction:"column",align:"stretch",autohide:!1,autofix:!0,fixed:!0,border:1,items:f.createToolbar(a,b.toolbar.items),oncancel:function(){a.focus()}}),b.toolbar.panel=c,c.renderTo(document.body).reflow(),void p(b))},t=function(){b.each(n(),function(a){a.panel&&a.panel.hide()})},u=function(b){var c,d,e,f=n();for(e=a.$(b).parents().add(b),c=e.length-1;c>=0;c--)for(d=f.length-1;d>=0;d--)if(f[d].predicate(e[c]))return{toolbar:f[d],element:e[c]};return null};a.on("click keyup setContent ObjectResized",function(b){("setcontent"!==b.type||b.selection)&&c.setEditorTimeout(a,function(){var b;b=u(a.selection.getNode()),b?(t(),s(b)):t()})}),a.on("blur hide contextmenu",t),a.on("ObjectResizeStart",function(){var b=u(a.selection.getNode());b&&b.toolbar.panel&&b.toolbar.panel.hide()}),a.on("Res
izeEditor ResizeWindow",q(!0)),a.on("nodeChange",q(!1)),a.on("remove",function(){b.each(n(),function(a){a.panel&&a.panel.remove()}),a.contextToolbars={}}),a.shortcuts.add("ctrl+shift+e > ctrl+shift+p","",function(){var b=u(a.selection.getNode());b&&b.toolbar.panel&&b.toolbar.panel.items()[0].focus()})};return{addContextualToolbars:m}}),g("h",["d"],function(a){var b={file:{title:"File",items:"newdocument"},edit:{title:"Edit",items:"undo redo | cut copy paste pastetext | selectall"},insert:{title:"Insert",items:"|"},view:{title:"View",items:"visualaid |"},format:{title:"Format",items:"bold italic underline strikethrough superscript subscript | formats | removeformat"},table:{title:"Table"},tools:{title:"Tools"}},c=function(a,b){var c;return"|"==b?{text:"|"}
:c=a[b]},d=function(d,e,f){var g,h,i,j,k;if(k=a.makeMap((e.removed_menuitems||"").split(/[ ,]/)),e.menu?(h=e.menu[f],j=!0):h=b[f],h){g={text:h.title},i=[],a.each((h.items||"").split(/[ ,]/),function(a){var b=c(d,a);b&&!k[a]&&i.push(c(d,a))}),j||a.each(d,function(a){a.context==f&&("before"==a.separator&&i.push({text:"|"}),a.prependToContext?i.unshift(a):i.push(a),"after"==a.separator&&i.push({text:"|"}))});for(var l=0;l<i.length;l++)"|"==i[l].text&&(0!==l&&l!=i.length-1||i.splice(l,1));if(g.menu=i,!g.menu.length)return null}return g},e=function(a){var c,e=[],f=a.settings,g=[];if(f.menu)for(c in f.menu)g.push(c);else for(c in b)g.push(c);for(var h="string"==typeof f.menubar?f.menubar.split(/[ ,]/):g,i=0;i<h.length;i++){var j=h[i];j=d(a.menuItems,a.settings,j),j&&e.push(j)}return e};return{createMenuButtons:e}}),g("9",["b&q
uot;],function(a){var b=a.DOM,c=function(a){return{width:a.clientWidth,height:a.clientHeight}},d=function(a,d,e){var f,g,h,i,j=a.settings;f=a.getContainer(),g=a.getContentAreaContainer().firstChild,h=c(f),i=c(g),null!==d&&(d=Math.max(j.min_width||100,d),d=Math.min(j.max_width||65535,d),b.setStyle(f,"width",d+(h.width-i.width)),b.setStyle(g,"width",d)),e=Math.max(j.min_height||100,e),e=Math.min(j.max_height||65535,e),b.setStyle(g,"height",e),a.fire("ResizeEditor")},e=function(a,b,c){var e=a.getContentAreaContainer();d(a,e.clientWidth+b,e.clientHeight+c)};return{resizeTo:d,resizeBy:e}}),g("i",["d","c","4"],function(a,b,c){var d=function(a){return{element:function(){return a}}},e=function(a,b,c){var e=a.settings[c];e&&e(d(b.getEl("body")))},f=function(b,c,d){a.each(d,function(a){var d=c.items().filter("#"+a.name)[0];d&&d.visible()&&a.name!==b&&(e(a
,d,"onhide"),d.visible(!1))})},g=function(a){a.items().each(function(a){a.active(!1)})},h=function(b,c){return a.grep(b,function(a){return a.name===c})[0]},i=function(a,c,d){return function(i){var j=i.control,k=j.parents().filter("panel")[0],l=k.find("#"+c)[0],m=h(d,c);f(c,k,d),g(j.parent()),l&&l.visible()?(e(m,l,"onhide"),l.hide(),j.active(!1)):(l?(l.show(),e(m,l,"onshow")):(l=b.create({type:"container",name:c,layout:"stack",classes:"sidebar-panel",html:""}),k.prepend(l),e(m,l,"onrender"),e(m,l,"onshow")),j.active(!0)),a.fire("ResizeEditor")}},j=function(){return!c.ie||c.ie>=11},k=function(a){return!(!j()||!a.sidebars)&&a.sidebars.length>0},l=function(b){var c=a.map(b.sidebars,function(a){var c=a.settings;return{type:"button",icon:c.icon,image:c.image,tooltip:c.tooltip,onclick:i(b,a.name,b.sidebars)}});return{type:"panel",
name:"sidebar",layout:"stack",classes:"sidebar",items:[{type:"toolbar",layout:"stack",classes:"sidebar-toolbar",items:c}]}};return{hasSidebar:k,createSidebar:l}}),g("j",[],function(){var a=function(a){var b=function(){a._skinLoaded=!0,a.fire("SkinLoaded")};return function(){a.initialized?b():a.on("init",b)}};return{fireSkinLoaded:a}}),g("6",["b","c","d","e","f","g","h","9","i","j","k"],function(a,b,c,d,e,f,g,h,i,j,k){var l=a.DOM,m=function(a){return function(b){a.find("*").disabled("readonly"===b.mode)}},n=function(a){return{type:"panel",name:"iframe",layout:"stack",classes:"edit-area",border:a,html:""}},o=function(a){return{type:"panel",layout:"stack",classes:"edit-aria-container&qu
ot;,border:"1 0 0 0",items:[n("0"),i.createSidebar(a)]}},p=function(a,c,p){var q,r,s,t=a.settings;return p.skinUiCss&&l.styleSheetLoader.load(p.skinUiCss,j.fireSkinLoaded(a)),q=c.panel=b.create({type:"panel",role:"application",classes:"tinymce",style:"visibility: hidden",layout:"stack",border:1,items:[t.menubar===!1?null:{type:"menubar",border:"0 0 1 0",items:g.createMenuButtons(a)},k.createToolbars(a,t.toolbar_items_size),i.hasSidebar(a)?o(a):n("1 0 0 0")]}),t.resize!==!1&&(r={type:"resizehandle",direction:t.resize,onResizeStart:function(){var b=a.getContentAreaContainer().firstChild;s={width:b.clientWidth,height:b.clientHeight}},onResize:function(b){"both"===t.resize?h.resizeTo(a,s.width+b.deltaX,s.height+b.deltaY):h.resizeTo(a,null,s.height+b.deltaY)}}),t.statusbar!==!1&&q.add({type:"panel",name:"statusbar",classes:&qu
ot;statusbar",layout:"flow",border:"1 0 0 0",ariaRoot:!0,items:[{type:"elementpath",editor:a},r]}),a.fire("BeforeRenderUI"),a.on("SwitchMode",m(q)),q.renderBefore(p.targetNode).reflow(),t.readonly&&a.setMode("readonly"),p.width&&l.setStyle(q.getEl(),"width",p.width),a.on("remove",function(){q.remove(),q=null}),d.addKeys(a,q),f.addContextualToolbars(a),e.setup(a),{iframeContainer:q.find("#iframe")[0].getEl(),editorContainer:q.getEl()}};return{render:p}}),g("l",["a"],function(a){return a("tinymce.ui.FloatPanel")}),g("7",["d","c","b","l","k","h","g","e","j"],function(a,b,c,d,e,f,g,h,i){var j=function(a,j,k){var l,m,n=a.settings,o=c.DOM;n.fixed_toolbar_container&&(m=o.select(n.fixed_toolbar_container)[0]);var p=function(){if(l&&l.move
Rel&&l.visible()&&!l._fixed){var b=a.selection.getScrollContainer(),c=a.getBody(),d=0,e=0;if(b){var f=o.getPos(c),g=o.getPos(b);d=Math.max(0,g.x-f.x),e=Math.max(0,g.y-f.y)}l.fixed(!1).moveRel(c,a.rtl?["tr-br","br-tr"]:["tl-bl","bl-tl","tr-br"]).moveBy(d,e)}},q=function(){l&&(l.show(),p(),o.addClass(a.getBody(),"mce-edit-focus"))},r=function(){l&&(l.hide(),d.hideAll(),o.removeClass(a.getBody(),"mce-edit-focus"))},s=function(){return l?void(l.visible()||q()):(l=j.panel=b.create({type:m?"panel":"floatpanel",role:"application",classes:"tinymce tinymce-inline",layout:"flex",direction:"column",align:"stretch",autohide:!1,autofix:!0,fixed:!!m,border:1,items:[n.menubar===!1?null:{type:"menubar",border:"0 0 1 0",items:f.createMenuButtons(a)},e.createToolbars(a,n.toolbar_items_size)]}),a.fire("Befor
eRenderUI"),l.renderTo(m||document.body).reflow(),h.addKeys(a,l),q(),g.addContextualToolbars(a),a.on("nodeChange",p),a.on("activate",q),a.on("deactivate",r),void a.nodeChanged())};return n.content_editable=!0,a.on("focus",function(){k.skinUiCss?o.styleSheetLoader.load(k.skinUiCss,s,s):s()}),a.on("blur hide",r),a.on("remove",function(){l&&(l.remove(),l=null)}),k.skinUiCss&&o.styleSheetLoader.load(k.skinUiCss,i.fireSkinLoaded(a)),{}};return{render:j}}),g("m",["a"],function(a){return a("tinymce.ui.Throbber")}),g("8",["m"],function(a){var b=function(b,c){var d;b.on("ProgressState",function(b){d=d||new a(c.panel.getEl("body")),b.state?d.show(b.time):d.hide()})};return{setup:b}}),g("0",["1","2","3","4","5","6","7","8","9"],function(a,b,c,d,e,
f,g,h,i){var j=b.ThemeManager;e.appendTo(a.tinymce?a.tinymce:{});var k=function(a,b,d){var e=a.settings,i=e.skin!==!1&&(e.skin||"lightgray");if(i){var j=e.skin_url;j=j?a.documentBaseURI.toAbsolute(j):c.baseURL+"/skins/"+i,d.skinUiCss=j+"/skin.min.css",a.contentCSS.push(j+"/content"+(a.inline?".inline":"")+".min.css")}return h.setup(a,b),e.inline?g.render(a,b,d):f.render(a,b,d)};return j.add("modern",function(a){return{renderUI:function(b){return k(a,this,b)},resizeTo:function(b,c){return i.resizeTo(a,b,c)},resizeBy:function(b,c){return i.resizeBy(a,b,c)}}}),function(){}}),d("0")()}();
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcetiny_mce_popupjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/tiny_mce_popup.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/tiny_mce_popup.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/tiny_mce_popup.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2,7 +2,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * tinymce_mce_popup.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -19,524 +19,524 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinyMCEPopup
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> var tinyMCEPopup = {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Initializes the popup this will be called automatically.
- *
- * @method init
- */
- init: function() {
- var self = this, parentWin, settings, uiWindow;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Initializes the popup this will be called automatically.
+ *
+ * @method init
+ */
+ init: function () {
+ var self = this, parentWin, settings, uiWindow;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Find window & API
- parentWin = self.getWin();
- tinymce = tinyMCE = parentWin.tinymce;
- self.editor = tinymce.EditorManager.activeEditor;
- self.params = self.editor.windowManager.getParams();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find window & API
+ parentWin = self.getWin();
+ tinymce = tinyMCE = parentWin.tinymce;
+ self.editor = tinymce.EditorManager.activeEditor;
+ self.params = self.editor.windowManager.getParams();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- uiWindow = self.editor.windowManager.windows[self.editor.windowManager.windows.length - 1];
- self.features = uiWindow.features;
- self.uiWindow = uiWindow;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ uiWindow = self.editor.windowManager.windows[self.editor.windowManager.windows.length - 1];
+ self.features = uiWindow.features;
+ self.uiWindow = uiWindow;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- settings = self.editor.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ settings = self.editor.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup popup CSS path(s)
- if (settings.popup_css !== false) {
- if (settings.popup_css) {
- settings.popup_css = self.editor.documentBaseURI.toAbsolute(settings.popup_css);
- } else {
- settings.popup_css = self.editor.baseURI.toAbsolute("plugins/compat3x/css/dialog.css");
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup popup CSS path(s)
+ if (settings.popup_css !== false) {
+ if (settings.popup_css) {
+ settings.popup_css = self.editor.documentBaseURI.toAbsolute(settings.popup_css);
+ } else {
+ settings.popup_css = self.editor.baseURI.toAbsolute("plugins/compat3x/css/dialog.css");
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.popup_css_add) {
- settings.popup_css += ',' + self.editor.documentBaseURI.toAbsolute(settings.popup_css_add);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.popup_css_add) {
+ settings.popup_css += ',' + self.editor.documentBaseURI.toAbsolute(settings.popup_css_add);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup local DOM
- self.dom = self.editor.windowManager.createInstance('tinymce.dom.DOMUtils', document, {
- ownEvents: true,
- proxy: tinyMCEPopup._eventProxy
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup local DOM
+ self.dom = self.editor.windowManager.createInstance('tinymce.plugins.dom.DOMUtils', document, {
+ ownEvents: true,
+ proxy: tinyMCEPopup._eventProxy
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.dom.bind(window, 'ready', self._onDOMLoaded, self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.dom.bind(window, 'ready', self._onDOMLoaded, self);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Enables you to skip loading the default css
- if (self.features.popup_css !== false) {
- self.dom.loadCSS(self.features.popup_css || self.editor.settings.popup_css);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Enables you to skip loading the default css
+ if (self.features.popup_css !== false) {
+ self.dom.loadCSS(self.features.popup_css || self.editor.settings.popup_css);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup on init listeners
- self.listeners = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup on init listeners
+ self.listeners = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Fires when the popup is initialized.
- *
- * @event onInit
- * @param {tinymce.Editor} editor Editor instance.
- * @example
- * // Alerts the selected contents when the dialog is loaded
- * tinyMCEPopup.onInit.add(function(ed) {
- * alert(ed.selection.getContent());
- * });
- *
- * // Executes the init method on page load in some object using the SomeObject scope
- * tinyMCEPopup.onInit.add(SomeObject.init, SomeObject);
- */
- self.onInit = {
- add: function(func, scope) {
- self.listeners.push({func : func, scope : scope});
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Fires when the popup is initialized.
+ *
+ * @event onInit
+ * @param {tinymce.Editor} editor Editor instance.
+ * @example
+ * // Alerts the selected contents when the dialog is loaded
+ * tinyMCEPopup.onInit.add(function(ed) {
+ * alert(ed.selection.getContent());
+ * });
+ *
+ * // Executes the init method on page load in some object using the SomeObject scope
+ * tinyMCEPopup.onInit.add(SomeObject.init, SomeObject);
+ */
+ self.onInit = {
+ add: function (func, scope) {
+ self.listeners.push({ func: func, scope: scope });
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.isWindow = !self.getWindowArg('mce_inline');
- self.id = self.getWindowArg('mce_window_id');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.isWindow = !self.getWindowArg('mce_inline');
+ self.id = self.getWindowArg('mce_window_id');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the reference to the parent window that opened the dialog.
- *
- * @method getWin
- * @return {Window} Reference to the parent window that opened the dialog.
- */
- getWin: function() {
- // Added frameElement check to fix bug: #2817583
- return (!window.frameElement && window.dialogArguments) || opener || parent || top;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the reference to the parent window that opened the dialog.
+ *
+ * @method getWin
+ * @return {Window} Reference to the parent window that opened the dialog.
+ */
+ getWin: function () {
+ // Added frameElement check to fix bug: #2817583
+ return (!window.frameElement && window.dialogArguments) || opener || parent || top;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a window argument/parameter by name.
- *
- * @method getWindowArg
- * @param {String} name Name of the window argument to retrieve.
- * @param {String} defaultValue Optional default value to return.
- * @return {String} Argument value or default value if it wasn't found.
- */
- getWindowArg : function(name, defaultValue) {
- var value = this.params[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a window argument/parameter by name.
+ *
+ * @method getWindowArg
+ * @param {String} name Name of the window argument to retrieve.
+ * @param {String} defaultValue Optional default value to return.
+ * @return {String} Argument value or default value if it wasn't found.
+ */
+ getWindowArg: function (name, defaultValue) {
+ var value = this.params[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return tinymce.is(value) ? value : defaultValue;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return tinymce.is(value) ? value : defaultValue;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a editor parameter/config option value.
- *
- * @method getParam
- * @param {String} name Name of the editor config option to retrieve.
- * @param {String} defaultValue Optional default value to return.
- * @return {String} Parameter value or default value if it wasn't found.
- */
- getParam : function(name, defaultValue) {
- return this.editor.getParam(name, defaultValue);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a editor parameter/config option value.
+ *
+ * @method getParam
+ * @param {String} name Name of the editor config option to retrieve.
+ * @param {String} defaultValue Optional default value to return.
+ * @return {String} Parameter value or default value if it wasn't found.
+ */
+ getParam: function (name, defaultValue) {
+ return this.editor.getParam(name, defaultValue);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a language item by key.
- *
- * @method getLang
- * @param {String} name Language item like mydialog.something.
- * @param {String} defaultValue Optional default value to return.
- * @return {String} Language value for the item like "my string" or the default value if it wasn't found.
- */
- getLang : function(name, defaultValue) {
- return this.editor.getLang(name, defaultValue);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a language item by key.
+ *
+ * @method getLang
+ * @param {String} name Language item like mydialog.something.
+ * @param {String} defaultValue Optional default value to return.
+ * @return {String} Language value for the item like "my string" or the default value if it wasn't found.
+ */
+ getLang: function (name, defaultValue) {
+ return this.editor.getLang(name, defaultValue);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Executed a command on editor that opened the dialog/popup.
- *
- * @method execCommand
- * @param {String} cmd Command to execute.
- * @param {Boolean} ui Optional boolean value if the UI for the command should be presented or not.
- * @param {Object} val Optional value to pass with the comman like an URL.
- * @param {Object} a Optional arguments object.
- */
- execCommand : function(cmd, ui, val, args) {
- args = args || {};
- args.skip_focus = 1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Executed a command on editor that opened the dialog/popup.
+ *
+ * @method execCommand
+ * @param {String} cmd Command to execute.
+ * @param {Boolean} ui Optional boolean value if the UI for the command should be presented or not.
+ * @param {Object} val Optional value to pass with the comman like an URL.
+ * @param {Object} a Optional arguments object.
+ */
+ execCommand: function (cmd, ui, val, args) {
+ args = args || {};
+ args.skip_focus = 1;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.restoreSelection();
- return this.editor.execCommand(cmd, ui, val, args);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.restoreSelection();
+ return this.editor.execCommand(cmd, ui, val, args);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Resizes the dialog to the inner size of the window. This is needed since various browsers
- * have different border sizes on windows.
- *
- * @method resizeToInnerSize
- */
- resizeToInnerSize : function() {
- /*var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Resizes the dialog to the inner size of the window. This is needed since various browsers
+ * have different border sizes on windows.
+ *
+ * @method resizeToInnerSize
+ */
+ resizeToInnerSize: function () {
+ /*var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Detach it to workaround a Chrome specific bug
- // https://sourceforge.net/tracker/?func=detail&atid=635682&aid=2926339&group_id=103281
- setTimeout(function() {
- var vp = self.dom.getViewPort(window);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Detach it to workaround a Chrome specific bug
+ // https://sourceforge.net/tracker/?func=detail&atid=635682&aid=2926339&group_id=103281
+ setTimeout(function() {
+ var vp = self.dom.getViewPort(window);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.editor.windowManager.resizeBy(
- self.getWindowArg('mce_width') - vp.w,
- self.getWindowArg('mce_height') - vp.h,
- self.id || window
- );
- }, 10);*/
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.editor.windowManager.resizeBy(
+ self.getWindowArg('mce_width') - vp.w,
+ self.getWindowArg('mce_height') - vp.h,
+ self.id || window
+ );
+ }, 10);*/
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Will executed the specified string when the page has been loaded. This function
- * was added for compatibility with the 2.x branch.
- *
- * @method executeOnLoad
- * @param {String} evil String to evalutate on init.
- */
- executeOnLoad : function(evil) {
- this.onInit.add(function() {
- eval(evil);
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Will executed the specified string when the page has been loaded. This function
+ * was added for compatibility with the 2.x branch.
+ *
+ * @method executeOnLoad
+ * @param {String} evil String to evalutate on init.
+ */
+ executeOnLoad: function (evil) {
+ this.onInit.add(function () {
+ eval(evil);
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Stores the current editor selection for later restoration. This can be useful since some browsers
- * looses it's selection if a control element is selected/focused inside the dialogs.
- *
- * @method storeSelection
- */
- storeSelection : function() {
- this.editor.windowManager.bookmark = tinyMCEPopup.editor.selection.getBookmark(1);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Stores the current editor selection for later restoration. This can be useful since some browsers
+ * looses it's selection if a control element is selected/focused inside the dialogs.
+ *
+ * @method storeSelection
+ */
+ storeSelection: function () {
+ this.editor.windowManager.bookmark = tinyMCEPopup.editor.selection.getBookmark(1);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Restores any stored selection. This can be useful since some browsers
- * looses it's selection if a control element is selected/focused inside the dialogs.
- *
- * @method restoreSelection
- */
- restoreSelection : function() {
- var self = tinyMCEPopup;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Restores any stored selection. This can be useful since some browsers
+ * looses it's selection if a control element is selected/focused inside the dialogs.
+ *
+ * @method restoreSelection
+ */
+ restoreSelection: function () {
+ var self = tinyMCEPopup;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.isWindow && tinymce.isIE) {
- self.editor.selection.moveToBookmark(self.editor.windowManager.bookmark);
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.isWindow && tinymce.isIE) {
+ self.editor.selection.moveToBookmark(self.editor.windowManager.bookmark);
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Loads a specific dialog language pack. If you pass in plugin_url as a argument
- * when you open the window it will load the <plugin url>/langs/<code>_dlg.js lang pack file.
- *
- * @method requireLangPack
- */
- requireLangPack : function() {
- var self = this, url = self.getWindowArg('plugin_url') || self.getWindowArg('theme_url'), settings = self.editor.settings, lang;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Loads a specific dialog language pack. If you pass in plugin_url as a argument
+ * when you open the window it will load the <plugin url>/langs/<code>_dlg.js lang pack file.
+ *
+ * @method requireLangPack
+ */
+ requireLangPack: function () {
+ var self = this, url = self.getWindowArg('plugin_url') || self.getWindowArg('theme_url'), settings = self.editor.settings, lang;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.language !== false) {
- lang = settings.language || "en";
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.language !== false) {
+ lang = settings.language || "en";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (url && lang && self.features.translate_i18n !== false && settings.language_load !== false) {
- url += '/langs/' + lang + '_dlg.js';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (url && lang && self.features.translate_i18n !== false && settings.language_load !== false) {
+ url += '/langs/' + lang + '_dlg.js';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!tinymce.ScriptLoader.isDone(url)) {
- document.write('<script type="text/javascript" src="' + url + '"></script>');
- tinymce.ScriptLoader.markDone(url);
- }
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!tinymce.ScriptLoader.isDone(url)) {
+ document.write('<script type="text/javascript" src="' + url + '"></script>');
+ tinymce.ScriptLoader.markDone(url);
+ }
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Executes a color picker on the specified element id. When the user
- * then selects a color it will be set as the value of the specified element.
- *
- * @method pickColor
- * @param {DOMEvent} e DOM event object.
- * @param {string} element_id Element id to be filled with the color value from the picker.
- */
- pickColor : function(e, element_id) {
- var el = document.getElementById(element_id), colorPickerCallback = this.editor.settings.color_picker_callback;
- if (colorPickerCallback) {
- colorPickerCallback.call(
- this.editor,
- function (value) {
- el.value = value;
- try {
- el.onchange();
- } catch (ex) {
- // Try fire event, ignore errors
- }
- },
- el.value
- );
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Executes a color picker on the specified element id. When the user
+ * then selects a color it will be set as the value of the specified element.
+ *
+ * @method pickColor
+ * @param {DOMEvent} e DOM event object.
+ * @param {string} element_id Element id to be filled with the color value from the picker.
+ */
+ pickColor: function (e, element_id) {
+ var el = document.getElementById(element_id), colorPickerCallback = this.editor.settings.color_picker_callback;
+ if (colorPickerCallback) {
+ colorPickerCallback.call(
+ this.editor,
+ function (value) {
+ el.value = value;
+ try {
+ el.onchange();
+ } catch (ex) {
+ // Try fire event, ignore errors
+ }
+ },
+ el.value
+ );
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Opens a filebrowser/imagebrowser this will set the output value from
- * the browser as a value on the specified element.
- *
- * @method openBrowser
- * @param {string} element_id Id of the element to set value in.
- * @param {string} type Type of browser to open image/file/flash.
- * @param {string} option Option name to get the file_broswer_callback function name from.
- */
- openBrowser : function(element_id, type) {
- tinyMCEPopup.restoreSelection();
- this.editor.execCallback('file_browser_callback', element_id, document.getElementById(element_id).value, type, window);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Opens a filebrowser/imagebrowser this will set the output value from
+ * the browser as a value on the specified element.
+ *
+ * @method openBrowser
+ * @param {string} element_id Id of the element to set value in.
+ * @param {string} type Type of browser to open image/file/flash.
+ * @param {string} option Option name to get the file_broswer_callback function name from.
+ */
+ openBrowser: function (element_id, type) {
+ tinyMCEPopup.restoreSelection();
+ this.editor.execCallback('file_browser_callback', element_id, document.getElementById(element_id).value, type, window);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates a confirm dialog. Please don't use the blocking behavior of this
- * native version use the callback method instead then it can be extended.
- *
- * @method confirm
- * @param {String} t Title for the new confirm dialog.
- * @param {function} cb Callback function to be executed after the user has selected ok or cancel.
- * @param {Object} s Optional scope to execute the callback in.
- */
- confirm : function(t, cb, s) {
- this.editor.windowManager.confirm(t, cb, s, window);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates a confirm dialog. Please don't use the blocking behavior of this
+ * native version use the callback method instead then it can be extended.
+ *
+ * @method confirm
+ * @param {String} t Title for the new confirm dialog.
+ * @param {function} cb Callback function to be executed after the user has selected ok or cancel.
+ * @param {Object} s Optional scope to execute the callback in.
+ */
+ confirm: function (t, cb, s) {
+ this.editor.windowManager.confirm(t, cb, s, window);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates a alert dialog. Please don't use the blocking behavior of this
- * native version use the callback method instead then it can be extended.
- *
- * @method alert
- * @param {String} tx Title for the new alert dialog.
- * @param {function} cb Callback function to be executed after the user has selected ok.
- * @param {Object} s Optional scope to execute the callback in.
- */
- alert : function(tx, cb, s) {
- this.editor.windowManager.alert(tx, cb, s, window);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates a alert dialog. Please don't use the blocking behavior of this
+ * native version use the callback method instead then it can be extended.
+ *
+ * @method alert
+ * @param {String} tx Title for the new alert dialog.
+ * @param {function} cb Callback function to be executed after the user has selected ok.
+ * @param {Object} s Optional scope to execute the callback in.
+ */
+ alert: function (tx, cb, s) {
+ this.editor.windowManager.alert(tx, cb, s, window);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Closes the current window.
- *
- * @method close
- */
- close : function() {
- var t = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Closes the current window.
+ *
+ * @method close
+ */
+ close: function () {
+ var t = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // To avoid domain relaxing issue in Opera
- function close() {
- t.editor.windowManager.close(window);
- tinymce = tinyMCE = t.editor = t.params = t.dom = t.dom.doc = null; // Cleanup
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // To avoid domain relaxing issue in Opera
+ function close() {
+ t.editor.windowManager.close(window);
+ tinymce = tinyMCE = t.editor = t.params = t.dom = t.dom.doc = null; // Cleanup
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (tinymce.isOpera) {
- t.getWin().setTimeout(close, 0);
- } else {
- close();
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (tinymce.isOpera) {
+ t.getWin().setTimeout(close, 0);
+ } else {
+ close();
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Internal functions
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Internal functions
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- _restoreSelection : function() {
- var e = window.event.srcElement;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ _restoreSelection: function () {
+ var e = window.event.srcElement;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.nodeName == 'INPUT' && (e.type == 'submit' || e.type == 'button')) {
- tinyMCEPopup.restoreSelection();
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.nodeName == 'INPUT' && (e.type == 'submit' || e.type == 'button')) {
+ tinyMCEPopup.restoreSelection();
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/* _restoreSelection : function() {
- var e = window.event.srcElement;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /* _restoreSelection : function() {
+ var e = window.event.srcElement;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If user focus a non text input or textarea
- if ((e.nodeName != 'INPUT' && e.nodeName != 'TEXTAREA') || e.type != 'text')
- tinyMCEPopup.restoreSelection();
- },*/
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If user focus a non text input or textarea
+ if ((e.nodeName != 'INPUT' && e.nodeName != 'TEXTAREA') || e.type != 'text')
+ tinyMCEPopup.restoreSelection();
+ },*/
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- _onDOMLoaded : function() {
- var t = tinyMCEPopup, ti = document.title, h, nv;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ _onDOMLoaded: function () {
+ var t = tinyMCEPopup, ti = document.title, h, nv;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Translate page
- if (t.features.translate_i18n !== false) {
- var map = {
- "update": "Ok",
- "insert": "Ok",
- "cancel": "Cancel",
- "not_set": "--",
- "class_name": "Class name",
- "browse": "Browse"
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Translate page
+ if (t.features.translate_i18n !== false) {
+ var map = {
+ "update": "Ok",
+ "insert": "Ok",
+ "cancel": "Cancel",
+ "not_set": "--",
+ "class_name": "Class name",
+ "browse": "Browse"
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var langCode = (tinymce.settings ? tinymce.settings : t.editor.settings).language || 'en';
- for (var key in map) {
- tinymce.i18n.data[langCode + "." + key] = tinymce.i18n.translate(map[key]);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var langCode = (tinymce.settings ? tinymce.settings : t.editor.settings).language || 'en';
+ for (var key in map) {
+ tinymce.i18n.data[langCode + "." + key] = tinymce.i18n.translate(map[key]);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- h = document.body.innerHTML;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ h = document.body.innerHTML;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Replace a=x with a="x" in IE
- if (tinymce.isIE) {
- h = h.replace(/ (value|title|alt)=([^"][^\s>]+)/gi, ' $1="$2"');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Replace a=x with a="x" in IE
+ if (tinymce.isIE) {
+ h = h.replace(/ (value|title|alt)=([^"][^\s>]+)/gi, ' $1="$2"');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- document.dir = t.editor.getParam('directionality','');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ document.dir = t.editor.getParam('directionality', '');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ((nv = t.editor.translate(h)) && nv != h) {
- document.body.innerHTML = nv;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((nv = t.editor.translate(h)) && nv != h) {
+ document.body.innerHTML = nv;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ((nv = t.editor.translate(ti)) && nv != ti) {
- document.title = ti = nv;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((nv = t.editor.translate(ti)) && nv != ti) {
+ document.title = ti = nv;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!t.editor.getParam('browser_preferred_colors', false) || !t.isWindow) {
- t.dom.addClass(document.body, 'forceColors');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!t.editor.getParam('browser_preferred_colors', false) || !t.isWindow) {
+ t.dom.addClass(document.body, 'forceColors');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- document.body.style.display = '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ document.body.style.display = '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Restore selection in IE when focus is placed on a non textarea or input element of the type text
- if (tinymce.Env.ie) {
- if (tinymce.Env.ie < 11) {
- document.attachEvent('onmouseup', tinyMCEPopup._restoreSelection);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Restore selection in IE when focus is placed on a non textarea or input element of the type text
+ if (tinymce.Env.ie) {
+ if (tinymce.Env.ie < 11) {
+ document.attachEvent('onmouseup', tinyMCEPopup._restoreSelection);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add base target element for it since it would fail with modal dialogs
- t.dom.add(t.dom.select('head')[0], 'base', {target: '_self'});
- } else {
- document.addEventListener('mouseup', tinyMCEPopup._restoreSelection, false);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add base target element for it since it would fail with modal dialogs
+ t.dom.add(t.dom.select('head')[0], 'base', { target: '_self' });
+ } else {
+ document.addEventListener('mouseup', tinyMCEPopup._restoreSelection, false);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- t.restoreSelection();
- t.resizeToInnerSize();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ t.restoreSelection();
+ t.resizeToInnerSize();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set inline title
- if (!t.isWindow) {
- t.editor.windowManager.setTitle(window, ti);
- } else {
- window.focus();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set inline title
+ if (!t.isWindow) {
+ t.editor.windowManager.setTitle(window, ti);
+ } else {
+ window.focus();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!tinymce.isIE && !t.isWindow) {
- t.dom.bind(document, 'focus', function() {
- t.editor.windowManager.focus(t.id);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!tinymce.isIE && !t.isWindow) {
+ t.dom.bind(document, 'focus', function () {
+ t.editor.windowManager.focus(t.id);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Patch for accessibility
- tinymce.each(t.dom.select('select'), function(e) {
- e.onkeydown = tinyMCEPopup._accessHandler;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Patch for accessibility
+ tinymce.each(t.dom.select('select'), function (e) {
+ e.onkeydown = tinyMCEPopup._accessHandler;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Call onInit
- // Init must be called before focus so the selection won't get lost by the focus call
- tinymce.each(t.listeners, function(o) {
- o.func.call(o.scope, t.editor);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Call onInit
+ // Init must be called before focus so the selection won't get lost by the focus call
+ tinymce.each(t.listeners, function (o) {
+ o.func.call(o.scope, t.editor);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move focus to window
- if (t.getWindowArg('mce_auto_focus', true)) {
- window.focus();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move focus to window
+ if (t.getWindowArg('mce_auto_focus', true)) {
+ window.focus();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Focus element with mceFocus class
- tinymce.each(document.forms, function(f) {
- tinymce.each(f.elements, function(e) {
- if (t.dom.hasClass(e, 'mceFocus') && !e.disabled) {
- e.focus();
- return false; // Break loop
- }
- });
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Focus element with mceFocus class
+ tinymce.each(document.forms, function (f) {
+ tinymce.each(f.elements, function (e) {
+ if (t.dom.hasClass(e, 'mceFocus') && !e.disabled) {
+ e.focus();
+ return false; // Break loop
+ }
+ });
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- document.onkeyup = tinyMCEPopup._closeWinKeyHandler;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ document.onkeyup = tinyMCEPopup._closeWinKeyHandler;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ('textContent' in document) {
- t.uiWindow.getEl('head').firstChild.textContent = document.title;
- } else {
- t.uiWindow.getEl('head').firstChild.innerText = document.title;
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ('textContent' in document) {
+ t.uiWindow.getEl('head').firstChild.textContent = document.title;
+ } else {
+ t.uiWindow.getEl('head').firstChild.innerText = document.title;
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- _accessHandler : function(e) {
- e = e || window.event;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ _accessHandler: function (e) {
+ e = e || window.event;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.keyCode == 13 || e.keyCode == 32) {
- var elm = e.target || e.srcElement;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.keyCode == 13 || e.keyCode == 32) {
+ var elm = e.target || e.srcElement;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elm.onchange) {
- elm.onchange();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (elm.onchange) {
+ elm.onchange();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return tinymce.dom.Event.cancel(e);
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return tinymce.dom.Event.cancel(e);
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- _closeWinKeyHandler : function(e) {
- e = e || window.event;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ _closeWinKeyHandler: function (e) {
+ e = e || window.event;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.keyCode == 27) {
- tinyMCEPopup.close();
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.keyCode == 27) {
+ tinyMCEPopup.close();
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- _eventProxy: function(id) {
- return function(evt) {
- tinyMCEPopup.dom.events.callNativeHandler(id, evt);
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ _eventProxy: function (id) {
+ return function (evt) {
+ tinyMCEPopup.dom.events.callNativeHandler(id, evt);
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> };
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> tinyMCEPopup.init();
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-tinymce.util.Dispatcher = function(scope) {
- this.scope = scope || this;
- this.listeners = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+tinymce.util.Dispatcher = function (scope) {
+ this.scope = scope || this;
+ this.listeners = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.add = function(callback, scope) {
- this.listeners.push({cb : callback, scope : scope || this.scope});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.add = function (callback, scope) {
+ this.listeners.push({ cb: callback, scope: scope || this.scope });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return callback;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return callback;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.addToTop = function(callback, scope) {
- var self = this, listener = {cb : callback, scope : scope || self.scope};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.addToTop = function (callback, scope) {
+ var self = this, listener = { cb: callback, scope: scope || self.scope };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Create new listeners if addToTop is executed in a dispatch loop
- if (self.inDispatch) {
- self.listeners = [listener].concat(self.listeners);
- } else {
- self.listeners.unshift(listener);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Create new listeners if addToTop is executed in a dispatch loop
+ if (self.inDispatch) {
+ self.listeners = [listener].concat(self.listeners);
+ } else {
+ self.listeners.unshift(listener);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return callback;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return callback;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.remove = function(callback) {
- var listeners = this.listeners, output = null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.remove = function (callback) {
+ var listeners = this.listeners, output = null;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tinymce.each(listeners, function(listener, i) {
- if (callback == listener.cb) {
- output = listener;
- listeners.splice(i, 1);
- return false;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ tinymce.each(listeners, function (listener, i) {
+ if (callback == listener.cb) {
+ output = listener;
+ listeners.splice(i, 1);
+ return false;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return output;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return output;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.dispatch = function() {
- var self = this, returnValue, args = arguments, i, listeners = self.listeners, listener;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.dispatch = function () {
+ var self = this, returnValue, args = arguments, i, listeners = self.listeners, listener;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.inDispatch = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.inDispatch = true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Needs to be a real loop since the listener count might change while looping
- // And this is also more efficient
- for (i = 0; i < listeners.length; i++) {
- listener = listeners[i];
- returnValue = listener.cb.apply(listener.scope, args.length > 0 ? args : [listener.scope]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Needs to be a real loop since the listener count might change while looping
+ // And this is also more efficient
+ for (i = 0; i < listeners.length; i++) {
+ listener = listeners[i];
+ returnValue = listener.cb.apply(listener.scope, args.length > 0 ? args : [listener.scope]);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (returnValue === false) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (returnValue === false) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.inDispatch = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.inDispatch = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return returnValue;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return returnValue;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px"> };
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymcetinymcejs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/tinymce.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/tinymce.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/tinymce.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,111 +1,93 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// 4.5.6 (2017-03-30)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+(function () {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Compiled inline version. (Library mode)
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+var defs = {}; // id -> {dependencies, definition, instance (possibly undefined)}
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/*jshint smarttabs:true, undef:true, latedef:true, curly:true, bitwise:true, camelcase:true */
-/*globals $code */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+// Used when there is no 'main' module.
+// The name is probably (hopefully) unique so minification removes for releases.
+var register_3795 = function (id) {
+ var module = dem(id);
+ var fragments = id.split('.');
+ var target = Function('return this;')();
+ for (var i = 0; i < fragments.length - 1; ++i) {
+ if (target[fragments[i]] === undefined)
+ target[fragments[i]] = {};
+ target = target[fragments[i]];
+ }
+ target[fragments[fragments.length - 1]] = module;
+};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-(function(exports, undefined) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+var instantiate = function (id) {
+ var actual = defs[id];
+ var dependencies = actual.deps;
+ var definition = actual.defn;
+ var len = dependencies.length;
+ var instances = new Array(len);
+ for (var i = 0; i < len; ++i)
+ instances[i] = dem(dependencies[i]);
+ var defResult = definition.apply(null, instances);
+ if (defResult === undefined)
+ throw 'module [' + id + '] returned undefined';
+ actual.instance = defResult;
+};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var modules = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+var def = function (id, dependencies, definition) {
+ if (typeof id !== 'string')
+ throw 'module id must be a string';
+ else if (dependencies === undefined)
+ throw 'no dependencies for ' + id;
+ else if (definition === undefined)
+ throw 'no definition function for ' + id;
+ defs[id] = {
+ deps: dependencies,
+ defn: definition,
+ instance: undefined
+ };
+};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function require(ids, callback) {
- var module, defs = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+var dem = function (id) {
+ var actual = defs[id];
+ if (actual === undefined)
+ throw 'module [' + id + '] was undefined';
+ else if (actual.instance === undefined)
+ instantiate(id);
+ return actual.instance;
+};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var i = 0; i < ids.length; ++i) {
- module = modules[ids[i]] || resolve(ids[i]);
- if (!module) {
- throw 'module definition dependecy not found: ' + ids[i];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+var req = function (ids, callback) {
+ var len = ids.length;
+ var instances = new Array(len);
+ for (var i = 0; i < len; ++i)
+ instances.push(dem(ids[i]));
+ callback.apply(null, callback);
+};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- defs.push(module);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+var ephox = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- callback.apply(null, defs);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ephox.bolt = {
+ module: {
+ api: {
+ define: def,
+ require: req,
+ demand: dem
+ }
+ }
+};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function define(id, dependencies, definition) {
- if (typeof id !== 'string') {
- throw 'invalid module definition, module id must be defined and be a string';
- }
-
- if (dependencies === undefined) {
- throw 'invalid module definition, dependencies must be specified';
- }
-
- if (definition === undefined) {
- throw 'invalid module definition, definition function must be specified';
- }
-
- require(dependencies, function() {
- modules[id] = definition.apply(null, arguments);
- });
- }
-
- function defined(id) {
- return !!modules[id];
- }
-
- function resolve(id) {
- var target = exports;
- var fragments = id.split(/[.\/]/);
-
- for (var fi = 0; fi < fragments.length; ++fi) {
- if (!target[fragments[fi]]) {
- return;
- }
-
- target = target[fragments[fi]];
- }
-
- return target;
- }
-
- function expose(ids) {
- var i, target, id, fragments, privateModules;
-
- for (i = 0; i < ids.length; i++) {
- target = exports;
- id = ids[i];
- fragments = id.split(/[.\/]/);
-
- for (var fi = 0; fi < fragments.length - 1; ++fi) {
- if (target[fragments[fi]] === undefined) {
- target[fragments[fi]] = {};
- }
-
- target = target[fragments[fi]];
- }
-
- target[fragments[fragments.length - 1]] = modules[id];
- }
-
- // Expose private modules for unit tests
- if (exports.AMDLC_TESTS) {
- privateModules = exports.privateModules || {};
-
- for (id in modules) {
- privateModules[id] = modules[id];
- }
-
- for (i = 0; i < ids.length; i++) {
- delete privateModules[ids[i]];
- }
-
- exports.privateModules = privateModules;
- }
- }
-
-// Included from: js/tinymce/classes/geom/Rect.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+var define = def;
+var require = req;
+var demand = dem;
+// this helps with minificiation when using a lot of global references
+var defineGlobal = function (id, ref) {
+ define(id, [], function () { return ref; });
+};
+/*jsc
+["tinymce.core.api.Main","tinymce.core.api.Tinymce","tinymce.core.Register","tinymce.core.geom.Rect","tinymce.core.util.Promise","tinymce.core.util.Delay","tinymce.core.Env","tinymce.core.dom.EventUtils","tinymce.core.dom.Sizzle","tinymce.core.util.Tools","tinymce.core.dom.DomQuery","tinymce.core.html.Styles","tinymce.core.dom.TreeWalker","tinymce.core.html.Entities","tinymce.core.dom.DOMUtils","tinymce.core.dom.ScriptLoader","tinymce.core.AddOnManager","tinymce.core.dom.RangeUtils","tinymce.core.html.Node","tinymce.core.html.Schema","tinymce.core.html.SaxParser","tinymce.core.html.DomParser","tinymce.core.html.Writer","tinymce.core.html.Serializer","tinymce.core.dom.Serializer","tinymce.core.util.VK","tinymce.core.dom.Con
trolSelection","tinymce.core.dom.BookmarkManager","tinymce.core.dom.Selection","tinymce.core.Formatter","tinymce.core.UndoManager","tinymce.core.EditorCommands","tinymce.core.util.URI","tinymce.core.util.Class","tinymce.core.util.EventDispatcher","tinymce.core.util.Observable","tinymce.core.WindowManager","tinymce.core.NotificationManager","tinymce.core.EditorObservable","tinymce.core.Shortcuts","tinymce.core.Editor","tinymce.core.util.I18n","tinymce.core.FocusManager","tinymce.core.EditorManager","tinymce.core.util.XHR","tinymce.core.util.JSON","tinymce.core.util.JSONRequest","tinymce.core.util.JSONP","tinymce.core.util.LocalStorage","tinymce.core.api.Compat","tinymce.core.util.Color","tinymce.core.ui.Api","tinymce.core.util.A
rr","tinymce.core.dom.Range","tinymce.core.dom.StyleSheetLoader","tinymce.core.dom.NodeType","tinymce.core.caret.CaretContainer","tinymce.core.text.Zwsp","tinymce.core.caret.CaretBookmark","tinymce.core.caret.CaretPosition","tinymce.core.dom.ScrollIntoView","tinymce.core.dom.TridentSelection","tinymce.core.dom.ElementUtils","tinymce.core.util.Fun","tinymce.core.fmt.Preview","tinymce.core.fmt.Hooks","tinymce.core.undo.Levels","tinymce.core.delete.DeleteCommands","tinymce.core.InsertContent","global!document","tinymce.core.ui.Window","tinymce.core.ui.MessageBox","tinymce.core.ui.Notification","tinymce.core.init.Render","tinymce.core.Mode","tinymce.core.ui.Sidebar","tinymce.core.util.Uuid","tinymce.core.ErrorReporter","tinymce.cor
e.LegacyInput","tinymce.core.ui.Selector","tinymce.core.ui.Collection","tinymce.core.ui.ReflowQueue","tinymce.core.ui.Control","tinymce.core.ui.Factory","tinymce.core.ui.KeyboardNavigation","tinymce.core.ui.Container","tinymce.core.ui.DragHelper","tinymce.core.ui.Scrollable","tinymce.core.ui.Panel","tinymce.core.ui.Movable","tinymce.core.ui.Resizable","tinymce.core.ui.FloatPanel","tinymce.core.ui.Tooltip","tinymce.core.ui.Widget","tinymce.core.ui.Progress","tinymce.core.ui.Layout","tinymce.core.ui.AbsoluteLayout","tinymce.core.ui.Button","tinymce.core.ui.ButtonGroup","tinymce.core.ui.Checkbox","tinymce.core.ui.ComboBox","tinymce.core.ui.ColorBox","tinymce.core.ui.PanelButton","tinymce.core.ui.ColorButton","tinymce.core.ui.Color
Picker","tinymce.core.ui.Path","tinymce.core.ui.ElementPath","tinymce.core.ui.FormItem","tinymce.core.ui.Form","tinymce.core.ui.FieldSet","tinymce.core.ui.FilePicker","tinymce.core.ui.FitLayout","tinymce.core.ui.FlexLayout","tinymce.core.ui.FlowLayout","tinymce.core.ui.FormatControls","tinymce.core.ui.GridLayout","tinymce.core.ui.Iframe","tinymce.core.ui.InfoBox","tinymce.core.ui.Label","tinymce.core.ui.Toolbar","tinymce.core.ui.MenuBar","tinymce.core.ui.MenuButton","tinymce.core.ui.MenuItem","tinymce.core.ui.Throbber","tinymce.core.ui.Menu","tinymce.core.ui.ListBox","tinymce.core.ui.Radio","tinymce.core.ui.ResizeHandle","tinymce.core.ui.SelectBox","tinymce.core.ui.Slider","tinymce.core.ui.Spacer","tinymce.core.ui.Spl
itButton","tinymce.core.ui.StackLayout","tinymce.core.ui.TabPanel","tinymce.core.ui.TextBox","ephox.katamari.api.Arr","ephox.katamari.api.Fun","ephox.katamari.api.Future","ephox.katamari.api.Futures","ephox.katamari.api.Result","tinymce.core.caret.CaretCandidate","tinymce.core.geom.ClientRect","tinymce.core.text.ExtendingChar","tinymce.core.undo.Fragments","tinymce.core.delete.BlockBoundaryDelete","tinymce.core.delete.BlockRangeDelete","tinymce.core.delete.CefDelete","tinymce.core.delete.InlineBoundaryDelete","tinymce.core.caret.CaretWalker","tinymce.core.dom.RangeNormalizer","tinymce.core.InsertList","tinymce.core.data.ObservableObject","tinymce.core.ui.DomUtils","tinymce.core.ui.BoxUtils","tinymce.core.ui.ClassList","global!window","ti
nymce.core.init.Init","tinymce.core.PluginManager","tinymce.core.ThemeManager","tinymce.core.content.LinkTargets","tinymce.core.fmt.FontInfo","ephox.katamari.api.Option","global!Array","global!Error","global!String","ephox.katamari.api.LazyValue","ephox.katamari.async.Bounce","ephox.katamari.async.AsyncValues","tinymce.core.undo.Diff","tinymce.core.delete.BlockBoundary","tinymce.core.delete.MergeBlocks","ephox.katamari.api.Options","ephox.sugar.api.dom.Compare","ephox.sugar.api.node.Element","tinymce.core.delete.DeleteUtils","tinymce.core.caret.CaretUtils","tinymce.core.delete.CefDeleteAction","tinymce.core.delete.DeleteElement","tinymce.core.keyboard.BoundaryCaret","tinymce.core.keyboard.BoundaryLocation","tinymce.core.keyboard.BoundarySelection&
quot;,"tinymce.core.keyboard.InlineUtils","tinymce.core.caret.CaretFinder","tinymce.core.data.Binding","tinymce.core.init.InitContentBody","global!Object","global!setTimeout","ephox.katamari.api.Struct","ephox.sand.api.Node","ephox.sand.api.PlatformDetection","ephox.sugar.api.search.Selectors","global!console","ephox.sugar.api.node.Node","ephox.sugar.api.search.PredicateFind","ephox.sugar.api.search.Traverse","tinymce.core.dom.Empty","ephox.sugar.api.dom.Insert","ephox.sugar.api.dom.Remove","ephox.katamari.api.Adt","tinymce.core.text.Bidi","tinymce.core.caret.CaretContainerInline","tinymce.core.caret.CaretContainerRemove","tinymce.core.util.LazyEvaluator","ephox.katamari.api.Cell","tinymce.core.caret.CaretContainerInput","tinymce.core.EditorU
pload","tinymce.core.ForceBlocks","tinymce.core.keyboard.KeyboardOverrides","tinymce.core.NodeChange","tinymce.core.SelectionOverrides","tinymce.core.util.Quirks","ephox.katamari.data.Immutable","ephox.katamari.data.MixedBag","ephox.sand.util.Global","ephox.katamari.api.Thunk","ephox.sand.core.PlatformDetection","global!navigator","ephox.sugar.api.node.NodeTypes","ephox.katamari.api.Type","ephox.sugar.api.node.Body","ephox.sugar.impl.ClosestOrAncestor","ephox.sugar.alien.Recurse","ephox.sugar.api.search.SelectorExists","ephox.sugar.api.dom.InsertAll","ephox.katamari.api.Obj","tinymce.core.file.Uploader","tinymce.core.file.ImageScanner","tinymce.core.file.BlobCache","tinymce.core.file.UploadStatus","tinymce.core.keyboard.ArrowKeys","tinym
ce.core.keyboard.DeleteBackspaceKeys","tinymce.core.keyboard.EnterKey","tinymce.core.keyboard.SpaceKey","tinymce.core.caret.FakeCaret","tinymce.core.caret.LineWalker","tinymce.core.caret.LineUtils","tinymce.core.DragDropOverrides","tinymce.core.dom.NodePath","ephox.katamari.util.BagUtils","ephox.katamari.api.Resolve","ephox.sand.core.Browser","ephox.sand.core.OperatingSystem","ephox.sand.detect.DeviceType","ephox.sand.detect.UaString","ephox.sand.info.PlatformInfo","ephox.sugar.api.search.SelectorFind","tinymce.core.file.Conversions","global!URL","tinymce.core.keyboard.MatchKeys","tinymce.core.keyboard.InsertSpace","tinymce.core.dom.Dimensions","tinymce.core.dom.MousePosition","ephox.katamari.api.Global","ephox.sand.detect.Version","ephox.katamari
.api.Strings","ephox.katamari.api.Merger","global!Number","ephox.katamari.str.StrAppend","ephox.katamari.str.StringParts"]
+jsc*/
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Rect.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -116,213 +98,215 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.geom.Rect
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/geom/Rect", [
-], function() {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.geom.Rect',
+ [
+ ],
+ function () {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var min = Math.min, max = Math.max, round = Math.round;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var min = Math.min, max = Math.max, round = Math.round;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the rect positioned based on the relative position name
- * to the target rect.
- *
- * @method relativePosition
- * @param {Rect} rect Source rect to modify into a new rect.
- * @param {Rect} targetRect Rect to move relative to based on the rel option.
- * @param {String} rel Relative position. For example: tr-bl.
- */
- function relativePosition(rect, targetRect, rel) {
- var x, y, w, h, targetW, targetH;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the rect positioned based on the relative position name
+ * to the target rect.
+ *
+ * @method relativePosition
+ * @param {Rect} rect Source rect to modify into a new rect.
+ * @param {Rect} targetRect Rect to move relative to based on the rel option.
+ * @param {String} rel Relative position. For example: tr-bl.
+ */
+ function relativePosition(rect, targetRect, rel) {
+ var x, y, w, h, targetW, targetH;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- x = targetRect.x;
- y = targetRect.y;
- w = rect.w;
- h = rect.h;
- targetW = targetRect.w;
- targetH = targetRect.h;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ x = targetRect.x;
+ y = targetRect.y;
+ w = rect.w;
+ h = rect.h;
+ targetW = targetRect.w;
+ targetH = targetRect.h;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rel = (rel || '').split('');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rel = (rel || '').split('');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rel[0] === 'b') {
- y += targetH;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rel[0] === 'b') {
+ y += targetH;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rel[1] === 'r') {
- x += targetW;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rel[1] === 'r') {
+ x += targetW;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rel[0] === 'c') {
- y += round(targetH / 2);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rel[0] === 'c') {
+ y += round(targetH / 2);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rel[1] === 'c') {
- x += round(targetW / 2);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rel[1] === 'c') {
+ x += round(targetW / 2);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rel[3] === 'b') {
- y -= h;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rel[3] === 'b') {
+ y -= h;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rel[4] === 'r') {
- x -= w;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rel[4] === 'r') {
+ x -= w;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rel[3] === 'c') {
- y -= round(h / 2);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rel[3] === 'c') {
+ y -= round(h / 2);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rel[4] === 'c') {
- x -= round(w / 2);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rel[4] === 'c') {
+ x -= round(w / 2);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return create(x, y, w, h);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return create(x, y, w, h);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Tests various positions to get the most suitable one.
- *
- * @method findBestRelativePosition
- * @param {Rect} rect Rect to use as source.
- * @param {Rect} targetRect Rect to move relative to.
- * @param {Rect} constrainRect Rect to constrain within.
- * @param {Array} rels Array of relative positions to test against.
- */
- function findBestRelativePosition(rect, targetRect, constrainRect, rels) {
- var pos, i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Tests various positions to get the most suitable one.
+ *
+ * @method findBestRelativePosition
+ * @param {Rect} rect Rect to use as source.
+ * @param {Rect} targetRect Rect to move relative to.
+ * @param {Rect} constrainRect Rect to constrain within.
+ * @param {Array} rels Array of relative positions to test against.
+ */
+ function findBestRelativePosition(rect, targetRect, constrainRect, rels) {
+ var pos, i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0; i < rels.length; i++) {
- pos = relativePosition(rect, targetRect, rels[i]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0; i < rels.length; i++) {
+ pos = relativePosition(rect, targetRect, rels[i]);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (pos.x >= constrainRect.x && pos.x + pos.w <= constrainRect.w + constrainRect.x &&
- pos.y >= constrainRect.y && pos.y + pos.h <= constrainRect.h + constrainRect.y) {
- return rels[i];
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (pos.x >= constrainRect.x && pos.x + pos.w <= constrainRect.w + constrainRect.x &&
+ pos.y >= constrainRect.y && pos.y + pos.h <= constrainRect.h + constrainRect.y) {
+ return rels[i];
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Inflates the rect in all directions.
- *
- * @method inflate
- * @param {Rect} rect Rect to expand.
- * @param {Number} w Relative width to expand by.
- * @param {Number} h Relative height to expand by.
- * @return {Rect} New expanded rect.
- */
- function inflate(rect, w, h) {
- return create(rect.x - w, rect.y - h, rect.w + w * 2, rect.h + h * 2);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Inflates the rect in all directions.
+ *
+ * @method inflate
+ * @param {Rect} rect Rect to expand.
+ * @param {Number} w Relative width to expand by.
+ * @param {Number} h Relative height to expand by.
+ * @return {Rect} New expanded rect.
+ */
+ function inflate(rect, w, h) {
+ return create(rect.x - w, rect.y - h, rect.w + w * 2, rect.h + h * 2);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the intersection of the specified rectangles.
- *
- * @method intersect
- * @param {Rect} rect The first rectangle to compare.
- * @param {Rect} cropRect The second rectangle to compare.
- * @return {Rect} The intersection of the two rectangles or null if they don't intersect.
- */
- function intersect(rect, cropRect) {
- var x1, y1, x2, y2;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the intersection of the specified rectangles.
+ *
+ * @method intersect
+ * @param {Rect} rect The first rectangle to compare.
+ * @param {Rect} cropRect The second rectangle to compare.
+ * @return {Rect} The intersection of the two rectangles or null if they don't intersect.
+ */
+ function intersect(rect, cropRect) {
+ var x1, y1, x2, y2;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- x1 = max(rect.x, cropRect.x);
- y1 = max(rect.y, cropRect.y);
- x2 = min(rect.x + rect.w, cropRect.x + cropRect.w);
- y2 = min(rect.y + rect.h, cropRect.y + cropRect.h);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ x1 = max(rect.x, cropRect.x);
+ y1 = max(rect.y, cropRect.y);
+ x2 = min(rect.x + rect.w, cropRect.x + cropRect.w);
+ y2 = min(rect.y + rect.h, cropRect.y + cropRect.h);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (x2 - x1 < 0 || y2 - y1 < 0) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (x2 - x1 < 0 || y2 - y1 < 0) {
+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return create(x1, y1, x2 - x1, y2 - y1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return create(x1, y1, x2 - x1, y2 - y1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a rect clamped within the specified clamp rect. This forces the
- * rect to be inside the clamp rect.
- *
- * @method clamp
- * @param {Rect} rect Rectangle to force within clamp rect.
- * @param {Rect} clampRect Rectable to force within.
- * @param {Boolean} fixedSize True/false if size should be fixed.
- * @return {Rect} Clamped rect.
- */
- function clamp(rect, clampRect, fixedSize) {
- var underflowX1, underflowY1, overflowX2, overflowY2,
- x1, y1, x2, y2, cx2, cy2;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a rect clamped within the specified clamp rect. This forces the
+ * rect to be inside the clamp rect.
+ *
+ * @method clamp
+ * @param {Rect} rect Rectangle to force within clamp rect.
+ * @param {Rect} clampRect Rectable to force within.
+ * @param {Boolean} fixedSize True/false if size should be fixed.
+ * @return {Rect} Clamped rect.
+ */
+ function clamp(rect, clampRect, fixedSize) {
+ var underflowX1, underflowY1, overflowX2, overflowY2,
+ x1, y1, x2, y2, cx2, cy2;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- x1 = rect.x;
- y1 = rect.y;
- x2 = rect.x + rect.w;
- y2 = rect.y + rect.h;
- cx2 = clampRect.x + clampRect.w;
- cy2 = clampRect.y + clampRect.h;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ x1 = rect.x;
+ y1 = rect.y;
+ x2 = rect.x + rect.w;
+ y2 = rect.y + rect.h;
+ cx2 = clampRect.x + clampRect.w;
+ cy2 = clampRect.y + clampRect.h;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- underflowX1 = max(0, clampRect.x - x1);
- underflowY1 = max(0, clampRect.y - y1);
- overflowX2 = max(0, x2 - cx2);
- overflowY2 = max(0, y2 - cy2);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ underflowX1 = max(0, clampRect.x - x1);
+ underflowY1 = max(0, clampRect.y - y1);
+ overflowX2 = max(0, x2 - cx2);
+ overflowY2 = max(0, y2 - cy2);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- x1 += underflowX1;
- y1 += underflowY1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ x1 += underflowX1;
+ y1 += underflowY1;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (fixedSize) {
- x2 += underflowX1;
- y2 += underflowY1;
- x1 -= overflowX2;
- y1 -= overflowY2;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (fixedSize) {
+ x2 += underflowX1;
+ y2 += underflowY1;
+ x1 -= overflowX2;
+ y1 -= overflowY2;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- x2 -= overflowX2;
- y2 -= overflowY2;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ x2 -= overflowX2;
+ y2 -= overflowY2;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return create(x1, y1, x2 - x1, y2 - y1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return create(x1, y1, x2 - x1, y2 - y1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates a new rectangle object.
- *
- * @method create
- * @param {Number} x Rectangle x location.
- * @param {Number} y Rectangle y location.
- * @param {Number} w Rectangle width.
- * @param {Number} h Rectangle height.
- * @return {Rect} New rectangle object.
- */
- function create(x, y, w, h) {
- return {x: x, y: y, w: w, h: h};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates a new rectangle object.
+ *
+ * @method create
+ * @param {Number} x Rectangle x location.
+ * @param {Number} y Rectangle y location.
+ * @param {Number} w Rectangle width.
+ * @param {Number} h Rectangle height.
+ * @return {Rect} New rectangle object.
+ */
+ function create(x, y, w, h) {
+ return { x: x, y: y, w: w, h: h };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates a new rectangle object form a clientRects object.
- *
- * @method fromClientRect
- * @param {ClientRect} clientRect DOM ClientRect object.
- * @return {Rect} New rectangle object.
- */
- function fromClientRect(clientRect) {
- return create(clientRect.left, clientRect.top, clientRect.width, clientRect.height);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates a new rectangle object form a clientRects object.
+ *
+ * @method fromClientRect
+ * @param {ClientRect} clientRect DOM ClientRect object.
+ * @return {Rect} New rectangle object.
+ */
+ function fromClientRect(clientRect) {
+ return create(clientRect.left, clientRect.top, clientRect.width, clientRect.height);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- inflate: inflate,
- relativePosition: relativePosition,
- findBestRelativePosition: findBestRelativePosition,
- intersect: intersect,
- clamp: clamp,
- create: create,
- fromClientRect: fromClientRect
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ inflate: inflate,
+ relativePosition: relativePosition,
+ findBestRelativePosition: findBestRelativePosition,
+ intersect: intersect,
+ clamp: clamp,
+ create: create,
+ fromClientRect: fromClientRect
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/util/Promise.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Promise.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Promise polyfill under MIT license: https://github.com/taylorhakes/promise-polyfill
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -336,196 +320,197 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Modifed to be a feature fill and wrapped as tinymce module.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/util/Promise", [], function() {
- if (window.Promise) {
- return window.Promise;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.Promise',
+ [],
+ function () {
+ if (window.Promise) {
+ return window.Promise;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Use polyfill for setImmediate for performance gains
- var asap = Promise.immediateFn || (typeof setImmediate === 'function' && setImmediate) ||
- function(fn) { setTimeout(fn, 1); };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Use polyfill for setImmediate for performance gains
+ var asap = Promise.immediateFn || (typeof setImmediate === 'function' && setImmediate) ||
+ function (fn) { setTimeout(fn, 1); };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Polyfill for Function.prototype.bind
- function bind(fn, thisArg) {
- return function() {
- fn.apply(thisArg, arguments);
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Polyfill for Function.prototype.bind
+ function bind(fn, thisArg) {
+ return function () {
+ fn.apply(thisArg, arguments);
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isArray = Array.isArray || function(value) { return Object.prototype.toString.call(value) === "[object Array]"; };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isArray = Array.isArray || function (value) { return Object.prototype.toString.call(value) === "[object Array]"; };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function Promise(fn) {
- if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new');
- if (typeof fn !== 'function') throw new TypeError('not a function');
- this._state = null;
- this._value = null;
- this._deferreds = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function Promise(fn) {
+ if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new');
+ if (typeof fn !== 'function') throw new TypeError('not a function');
+ this._state = null;
+ this._value = null;
+ this._deferreds = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- doResolve(fn, bind(resolve, this), bind(reject, this));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ doResolve(fn, bind(resolve, this), bind(reject, this));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function handle(deferred) {
- var me = this;
- if (this._state === null) {
- this._deferreds.push(deferred);
- return;
- }
- asap(function() {
- var cb = me._state ? deferred.onFulfilled : deferred.onRejected;
- if (cb === null) {
- (me._state ? deferred.resolve : deferred.reject)(me._value);
- return;
- }
- var ret;
- try {
- ret = cb(me._value);
- }
- catch (e) {
- deferred.reject(e);
- return;
- }
- deferred.resolve(ret);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function handle(deferred) {
+ var me = this;
+ if (this._state === null) {
+ this._deferreds.push(deferred);
+ return;
+ }
+ asap(function () {
+ var cb = me._state ? deferred.onFulfilled : deferred.onRejected;
+ if (cb === null) {
+ (me._state ? deferred.resolve : deferred.reject)(me._value);
+ return;
+ }
+ var ret;
+ try {
+ ret = cb(me._value);
+ }
+ catch (e) {
+ deferred.reject(e);
+ return;
+ }
+ deferred.resolve(ret);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function resolve(newValue) {
- try { //Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
- if (newValue === this) throw new TypeError('A promise cannot be resolved with itself.');
- if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
- var then = newValue.then;
- if (typeof then === 'function') {
- doResolve(bind(then, newValue), bind(resolve, this), bind(reject, this));
- return;
- }
- }
- this._state = true;
- this._value = newValue;
- finale.call(this);
- } catch (e) { reject.call(this, e); }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function resolve(newValue) {
+ try { //Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
+ if (newValue === this) throw new TypeError('A promise cannot be resolved with itself.');
+ if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
+ var then = newValue.then;
+ if (typeof then === 'function') {
+ doResolve(bind(then, newValue), bind(resolve, this), bind(reject, this));
+ return;
+ }
+ }
+ this._state = true;
+ this._value = newValue;
+ finale.call(this);
+ } catch (e) { reject.call(this, e); }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function reject(newValue) {
- this._state = false;
- this._value = newValue;
- finale.call(this);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function reject(newValue) {
+ this._state = false;
+ this._value = newValue;
+ finale.call(this);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function finale() {
- for (var i = 0, len = this._deferreds.length; i < len; i++) {
- handle.call(this, this._deferreds[i]);
- }
- this._deferreds = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function finale() {
+ for (var i = 0, len = this._deferreds.length; i < len; i++) {
+ handle.call(this, this._deferreds[i]);
+ }
+ this._deferreds = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function Handler(onFulfilled, onRejected, resolve, reject){
- this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
- this.onRejected = typeof onRejected === 'function' ? onRejected : null;
- this.resolve = resolve;
- this.reject = reject;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function Handler(onFulfilled, onRejected, resolve, reject) {
+ this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
+ this.onRejected = typeof onRejected === 'function' ? onRejected : null;
+ this.resolve = resolve;
+ this.reject = reject;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Take a potentially misbehaving resolver function and make sure
- * onFulfilled and onRejected are only called once.
- *
- * Makes no guarantees about asynchrony.
- */
- function doResolve(fn, onFulfilled, onRejected) {
- var done = false;
- try {
- fn(function (value) {
- if (done) return;
- done = true;
- onFulfilled(value);
- }, function (reason) {
- if (done) return;
- done = true;
- onRejected(reason);
- });
- } catch (ex) {
- if (done) return;
- done = true;
- onRejected(ex);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Take a potentially misbehaving resolver function and make sure
+ * onFulfilled and onRejected are only called once.
+ *
+ * Makes no guarantees about asynchrony.
+ */
+ function doResolve(fn, onFulfilled, onRejected) {
+ var done = false;
+ try {
+ fn(function (value) {
+ if (done) return;
+ done = true;
+ onFulfilled(value);
+ }, function (reason) {
+ if (done) return;
+ done = true;
+ onRejected(reason);
+ });
+ } catch (ex) {
+ if (done) return;
+ done = true;
+ onRejected(ex);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Promise.prototype['catch'] = function (onRejected) {
- return this.then(null, onRejected);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Promise.prototype['catch'] = function (onRejected) {
+ return this.then(null, onRejected);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Promise.prototype.then = function(onFulfilled, onRejected) {
- var me = this;
- return new Promise(function(resolve, reject) {
- handle.call(me, new Handler(onFulfilled, onRejected, resolve, reject));
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Promise.prototype.then = function (onFulfilled, onRejected) {
+ var me = this;
+ return new Promise(function (resolve, reject) {
+ handle.call(me, new Handler(onFulfilled, onRejected, resolve, reject));
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Promise.all = function () {
- var args = Array.prototype.slice.call(arguments.length === 1 && isArray(arguments[0]) ? arguments[0] : arguments);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Promise.all = function () {
+ var args = Array.prototype.slice.call(arguments.length === 1 && isArray(arguments[0]) ? arguments[0] : arguments);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return new Promise(function (resolve, reject) {
- if (args.length === 0) return resolve([]);
- var remaining = args.length;
- function res(i, val) {
- try {
- if (val && (typeof val === 'object' || typeof val === 'function')) {
- var then = val.then;
- if (typeof then === 'function') {
- then.call(val, function (val) { res(i, val); }, reject);
- return;
- }
- }
- args[i] = val;
- if (--remaining === 0) {
- resolve(args);
- }
- } catch (ex) {
- reject(ex);
- }
- }
- for (var i = 0; i < args.length; i++) {
- res(i, args[i]);
- }
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return new Promise(function (resolve, reject) {
+ if (args.length === 0) return resolve([]);
+ var remaining = args.length;
+ function res(i, val) {
+ try {
+ if (val && (typeof val === 'object' || typeof val === 'function')) {
+ var then = val.then;
+ if (typeof then === 'function') {
+ then.call(val, function (val) { res(i, val); }, reject);
+ return;
+ }
+ }
+ args[i] = val;
+ if (--remaining === 0) {
+ resolve(args);
+ }
+ } catch (ex) {
+ reject(ex);
+ }
+ }
+ for (var i = 0; i < args.length; i++) {
+ res(i, args[i]);
+ }
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Promise.resolve = function (value) {
- if (value && typeof value === 'object' && value.constructor === Promise) {
- return value;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Promise.resolve = function (value) {
+ if (value && typeof value === 'object' && value.constructor === Promise) {
+ return value;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return new Promise(function (resolve) {
- resolve(value);
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return new Promise(function (resolve) {
+ resolve(value);
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Promise.reject = function (value) {
- return new Promise(function (resolve, reject) {
- reject(value);
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Promise.reject = function (value) {
+ return new Promise(function (resolve, reject) {
+ reject(value);
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Promise.race = function (values) {
- return new Promise(function (resolve, reject) {
- for(var i = 0, len = values.length; i < len; i++) {
- values[i].then(resolve, reject);
- }
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Promise.race = function (values) {
+ return new Promise(function (resolve, reject) {
+ for (var i = 0, len = values.length; i < len; i++) {
+ values[i].then(resolve, reject);
+ }
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Promise;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Promise;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /* jshint ignore:end */
</span><span class="cx" style="display: block; padding: 0 10px"> /* eslint-enable */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-// Included from: js/tinymce/classes/util/Delay.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Delay.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -536,195 +521,197 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.util.Delay
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/util/Delay", [
- "tinymce/util/Promise"
-], function(Promise) {
- var requestAnimationFramePromise;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.Delay',
+ [
+ "tinymce.core.util.Promise"
+ ],
+ function (Promise) {
+ var requestAnimationFramePromise;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function requestAnimationFrame(callback, element) {
- var i, requestAnimationFrameFunc = window.requestAnimationFrame, vendors = ['ms', 'moz', 'webkit'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function requestAnimationFrame(callback, element) {
+ var i, requestAnimationFrameFunc = window.requestAnimationFrame, vendors = ['ms', 'moz', 'webkit'];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function featurefill(callback) {
- window.setTimeout(callback, 0);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function featurefill(callback) {
+ window.setTimeout(callback, 0);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0; i < vendors.length && !requestAnimationFrameFunc; i++) {
- requestAnimationFrameFunc = window[vendors[i] + 'RequestAnimationFrame'];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0; i < vendors.length && !requestAnimationFrameFunc; i++) {
+ requestAnimationFrameFunc = window[vendors[i] + 'RequestAnimationFrame'];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!requestAnimationFrameFunc) {
- requestAnimationFrameFunc = featurefill;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!requestAnimationFrameFunc) {
+ requestAnimationFrameFunc = featurefill;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- requestAnimationFrameFunc(callback, element);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ requestAnimationFrameFunc(callback, element);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function wrappedSetTimeout(callback, time) {
- if (typeof time != 'number') {
- time = 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function wrappedSetTimeout(callback, time) {
+ if (typeof time != 'number') {
+ time = 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return setTimeout(callback, time);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return setTimeout(callback, time);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function wrappedSetInterval(callback, time) {
- if (typeof time != 'number') {
- time = 1; // IE 8 needs it to be > 0
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function wrappedSetInterval(callback, time) {
+ if (typeof time != 'number') {
+ time = 1; // IE 8 needs it to be > 0
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return setInterval(callback, time);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return setInterval(callback, time);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function wrappedClearTimeout(id) {
- return clearTimeout(id);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function wrappedClearTimeout(id) {
+ return clearTimeout(id);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function wrappedClearInterval(id) {
- return clearInterval(id);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function wrappedClearInterval(id) {
+ return clearInterval(id);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function debounce(callback, time) {
- var timer, func;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function debounce(callback, time) {
+ var timer, func;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- func = function() {
- var args = arguments;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ func = function () {
+ var args = arguments;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- clearTimeout(timer);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ clearTimeout(timer);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- timer = wrappedSetTimeout(function() {
- callback.apply(this, args);
- }, time);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ timer = wrappedSetTimeout(function () {
+ callback.apply(this, args);
+ }, time);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- func.stop = function() {
- clearTimeout(timer);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ func.stop = function () {
+ clearTimeout(timer);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return func;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return func;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- /**
- * Requests an animation frame and fallbacks to a timeout on older browsers.
- *
- * @method requestAnimationFrame
- * @param {function} callback Callback to execute when a new frame is available.
- * @param {DOMElement} element Optional element to scope it to.
- */
- requestAnimationFrame: function(callback, element) {
- if (requestAnimationFramePromise) {
- requestAnimationFramePromise.then(callback);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ /**
+ * Requests an animation frame and fallbacks to a timeout on older browsers.
+ *
+ * @method requestAnimationFrame
+ * @param {function} callback Callback to execute when a new frame is available.
+ * @param {DOMElement} element Optional element to scope it to.
+ */
+ requestAnimationFrame: function (callback, element) {
+ if (requestAnimationFramePromise) {
+ requestAnimationFramePromise.then(callback);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- requestAnimationFramePromise = new Promise(function(resolve) {
- if (!element) {
- element = document.body;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ requestAnimationFramePromise = new Promise(function (resolve) {
+ if (!element) {
+ element = document.body;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- requestAnimationFrame(resolve, element);
- }).then(callback);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ requestAnimationFrame(resolve, element);
+ }).then(callback);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets a timer in ms and executes the specified callback when the timer runs out.
- *
- * @method setTimeout
- * @param {function} callback Callback to execute when timer runs out.
- * @param {Number} time Optional time to wait before the callback is executed, defaults to 0.
- * @return {Number} Timeout id number.
- */
- setTimeout: wrappedSetTimeout,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets a timer in ms and executes the specified callback when the timer runs out.
+ *
+ * @method setTimeout
+ * @param {function} callback Callback to execute when timer runs out.
+ * @param {Number} time Optional time to wait before the callback is executed, defaults to 0.
+ * @return {Number} Timeout id number.
+ */
+ setTimeout: wrappedSetTimeout,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets an interval timer in ms and executes the specified callback at every interval of that time.
- *
- * @method setInterval
- * @param {function} callback Callback to execute when interval time runs out.
- * @param {Number} time Optional time to wait before the callback is executed, defaults to 0.
- * @return {Number} Timeout id number.
- */
- setInterval: wrappedSetInterval,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets an interval timer in ms and executes the specified callback at every interval of that time.
+ *
+ * @method setInterval
+ * @param {function} callback Callback to execute when interval time runs out.
+ * @param {Number} time Optional time to wait before the callback is executed, defaults to 0.
+ * @return {Number} Timeout id number.
+ */
+ setInterval: wrappedSetInterval,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets an editor timeout it's similar to setTimeout except that it checks if the editor instance is
- * still alive when the callback gets executed.
- *
- * @method setEditorTimeout
- * @param {tinymce.Editor} editor Editor instance to check the removed state on.
- * @param {function} callback Callback to execute when timer runs out.
- * @param {Number} time Optional time to wait before the callback is executed, defaults to 0.
- * @return {Number} Timeout id number.
- */
- setEditorTimeout: function(editor, callback, time) {
- return wrappedSetTimeout(function() {
- if (!editor.removed) {
- callback();
- }
- }, time);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets an editor timeout it's similar to setTimeout except that it checks if the editor instance is
+ * still alive when the callback gets executed.
+ *
+ * @method setEditorTimeout
+ * @param {tinymce.Editor} editor Editor instance to check the removed state on.
+ * @param {function} callback Callback to execute when timer runs out.
+ * @param {Number} time Optional time to wait before the callback is executed, defaults to 0.
+ * @return {Number} Timeout id number.
+ */
+ setEditorTimeout: function (editor, callback, time) {
+ return wrappedSetTimeout(function () {
+ if (!editor.removed) {
+ callback();
+ }
+ }, time);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets an interval timer it's similar to setInterval except that it checks if the editor instance is
- * still alive when the callback gets executed.
- *
- * @method setEditorInterval
- * @param {function} callback Callback to execute when interval time runs out.
- * @param {Number} time Optional time to wait before the callback is executed, defaults to 0.
- * @return {Number} Timeout id number.
- */
- setEditorInterval: function(editor, callback, time) {
- var timer;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets an interval timer it's similar to setInterval except that it checks if the editor instance is
+ * still alive when the callback gets executed.
+ *
+ * @method setEditorInterval
+ * @param {function} callback Callback to execute when interval time runs out.
+ * @param {Number} time Optional time to wait before the callback is executed, defaults to 0.
+ * @return {Number} Timeout id number.
+ */
+ setEditorInterval: function (editor, callback, time) {
+ var timer;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- timer = wrappedSetInterval(function() {
- if (!editor.removed) {
- callback();
- } else {
- clearInterval(timer);
- }
- }, time);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ timer = wrappedSetInterval(function () {
+ if (!editor.removed) {
+ callback();
+ } else {
+ clearInterval(timer);
+ }
+ }, time);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return timer;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return timer;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates debounced callback function that only gets executed once within the specified time.
- *
- * @method debounce
- * @param {function} callback Callback to execute when timer finishes.
- * @param {Number} time Optional time to wait before the callback is executed, defaults to 0.
- * @return {Function} debounced function callback.
- */
- debounce: debounce,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates debounced callback function that only gets executed once within the specified time.
+ *
+ * @method debounce
+ * @param {function} callback Callback to execute when timer finishes.
+ * @param {Number} time Optional time to wait before the callback is executed, defaults to 0.
+ * @return {Function} debounced function callback.
+ */
+ debounce: debounce,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Throttle needs to be debounce due to backwards compatibility.
- throttle: debounce,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Throttle needs to be debounce due to backwards compatibility.
+ throttle: debounce,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Clears an interval timer so it won't execute.
- *
- * @method clearInterval
- * @param {Number} Interval timer id number.
- */
- clearInterval: wrappedClearInterval,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Clears an interval timer so it won't execute.
+ *
+ * @method clearInterval
+ * @param {Number} Interval timer id number.
+ */
+ clearInterval: wrappedClearInterval,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Clears an timeout timer so it won't execute.
- *
- * @method clearTimeout
- * @param {Number} Timeout timer id number.
- */
- clearTimeout: wrappedClearTimeout
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Clears an timeout timer so it won't execute.
+ *
+ * @method clearTimeout
+ * @param {Number} Timeout timer id number.
+ */
+ clearTimeout: wrappedClearTimeout
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/Env.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Env.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -738,178 +725,181 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.Env
</span><span class="cx" style="display: block; padding: 0 10px"> * @static
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/Env", [], function() {
- var nav = navigator, userAgent = nav.userAgent;
- var opera, webkit, ie, ie11, ie12, gecko, mac, iDevice, android, fileApi, phone, tablet, windowsPhone;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.Env',
+ [
+ ],
+ function () {
+ var nav = navigator, userAgent = nav.userAgent;
+ var opera, webkit, ie, ie11, ie12, gecko, mac, iDevice, android, fileApi, phone, tablet, windowsPhone;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function matchMediaQuery(query) {
- return "matchMedia" in window ? matchMedia(query).matches : false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function matchMediaQuery(query) {
+ return "matchMedia" in window ? matchMedia(query).matches : false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- opera = window.opera && window.opera.buildNumber;
- android = /Android/.test(userAgent);
- webkit = /WebKit/.test(userAgent);
- ie = !webkit && !opera && (/MSIE/gi).test(userAgent) && (/Explorer/gi).test(nav.appName);
- ie = ie && /MSIE (\w+)\./.exec(userAgent)[1];
- ie11 = userAgent.indexOf('Trident/') != -1 && (userAgent.indexOf('rv:') != -1 || nav.appName.indexOf('Netscape') != -1) ? 11 : false;
- ie12 = (userAgent.indexOf('Edge/') != -1 && !ie && !ie11) ? 12 : false;
- ie = ie || ie11 || ie12;
- gecko = !webkit && !ie11 && /Gecko/.test(userAgent);
- mac = userAgent.indexOf('Mac') != -1;
- iDevice = /(iPad|iPhone)/.test(userAgent);
- fileApi = "FormData" in window && "FileReader" in window && "URL" in window && !!URL.createObjectURL;
- phone = matchMediaQuery("only screen and (max-device-width: 480px)") && (android || iDevice);
- tablet = matchMediaQuery("only screen and (min-width: 800px)") && (android || iDevice);
- windowsPhone = userAgent.indexOf('Windows Phone') != -1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ opera = window.opera && window.opera.buildNumber;
+ android = /Android/.test(userAgent);
+ webkit = /WebKit/.test(userAgent);
+ ie = !webkit && !opera && (/MSIE/gi).test(userAgent) && (/Explorer/gi).test(nav.appName);
+ ie = ie && /MSIE (\w+)\./.exec(userAgent)[1];
+ ie11 = userAgent.indexOf('Trident/') != -1 && (userAgent.indexOf('rv:') != -1 || nav.appName.indexOf('Netscape') != -1) ? 11 : false;
+ ie12 = (userAgent.indexOf('Edge/') != -1 && !ie && !ie11) ? 12 : false;
+ ie = ie || ie11 || ie12;
+ gecko = !webkit && !ie11 && /Gecko/.test(userAgent);
+ mac = userAgent.indexOf('Mac') != -1;
+ iDevice = /(iPad|iPhone)/.test(userAgent);
+ fileApi = "FormData" in window && "FileReader" in window && "URL" in window && !!URL.createObjectURL;
+ phone = matchMediaQuery("only screen and (max-device-width: 480px)") && (android || iDevice);
+ tablet = matchMediaQuery("only screen and (min-width: 800px)") && (android || iDevice);
+ windowsPhone = userAgent.indexOf('Windows Phone') != -1;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (ie12) {
- webkit = false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (ie12) {
+ webkit = false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Is a iPad/iPhone and not on iOS5 sniff the WebKit version since older iOS WebKit versions
- // says it has contentEditable support but there is no visible caret.
- var contentEditable = !iDevice || fileApi || userAgent.match(/AppleWebKit\/(\d*)/)[1] >= 534;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Is a iPad/iPhone and not on iOS5 sniff the WebKit version since older iOS WebKit versions
+ // says it has contentEditable support but there is no visible caret.
+ var contentEditable = !iDevice || fileApi || userAgent.match(/AppleWebKit\/(\d*)/)[1] >= 534;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- /**
- * Constant that is true if the browser is Opera.
- *
- * @property opera
- * @type Boolean
- * @final
- */
- opera: opera,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ /**
+ * Constant that is true if the browser is Opera.
+ *
+ * @property opera
+ * @type Boolean
+ * @final
+ */
+ opera: opera,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constant that is true if the browser is WebKit (Safari/Chrome).
- *
- * @property webKit
- * @type Boolean
- * @final
- */
- webkit: webkit,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constant that is true if the browser is WebKit (Safari/Chrome).
+ *
+ * @property webKit
+ * @type Boolean
+ * @final
+ */
+ webkit: webkit,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constant that is more than zero if the browser is IE.
- *
- * @property ie
- * @type Boolean
- * @final
- */
- ie: ie,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constant that is more than zero if the browser is IE.
+ *
+ * @property ie
+ * @type Boolean
+ * @final
+ */
+ ie: ie,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constant that is true if the browser is Gecko.
- *
- * @property gecko
- * @type Boolean
- * @final
- */
- gecko: gecko,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constant that is true if the browser is Gecko.
+ *
+ * @property gecko
+ * @type Boolean
+ * @final
+ */
+ gecko: gecko,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constant that is true if the os is Mac OS.
- *
- * @property mac
- * @type Boolean
- * @final
- */
- mac: mac,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constant that is true if the os is Mac OS.
+ *
+ * @property mac
+ * @type Boolean
+ * @final
+ */
+ mac: mac,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constant that is true if the os is iOS.
- *
- * @property iOS
- * @type Boolean
- * @final
- */
- iOS: iDevice,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constant that is true if the os is iOS.
+ *
+ * @property iOS
+ * @type Boolean
+ * @final
+ */
+ iOS: iDevice,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constant that is true if the os is android.
- *
- * @property android
- * @type Boolean
- * @final
- */
- android: android,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constant that is true if the os is android.
+ *
+ * @property android
+ * @type Boolean
+ * @final
+ */
+ android: android,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constant that is true if the browser supports editing.
- *
- * @property contentEditable
- * @type Boolean
- * @final
- */
- contentEditable: contentEditable,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constant that is true if the browser supports editing.
+ *
+ * @property contentEditable
+ * @type Boolean
+ * @final
+ */
+ contentEditable: contentEditable,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Transparent image data url.
- *
- * @property transparentSrc
- * @type Boolean
- * @final
- */
- transparentSrc: "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Transparent image data url.
+ *
+ * @property transparentSrc
+ * @type Boolean
+ * @final
+ */
+ transparentSrc: "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the browser can or can't place the caret after a inline block like an image.
- *
- * @property noCaretAfter
- * @type Boolean
- * @final
- */
- caretAfter: ie != 8,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the browser can or can't place the caret after a inline block like an image.
+ *
+ * @property noCaretAfter
+ * @type Boolean
+ * @final
+ */
+ caretAfter: ie != 8,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constant that is true if the browser supports native DOM Ranges. IE 9+.
- *
- * @property range
- * @type Boolean
- */
- range: window.getSelection && "Range" in window,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constant that is true if the browser supports native DOM Ranges. IE 9+.
+ *
+ * @property range
+ * @type Boolean
+ */
+ range: window.getSelection && "Range" in window,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the IE document mode for non IE browsers this will fake IE 10.
- *
- * @property documentMode
- * @type Number
- */
- documentMode: ie && !ie12 ? (document.documentMode || 7) : 10,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the IE document mode for non IE browsers this will fake IE 10.
+ *
+ * @property documentMode
+ * @type Number
+ */
+ documentMode: ie && !ie12 ? (document.documentMode || 7) : 10,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constant that is true if the browser has a modern file api.
- *
- * @property fileApi
- * @type Boolean
- */
- fileApi: fileApi,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constant that is true if the browser has a modern file api.
+ *
+ * @property fileApi
+ * @type Boolean
+ */
+ fileApi: fileApi,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constant that is true if the browser supports contentEditable=false regions.
- *
- * @property ceFalse
- * @type Boolean
- */
- ceFalse: (ie === false || ie > 8),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constant that is true if the browser supports contentEditable=false regions.
+ *
+ * @property ceFalse
+ * @type Boolean
+ */
+ ceFalse: (ie === false || ie > 8),
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constant if CSP mode is possible or not. Meaning we can't use script urls for the iframe.
- */
- canHaveCSP: (ie === false || ie > 11),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constant if CSP mode is possible or not. Meaning we can't use script urls for the iframe.
+ */
+ canHaveCSP: (ie === false || ie > 11),
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- desktop: !phone && !tablet,
- windowsPhone: windowsPhone
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ desktop: !phone && !tablet,
+ windowsPhone: windowsPhone
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/dom/EventUtils.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * EventUtils.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -923,601 +913,612 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.dom.EventUtils
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/dom/EventUtils", [
- "tinymce/util/Delay",
- "tinymce/Env"
-], function(Delay, Env) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.EventUtils',
+ [
+ "tinymce.core.util.Delay",
+ "tinymce.core.Env"
+ ],
+ function (Delay, Env) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var eventExpandoPrefix = "mce-data-";
- var mouseEventRe = /^(?:mouse|contextmenu)|click/;
- var deprecated = {
- keyLocation: 1, layerX: 1, layerY: 1, returnValue: 1,
- webkitMovementX: 1, webkitMovementY: 1, keyIdentifier: 1
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var eventExpandoPrefix = "mce-data-";
+ var mouseEventRe = /^(?:mouse|contextmenu)|click/;
+ var deprecated = {
+ keyLocation: 1, layerX: 1, layerY: 1, returnValue: 1,
+ webkitMovementX: 1, webkitMovementY: 1, keyIdentifier: 1
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Binds a native event to a callback on the speified target.
- */
- function addEvent(target, name, callback, capture) {
- if (target.addEventListener) {
- target.addEventListener(name, callback, capture || false);
- } else if (target.attachEvent) {
- target.attachEvent('on' + name, callback);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Checks if it is our own isDefaultPrevented function
+ var hasIsDefaultPrevented = function (event) {
+ return event.isDefaultPrevented === returnTrue || event.isDefaultPrevented === returnFalse;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Unbinds a native event callback on the specified target.
- */
- function removeEvent(target, name, callback, capture) {
- if (target.removeEventListener) {
- target.removeEventListener(name, callback, capture || false);
- } else if (target.detachEvent) {
- target.detachEvent('on' + name, callback);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Dummy function that gets replaced on the delegation state functions
+ var returnFalse = function () {
+ return false;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Gets the event target based on shadow dom properties like path and deepPath.
- */
- function getTargetFromShadowDom(event, defaultTarget) {
- var path, target = defaultTarget;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Dummy function that gets replaced on the delegation state functions
+ var returnTrue = function () {
+ return true;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // When target element is inside Shadow DOM we need to take first element from path
- // otherwise we'll get Shadow Root parent, not actual target element
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Binds a native event to a callback on the speified target.
+ */
+ function addEvent(target, name, callback, capture) {
+ if (target.addEventListener) {
+ target.addEventListener(name, callback, capture || false);
+ } else if (target.attachEvent) {
+ target.attachEvent('on' + name, callback);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Normalize target for WebComponents v0 implementation (in Chrome)
- path = event.path;
- if (path && path.length > 0) {
- target = path[0];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Unbinds a native event callback on the specified target.
+ */
+ function removeEvent(target, name, callback, capture) {
+ if (target.removeEventListener) {
+ target.removeEventListener(name, callback, capture || false);
+ } else if (target.detachEvent) {
+ target.detachEvent('on' + name, callback);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Normalize target for WebComponents v1 implementation (standard)
- if (event.deepPath) {
- path = event.deepPath();
- if (path && path.length > 0) {
- target = path[0];
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Gets the event target based on shadow dom properties like path and deepPath.
+ */
+ function getTargetFromShadowDom(event, defaultTarget) {
+ var path, target = defaultTarget;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return target;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // When target element is inside Shadow DOM we need to take first element from path
+ // otherwise we'll get Shadow Root parent, not actual target element
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Normalizes a native event object or just adds the event specific methods on a custom event.
- */
- function fix(originalEvent, data) {
- var name, event = data || {}, undef;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Normalize target for WebComponents v0 implementation (in Chrome)
+ path = event.path;
+ if (path && path.length > 0) {
+ target = path[0];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Dummy function that gets replaced on the delegation state functions
- function returnFalse() {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Normalize target for WebComponents v1 implementation (standard)
+ if (event.deepPath) {
+ path = event.deepPath();
+ if (path && path.length > 0) {
+ target = path[0];
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Dummy function that gets replaced on the delegation state functions
- function returnTrue() {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return target;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Copy all properties from the original event
- for (name in originalEvent) {
- // layerX/layerY is deprecated in Chrome and produces a warning
- if (!deprecated[name]) {
- event[name] = originalEvent[name];
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Normalizes a native event object or just adds the event specific methods on a custom event.
+ */
+ function fix(originalEvent, data) {
+ var name, event = data || {}, undef;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Normalize target IE uses srcElement
- if (!event.target) {
- event.target = event.srcElement || document;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Copy all properties from the original event
+ for (name in originalEvent) {
+ // layerX/layerY is deprecated in Chrome and produces a warning
+ if (!deprecated[name]) {
+ event[name] = originalEvent[name];
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Experimental shadow dom support
- if (Env.experimentalShadowDom) {
- event.target = getTargetFromShadowDom(originalEvent, event.target);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Normalize target IE uses srcElement
+ if (!event.target) {
+ event.target = event.srcElement || document;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Calculate pageX/Y if missing and clientX/Y available
- if (originalEvent && mouseEventRe.test(originalEvent.type) && originalEvent.pageX === undef && originalEvent.clientX !== undef) {
- var eventDoc = event.target.ownerDocument || document;
- var doc = eventDoc.documentElement;
- var body = eventDoc.body;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Experimental shadow dom support
+ if (Env.experimentalShadowDom) {
+ event.target = getTargetFromShadowDom(originalEvent, event.target);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- event.pageX = originalEvent.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) -
- (doc && doc.clientLeft || body && body.clientLeft || 0);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Calculate pageX/Y if missing and clientX/Y available
+ if (originalEvent && mouseEventRe.test(originalEvent.type) && originalEvent.pageX === undef && originalEvent.clientX !== undef) {
+ var eventDoc = event.target.ownerDocument || document;
+ var doc = eventDoc.documentElement;
+ var body = eventDoc.body;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- event.pageY = originalEvent.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) -
- (doc && doc.clientTop || body && body.clientTop || 0);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ event.pageX = originalEvent.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) -
+ (doc && doc.clientLeft || body && body.clientLeft || 0);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add preventDefault method
- event.preventDefault = function() {
- event.isDefaultPrevented = returnTrue;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ event.pageY = originalEvent.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) -
+ (doc && doc.clientTop || body && body.clientTop || 0);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Execute preventDefault on the original event object
- if (originalEvent) {
- if (originalEvent.preventDefault) {
- originalEvent.preventDefault();
- } else {
- originalEvent.returnValue = false; // IE
- }
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add preventDefault method
+ event.preventDefault = function () {
+ event.isDefaultPrevented = returnTrue;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add stopPropagation
- event.stopPropagation = function() {
- event.isPropagationStopped = returnTrue;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Execute preventDefault on the original event object
+ if (originalEvent) {
+ if (originalEvent.preventDefault) {
+ originalEvent.preventDefault();
+ } else {
+ originalEvent.returnValue = false; // IE
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Execute stopPropagation on the original event object
- if (originalEvent) {
- if (originalEvent.stopPropagation) {
- originalEvent.stopPropagation();
- } else {
- originalEvent.cancelBubble = true; // IE
- }
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add stopPropagation
+ event.stopPropagation = function () {
+ event.isPropagationStopped = returnTrue;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add stopImmediatePropagation
- event.stopImmediatePropagation = function() {
- event.isImmediatePropagationStopped = returnTrue;
- event.stopPropagation();
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Execute stopPropagation on the original event object
+ if (originalEvent) {
+ if (originalEvent.stopPropagation) {
+ originalEvent.stopPropagation();
+ } else {
+ originalEvent.cancelBubble = true; // IE
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add event delegation states
- if (!event.isDefaultPrevented) {
- event.isDefaultPrevented = returnFalse;
- event.isPropagationStopped = returnFalse;
- event.isImmediatePropagationStopped = returnFalse;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add stopImmediatePropagation
+ event.stopImmediatePropagation = function () {
+ event.isImmediatePropagationStopped = returnTrue;
+ event.stopPropagation();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add missing metaKey for IE 8
- if (typeof event.metaKey == 'undefined') {
- event.metaKey = false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add event delegation states
+ if (hasIsDefaultPrevented(event) === false) {
+ event.isDefaultPrevented = returnFalse;
+ event.isPropagationStopped = returnFalse;
+ event.isImmediatePropagationStopped = returnFalse;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return event;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add missing metaKey for IE 8
+ if (typeof event.metaKey == 'undefined') {
+ event.metaKey = false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Bind a DOMContentLoaded event across browsers and executes the callback once the page DOM is initialized.
- * It will also set/check the domLoaded state of the event_utils instance so ready isn't called multiple times.
- */
- function bindOnReady(win, callback, eventUtils) {
- var doc = win.document, event = {type: 'ready'};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return event;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (eventUtils.domLoaded) {
- callback(event);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Bind a DOMContentLoaded event across browsers and executes the callback once the page DOM is initialized.
+ * It will also set/check the domLoaded state of the event_utils instance so ready isn't called multiple times.
+ */
+ function bindOnReady(win, callback, eventUtils) {
+ var doc = win.document, event = { type: 'ready' };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Gets called when the DOM is ready
- function readyHandler() {
- if (!eventUtils.domLoaded) {
- eventUtils.domLoaded = true;
- callback(event);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (eventUtils.domLoaded) {
+ callback(event);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function waitForDomLoaded() {
- // Check complete or interactive state if there is a body
- // element on some iframes IE 8 will produce a null body
- if (doc.readyState === "complete" || (doc.readyState === "interactive" && doc.body)) {
- removeEvent(doc, "readystatechange", waitForDomLoaded);
- readyHandler();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isDocReady() {
+ // Check complete or interactive state if there is a body
+ // element on some iframes IE 8 will produce a null body
+ return doc.readyState === "complete" || (doc.readyState === "interactive" && doc.body);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function tryScroll() {
- try {
- // If IE is used, use the trick by Diego Perini licensed under MIT by request to the author.
- // http://javascript.nwbox.com/IEContentLoaded/
- doc.documentElement.doScroll("left");
- } catch (ex) {
- Delay.setTimeout(tryScroll);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Gets called when the DOM is ready
+ function readyHandler() {
+ if (!eventUtils.domLoaded) {
+ eventUtils.domLoaded = true;
+ callback(event);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- readyHandler();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function waitForDomLoaded() {
+ if (isDocReady()) {
+ removeEvent(doc, "readystatechange", waitForDomLoaded);
+ readyHandler();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Use W3C method
- if (doc.addEventListener) {
- if (doc.readyState === "complete") {
- readyHandler();
- } else {
- addEvent(win, 'DOMContentLoaded', readyHandler);
- }
- } else {
- // Use IE method
- addEvent(doc, "readystatechange", waitForDomLoaded);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function tryScroll() {
+ try {
+ // If IE is used, use the trick by Diego Perini licensed under MIT by request to the author.
+ // http://javascript.nwbox.com/IEContentLoaded/
+ doc.documentElement.doScroll("left");
+ } catch (ex) {
+ Delay.setTimeout(tryScroll);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Wait until we can scroll, when we can the DOM is initialized
- if (doc.documentElement.doScroll && win.self === win.top) {
- tryScroll();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ readyHandler();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Fallback if any of the above methods should fail for some odd reason
- addEvent(win, 'load', readyHandler);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Use W3C method (exclude IE 9,10 - readyState "interactive" became valid only in IE 11)
+ if (doc.addEventListener && !(Env.ie && Env.ie < 11)) {
+ if (isDocReady()) {
+ readyHandler();
+ } else {
+ addEvent(win, 'DOMContentLoaded', readyHandler);
+ }
+ } else {
+ // Use IE method
+ addEvent(doc, "readystatechange", waitForDomLoaded);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * This class enables you to bind/unbind native events to elements and normalize it's behavior across browsers.
- */
- function EventUtils() {
- var self = this, events = {}, count, expando, hasFocusIn, hasMouseEnterLeave, mouseEnterLeave;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Wait until we can scroll, when we can the DOM is initialized
+ if (doc.documentElement.doScroll && win.self === win.top) {
+ tryScroll();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- expando = eventExpandoPrefix + (+new Date()).toString(32);
- hasMouseEnterLeave = "onmouseenter" in document.documentElement;
- hasFocusIn = "onfocusin" in document.documentElement;
- mouseEnterLeave = {mouseenter: 'mouseover', mouseleave: 'mouseout'};
- count = 1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Fallback if any of the above methods should fail for some odd reason
+ addEvent(win, 'load', readyHandler);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // State if the DOMContentLoaded was executed or not
- self.domLoaded = false;
- self.events = events;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * This class enables you to bind/unbind native events to elements and normalize it's behavior across browsers.
+ */
+ function EventUtils() {
+ var self = this, events = {}, count, expando, hasFocusIn, hasMouseEnterLeave, mouseEnterLeave;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Executes all event handler callbacks for a specific event.
- *
- * @private
- * @param {Event} evt Event object.
- * @param {String} id Expando id value to look for.
- */
- function executeHandlers(evt, id) {
- var callbackList, i, l, callback, container = events[id];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ expando = eventExpandoPrefix + (+new Date()).toString(32);
+ hasMouseEnterLeave = "onmouseenter" in document.documentElement;
+ hasFocusIn = "onfocusin" in document.documentElement;
+ mouseEnterLeave = { mouseenter: 'mouseover', mouseleave: 'mouseout' };
+ count = 1;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- callbackList = container && container[evt.type];
- if (callbackList) {
- for (i = 0, l = callbackList.length; i < l; i++) {
- callback = callbackList[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // State if the DOMContentLoaded was executed or not
+ self.domLoaded = false;
+ self.events = events;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if callback exists might be removed if a unbind is called inside the callback
- if (callback && callback.func.call(callback.scope, evt) === false) {
- evt.preventDefault();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Executes all event handler callbacks for a specific event.
+ *
+ * @private
+ * @param {Event} evt Event object.
+ * @param {String} id Expando id value to look for.
+ */
+ function executeHandlers(evt, id) {
+ var callbackList, i, l, callback, container = events[id];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Should we stop propagation to immediate listeners
- if (evt.isImmediatePropagationStopped()) {
- return;
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ callbackList = container && container[evt.type];
+ if (callbackList) {
+ for (i = 0, l = callbackList.length; i < l; i++) {
+ callback = callbackList[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Binds a callback to an event on the specified target.
- *
- * @method bind
- * @param {Object} target Target node/window or custom object.
- * @param {String} names Name of the event to bind.
- * @param {function} callback Callback function to execute when the event occurs.
- * @param {Object} scope Scope to call the callback function on, defaults to target.
- * @return {function} Callback function that got bound.
- */
- self.bind = function(target, names, callback, scope) {
- var id, callbackList, i, name, fakeName, nativeHandler, capture, win = window;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if callback exists might be removed if a unbind is called inside the callback
+ if (callback && callback.func.call(callback.scope, evt) === false) {
+ evt.preventDefault();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Native event handler function patches the event and executes the callbacks for the expando
- function defaultNativeHandler(evt) {
- executeHandlers(fix(evt || win.event), id);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Should we stop propagation to immediate listeners
+ if (evt.isImmediatePropagationStopped()) {
+ return;
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Don't bind to text nodes or comments
- if (!target || target.nodeType === 3 || target.nodeType === 8) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Binds a callback to an event on the specified target.
+ *
+ * @method bind
+ * @param {Object} target Target node/window or custom object.
+ * @param {String} names Name of the event to bind.
+ * @param {function} callback Callback function to execute when the event occurs.
+ * @param {Object} scope Scope to call the callback function on, defaults to target.
+ * @return {function} Callback function that got bound.
+ */
+ self.bind = function (target, names, callback, scope) {
+ var id, callbackList, i, name, fakeName, nativeHandler, capture, win = window;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Create or get events id for the target
- if (!target[expando]) {
- id = count++;
- target[expando] = id;
- events[id] = {};
- } else {
- id = target[expando];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Native event handler function patches the event and executes the callbacks for the expando
+ function defaultNativeHandler(evt) {
+ executeHandlers(fix(evt || win.event), id);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup the specified scope or use the target as a default
- scope = scope || target;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't bind to text nodes or comments
+ if (!target || target.nodeType === 3 || target.nodeType === 8) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Split names and bind each event, enables you to bind multiple events with one call
- names = names.split(' ');
- i = names.length;
- while (i--) {
- name = names[i];
- nativeHandler = defaultNativeHandler;
- fakeName = capture = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Create or get events id for the target
+ if (!target[expando]) {
+ id = count++;
+ target[expando] = id;
+ events[id] = {};
+ } else {
+ id = target[expando];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Use ready instead of DOMContentLoaded
- if (name === "DOMContentLoaded") {
- name = "ready";
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup the specified scope or use the target as a default
+ scope = scope || target;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // DOM is already ready
- if (self.domLoaded && name === "ready" && target.readyState == 'complete') {
- callback.call(scope, fix({type: name}));
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Split names and bind each event, enables you to bind multiple events with one call
+ names = names.split(' ');
+ i = names.length;
+ while (i--) {
+ name = names[i];
+ nativeHandler = defaultNativeHandler;
+ fakeName = capture = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle mouseenter/mouseleaver
- if (!hasMouseEnterLeave) {
- fakeName = mouseEnterLeave[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Use ready instead of DOMContentLoaded
+ if (name === "DOMContentLoaded") {
+ name = "ready";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (fakeName) {
- nativeHandler = function(evt) {
- var current, related;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // DOM is already ready
+ if (self.domLoaded && name === "ready" && target.readyState == 'complete') {
+ callback.call(scope, fix({ type: name }));
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- current = evt.currentTarget;
- related = evt.relatedTarget;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handle mouseenter/mouseleaver
+ if (!hasMouseEnterLeave) {
+ fakeName = mouseEnterLeave[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if related is inside the current target if it's not then the event should
- // be ignored since it's a mouseover/mouseout inside the element
- if (related && current.contains) {
- // Use contains for performance
- related = current.contains(related);
- } else {
- while (related && related !== current) {
- related = related.parentNode;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (fakeName) {
+ nativeHandler = function (evt) {
+ var current, related;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Fire fake event
- if (!related) {
- evt = fix(evt || win.event);
- evt.type = evt.type === 'mouseout' ? 'mouseleave' : 'mouseenter';
- evt.target = current;
- executeHandlers(evt, id);
- }
- };
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ current = evt.currentTarget;
+ related = evt.relatedTarget;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Fake bubbling of focusin/focusout
- if (!hasFocusIn && (name === "focusin" || name === "focusout")) {
- capture = true;
- fakeName = name === "focusin" ? "focus" : "blur";
- nativeHandler = function(evt) {
- evt = fix(evt || win.event);
- evt.type = evt.type === 'focus' ? 'focusin' : 'focusout';
- executeHandlers(evt, id);
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if related is inside the current target if it's not then the event should
+ // be ignored since it's a mouseover/mouseout inside the element
+ if (related && current.contains) {
+ // Use contains for performance
+ related = current.contains(related);
+ } else {
+ while (related && related !== current) {
+ related = related.parentNode;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup callback list and bind native event
- callbackList = events[id][name];
- if (!callbackList) {
- events[id][name] = callbackList = [{func: callback, scope: scope}];
- callbackList.fakeName = fakeName;
- callbackList.capture = capture;
- //callbackList.callback = callback;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Fire fake event
+ if (!related) {
+ evt = fix(evt || win.event);
+ evt.type = evt.type === 'mouseout' ? 'mouseleave' : 'mouseenter';
+ evt.target = current;
+ executeHandlers(evt, id);
+ }
+ };
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add the nativeHandler to the callback list so that we can later unbind it
- callbackList.nativeHandler = nativeHandler;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Fake bubbling of focusin/focusout
+ if (!hasFocusIn && (name === "focusin" || name === "focusout")) {
+ capture = true;
+ fakeName = name === "focusin" ? "focus" : "blur";
+ nativeHandler = function (evt) {
+ evt = fix(evt || win.event);
+ evt.type = evt.type === 'focus' ? 'focusin' : 'focusout';
+ executeHandlers(evt, id);
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if the target has native events support
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup callback list and bind native event
+ callbackList = events[id][name];
+ if (!callbackList) {
+ events[id][name] = callbackList = [{ func: callback, scope: scope }];
+ callbackList.fakeName = fakeName;
+ callbackList.capture = capture;
+ //callbackList.callback = callback;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name === "ready") {
- bindOnReady(target, nativeHandler, self);
- } else {
- addEvent(target, fakeName || name, nativeHandler, capture);
- }
- } else {
- if (name === "ready" && self.domLoaded) {
- callback({type: name});
- } else {
- // If it already has an native handler then just push the callback
- callbackList.push({func: callback, scope: scope});
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add the nativeHandler to the callback list so that we can later unbind it
+ callbackList.nativeHandler = nativeHandler;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- target = callbackList = 0; // Clean memory for IE
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if the target has native events support
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return callback;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name === "ready") {
+ bindOnReady(target, nativeHandler, self);
+ } else {
+ addEvent(target, fakeName || name, nativeHandler, capture);
+ }
+ } else {
+ if (name === "ready" && self.domLoaded) {
+ callback({ type: name });
+ } else {
+ // If it already has an native handler then just push the callback
+ callbackList.push({ func: callback, scope: scope });
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Unbinds the specified event by name, name and callback or all events on the target.
- *
- * @method unbind
- * @param {Object} target Target node/window or custom object.
- * @param {String} names Optional event name to unbind.
- * @param {function} callback Optional callback function to unbind.
- * @return {EventUtils} Event utils instance.
- */
- self.unbind = function(target, names, callback) {
- var id, callbackList, i, ci, name, eventMap;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ target = callbackList = 0; // Clean memory for IE
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Don't bind to text nodes or comments
- if (!target || target.nodeType === 3 || target.nodeType === 8) {
- return self;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return callback;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Unbind event or events if the target has the expando
- id = target[expando];
- if (id) {
- eventMap = events[id];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Unbinds the specified event by name, name and callback or all events on the target.
+ *
+ * @method unbind
+ * @param {Object} target Target node/window or custom object.
+ * @param {String} names Optional event name to unbind.
+ * @param {function} callback Optional callback function to unbind.
+ * @return {EventUtils} Event utils instance.
+ */
+ self.unbind = function (target, names, callback) {
+ var id, callbackList, i, ci, name, eventMap;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Specific callback
- if (names) {
- names = names.split(' ');
- i = names.length;
- while (i--) {
- name = names[i];
- callbackList = eventMap[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't bind to text nodes or comments
+ if (!target || target.nodeType === 3 || target.nodeType === 8) {
+ return self;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Unbind the event if it exists in the map
- if (callbackList) {
- // Remove specified callback
- if (callback) {
- ci = callbackList.length;
- while (ci--) {
- if (callbackList[ci].func === callback) {
- var nativeHandler = callbackList.nativeHandler;
- var fakeName = callbackList.fakeName, capture = callbackList.capture;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Unbind event or events if the target has the expando
+ id = target[expando];
+ if (id) {
+ eventMap = events[id];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Clone callbackList since unbind inside a callback would otherwise break the handlers loop
- callbackList = callbackList.slice(0, ci).concat(callbackList.slice(ci + 1));
- callbackList.nativeHandler = nativeHandler;
- callbackList.fakeName = fakeName;
- callbackList.capture = capture;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Specific callback
+ if (names) {
+ names = names.split(' ');
+ i = names.length;
+ while (i--) {
+ name = names[i];
+ callbackList = eventMap[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- eventMap[name] = callbackList;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Unbind the event if it exists in the map
+ if (callbackList) {
+ // Remove specified callback
+ if (callback) {
+ ci = callbackList.length;
+ while (ci--) {
+ if (callbackList[ci].func === callback) {
+ var nativeHandler = callbackList.nativeHandler;
+ var fakeName = callbackList.fakeName, capture = callbackList.capture;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove all callbacks if there isn't a specified callback or there is no callbacks left
- if (!callback || callbackList.length === 0) {
- delete eventMap[name];
- removeEvent(target, callbackList.fakeName || name, callbackList.nativeHandler, callbackList.capture);
- }
- }
- }
- } else {
- // All events for a specific element
- for (name in eventMap) {
- callbackList = eventMap[name];
- removeEvent(target, callbackList.fakeName || name, callbackList.nativeHandler, callbackList.capture);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Clone callbackList since unbind inside a callback would otherwise break the handlers loop
+ callbackList = callbackList.slice(0, ci).concat(callbackList.slice(ci + 1));
+ callbackList.nativeHandler = nativeHandler;
+ callbackList.fakeName = fakeName;
+ callbackList.capture = capture;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- eventMap = {};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ eventMap[name] = callbackList;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if object is empty, if it isn't then we won't remove the expando map
- for (name in eventMap) {
- return self;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove all callbacks if there isn't a specified callback or there is no callbacks left
+ if (!callback || callbackList.length === 0) {
+ delete eventMap[name];
+ removeEvent(target, callbackList.fakeName || name, callbackList.nativeHandler, callbackList.capture);
+ }
+ }
+ }
+ } else {
+ // All events for a specific element
+ for (name in eventMap) {
+ callbackList = eventMap[name];
+ removeEvent(target, callbackList.fakeName || name, callbackList.nativeHandler, callbackList.capture);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Delete event object
- delete events[id];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ eventMap = {};
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove expando from target
- try {
- // IE will fail here since it can't delete properties from window
- delete target[expando];
- } catch (ex) {
- // IE will set it to null
- target[expando] = null;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if object is empty, if it isn't then we won't remove the expando map
+ for (name in eventMap) {
+ return self;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Delete event object
+ delete events[id];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Fires the specified event on the specified target.
- *
- * @method fire
- * @param {Object} target Target node/window or custom object.
- * @param {String} name Event name to fire.
- * @param {Object} args Optional arguments to send to the observers.
- * @return {EventUtils} Event utils instance.
- */
- self.fire = function(target, name, args) {
- var id;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove expando from target
+ try {
+ // IE will fail here since it can't delete properties from window
+ delete target[expando];
+ } catch (ex) {
+ // IE will set it to null
+ target[expando] = null;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Don't bind to text nodes or comments
- if (!target || target.nodeType === 3 || target.nodeType === 8) {
- return self;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Build event object by patching the args
- args = fix(null, args);
- args.type = name;
- args.target = target;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Fires the specified event on the specified target.
+ *
+ * @method fire
+ * @param {Object} target Target node/window or custom object.
+ * @param {String} name Event name to fire.
+ * @param {Object} args Optional arguments to send to the observers.
+ * @return {EventUtils} Event utils instance.
+ */
+ self.fire = function (target, name, args) {
+ var id;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- do {
- // Found an expando that means there is listeners to execute
- id = target[expando];
- if (id) {
- executeHandlers(args, id);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't bind to text nodes or comments
+ if (!target || target.nodeType === 3 || target.nodeType === 8) {
+ return self;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Walk up the DOM
- target = target.parentNode || target.ownerDocument || target.defaultView || target.parentWindow;
- } while (target && !args.isPropagationStopped());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Build event object by patching the args
+ args = fix(null, args);
+ args.type = name;
+ args.target = target;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ do {
+ // Found an expando that means there is listeners to execute
+ id = target[expando];
+ if (id) {
+ executeHandlers(args, id);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes all bound event listeners for the specified target. This will also remove any bound
- * listeners to child nodes within that target.
- *
- * @method clean
- * @param {Object} target Target node/window object.
- * @return {EventUtils} Event utils instance.
- */
- self.clean = function(target) {
- var i, children, unbind = self.unbind;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Walk up the DOM
+ target = target.parentNode || target.ownerDocument || target.defaultView || target.parentWindow;
+ } while (target && !args.isPropagationStopped());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Don't bind to text nodes or comments
- if (!target || target.nodeType === 3 || target.nodeType === 8) {
- return self;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Unbind any element on the specified target
- if (target[expando]) {
- unbind(target);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes all bound event listeners for the specified target. This will also remove any bound
+ * listeners to child nodes within that target.
+ *
+ * @method clean
+ * @param {Object} target Target node/window object.
+ * @return {EventUtils} Event utils instance.
+ */
+ self.clean = function (target) {
+ var i, children, unbind = self.unbind;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Target doesn't have getElementsByTagName it's probably a window object then use it's document to find the children
- if (!target.getElementsByTagName) {
- target = target.document;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't bind to text nodes or comments
+ if (!target || target.nodeType === 3 || target.nodeType === 8) {
+ return self;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove events from each child element
- if (target && target.getElementsByTagName) {
- unbind(target);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Unbind any element on the specified target
+ if (target[expando]) {
+ unbind(target);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- children = target.getElementsByTagName('*');
- i = children.length;
- while (i--) {
- target = children[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Target doesn't have getElementsByTagName it's probably a window object then use it's document to find the children
+ if (!target.getElementsByTagName) {
+ target = target.document;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (target[expando]) {
- unbind(target);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove events from each child element
+ if (target && target.getElementsByTagName) {
+ unbind(target);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ children = target.getElementsByTagName('*');
+ i = children.length;
+ while (i--) {
+ target = children[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Destroys the event object. Call this on IE to remove memory leaks.
- */
- self.destroy = function() {
- events = {};
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (target[expando]) {
+ unbind(target);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Legacy function for canceling events
- self.cancel = function(e) {
- if (e) {
- e.preventDefault();
- e.stopImmediatePropagation();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Destroys the event object. Call this on IE to remove memory leaks.
+ */
+ self.destroy = function () {
+ events = {};
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- EventUtils.Event = new EventUtils();
- EventUtils.Event.bind(window, 'ready', function() {});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Legacy function for canceling events
+ self.cancel = function (e) {
+ if (e) {
+ e.preventDefault();
+ e.stopImmediatePropagation();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return EventUtils;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/dom/Sizzle.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ EventUtils.Event = new EventUtils();
+ EventUtils.Event.bind(window, 'ready', function () { });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return EventUtils;
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Sizzle.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1538,2039 +1539,2043 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Date: @DATE
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/dom/Sizzle", [], function() {
-var i,
- support,
- Expr,
- getText,
- isXML,
- tokenize,
- compile,
- select,
- outermostContext,
- sortInput,
- hasDuplicate,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.Sizzle',
+ [],
+ function () {
+ var i,
+ support,
+ Expr,
+ getText,
+ isXML,
+ tokenize,
+ compile,
+ select,
+ outermostContext,
+ sortInput,
+ hasDuplicate,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Local document vars
- setDocument,
- document,
- docElem,
- documentIsHTML,
- rbuggyQSA,
- rbuggyMatches,
- matches,
- contains,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Local document vars
+ setDocument,
+ document,
+ docElem,
+ documentIsHTML,
+ rbuggyQSA,
+ rbuggyMatches,
+ matches,
+ contains,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Instance-specific data
- expando = "sizzle" + -(new Date()),
- preferredDoc = window.document,
- dirruns = 0,
- done = 0,
- classCache = createCache(),
- tokenCache = createCache(),
- compilerCache = createCache(),
- sortOrder = function( a, b ) {
- if ( a === b ) {
- hasDuplicate = true;
- }
- return 0;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Instance-specific data
+ expando = "sizzle" + -(new Date()),
+ preferredDoc = window.document,
+ dirruns = 0,
+ done = 0,
+ classCache = createCache(),
+ tokenCache = createCache(),
+ compilerCache = createCache(),
+ sortOrder = function (a, b) {
+ if (a === b) {
+ hasDuplicate = true;
+ }
+ return 0;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // General-purpose constants
- strundefined = typeof undefined,
- MAX_NEGATIVE = 1 << 31,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // General-purpose constants
+ strundefined = typeof undefined,
+ MAX_NEGATIVE = 1 << 31,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Instance methods
- hasOwn = ({}).hasOwnProperty,
- arr = [],
- pop = arr.pop,
- push_native = arr.push,
- push = arr.push,
- slice = arr.slice,
- // Use a stripped-down indexOf if we can't use a native one
- indexOf = arr.indexOf || function( elem ) {
- var i = 0,
- len = this.length;
- for ( ; i < len; i++ ) {
- if ( this[i] === elem ) {
- return i;
- }
- }
- return -1;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Instance methods
+ hasOwn = ({}).hasOwnProperty,
+ arr = [],
+ pop = arr.pop,
+ push_native = arr.push,
+ push = arr.push,
+ slice = arr.slice,
+ // Use a stripped-down indexOf if we can't use a native one
+ indexOf = arr.indexOf || function (elem) {
+ var i = 0,
+ len = this.length;
+ for (; i < len; i++) {
+ if (this[i] === elem) {
+ return i;
+ }
+ }
+ return -1;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Regular expressions
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Regular expressions
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // http://www.w3.org/TR/css3-selectors/#whitespace
- whitespace = "[\\x20\\t\\r\\n\\f]",
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // http://www.w3.org/TR/css3-selectors/#whitespace
+ whitespace = "[\\x20\\t\\r\\n\\f]",
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
- identifier = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+ identifier = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
- attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
- // Operator (capture 2)
- "*([*^$|!~]?=)" + whitespace +
- // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
- "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
- "*\\]",
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
+ attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
+ // Operator (capture 2)
+ "*([*^$|!~]?=)" + whitespace +
+ // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
+ "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
+ "*\\]",
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- pseudos = ":(" + identifier + ")(?:\\((" +
- // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
- // 1. quoted (capture 3; capture 4 or capture 5)
- "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
- // 2. simple (capture 6)
- "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
- // 3. anything else (capture 2)
- ".*" +
- ")\\)|)",
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ pseudos = ":(" + identifier + ")(?:\\((" +
+ // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
+ // 1. quoted (capture 3; capture 4 or capture 5)
+ "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
+ // 2. simple (capture 6)
+ "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
+ // 3. anything else (capture 2)
+ ".*" +
+ ")\\)|)",
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
- rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+ rtrim = new RegExp("^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g"),
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
- rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rcomma = new RegExp("^" + whitespace + "*," + whitespace + "*"),
+ rcombinators = new RegExp("^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*"),
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rattributeQuotes = new RegExp("=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g"),
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rpseudo = new RegExp( pseudos ),
- ridentifier = new RegExp( "^" + identifier + "$" ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rpseudo = new RegExp(pseudos),
+ ridentifier = new RegExp("^" + identifier + "$"),
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- matchExpr = {
- "ID": new RegExp( "^#(" + identifier + ")" ),
- "CLASS": new RegExp( "^\\.(" + identifier + ")" ),
- "TAG": new RegExp( "^(" + identifier + "|[*])" ),
- "ATTR": new RegExp( "^" + attributes ),
- "PSEUDO": new RegExp( "^" + pseudos ),
- "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
- "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
- "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
- "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
- // For use in libraries implementing .is()
- // We use this for POS matching in `select`
- "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
- whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ matchExpr = {
+ "ID": new RegExp("^#(" + identifier + ")"),
+ "CLASS": new RegExp("^\\.(" + identifier + ")"),
+ "TAG": new RegExp("^(" + identifier + "|[*])"),
+ "ATTR": new RegExp("^" + attributes),
+ "PSEUDO": new RegExp("^" + pseudos),
+ "CHILD": new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
+ "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+ "*(\\d+)|))" + whitespace + "*\\)|)", "i"),
+ "bool": new RegExp("^(?:" + booleans + ")$", "i"),
+ // For use in libraries implementing .is()
+ // We use this for POS matching in `select`
+ "needsContext": new RegExp("^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
+ whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i")
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rinputs = /^(?:input|select|textarea|button)$/i,
- rheader = /^h\d$/i,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rinputs = /^(?:input|select|textarea|button)$/i,
+ rheader = /^h\d$/i,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rnative = /^[^{]+\{\s*\[native \w/,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rnative = /^[^{]+\{\s*\[native \w/,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Easily-parseable/retrievable ID or TAG or CLASS selectors
- rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Easily-parseable/retrievable ID or TAG or CLASS selectors
+ rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rsibling = /[+~]/,
- rescape = /'|\\/g,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rsibling = /[+~]/,
+ rescape = /'|\\/g,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
- runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
- funescape = function( _, escaped, escapedWhitespace ) {
- var high = "0x" + escaped - 0x10000;
- // NaN means non-codepoint
- // Support: Firefox<24
- // Workaround erroneous numeric interpretation of +"0x"
- return high !== high || escapedWhitespace ?
- escaped :
- high < 0 ?
- // BMP codepoint
- String.fromCharCode( high + 0x10000 ) :
- // Supplemental Plane codepoint (surrogate pair)
- String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
+ runescape = new RegExp("\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig"),
+ funescape = function (_, escaped, escapedWhitespace) {
+ var high = "0x" + escaped - 0x10000;
+ // NaN means non-codepoint
+ // Support: Firefox<24
+ // Workaround erroneous numeric interpretation of +"0x"
+ return high !== high || escapedWhitespace ?
+ escaped :
+ high < 0 ?
+ // BMP codepoint
+ String.fromCharCode(high + 0x10000) :
+ // Supplemental Plane codepoint (surrogate pair)
+ String.fromCharCode(high >> 10 | 0xD800, high & 0x3FF | 0xDC00);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Optimize for push.apply( _, NodeList )
-try {
- push.apply(
- (arr = slice.call( preferredDoc.childNodes )),
- preferredDoc.childNodes
- );
- // Support: Android<4.0
- // Detect silently failing push.apply
- arr[ preferredDoc.childNodes.length ].nodeType;
-} catch ( e ) {
- push = { apply: arr.length ?
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Optimize for push.apply( _, NodeList )
+ try {
+ push.apply(
+ (arr = slice.call(preferredDoc.childNodes)),
+ preferredDoc.childNodes
+ );
+ // Support: Android<4.0
+ // Detect silently failing push.apply
+ arr[preferredDoc.childNodes.length].nodeType;
+ } catch (e) {
+ push = {
+ apply: arr.length ?
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Leverage slice if possible
- function( target, els ) {
- push_native.apply( target, slice.call(els) );
- } :
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Leverage slice if possible
+ function (target, els) {
+ push_native.apply(target, slice.call(els));
+ } :
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Support: IE<9
- // Otherwise append directly
- function( target, els ) {
- var j = target.length,
- i = 0;
- // Can't trust NodeList.length
- while ( (target[j++] = els[i++]) ) {}
- target.length = j - 1;
- }
- };
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Support: IE<9
+ // Otherwise append directly
+ function (target, els) {
+ var j = target.length,
+ i = 0;
+ // Can't trust NodeList.length
+ while ((target[j++] = els[i++])) { }
+ target.length = j - 1;
+ }
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function Sizzle( selector, context, results, seed ) {
- var match, elem, m, nodeType,
- // QSA vars
- i, groups, old, nid, newContext, newSelector;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function Sizzle(selector, context, results, seed) {
+ var match, elem, m, nodeType,
+ // QSA vars
+ i, groups, old, nid, newContext, newSelector;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
- setDocument( context );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((context ? context.ownerDocument || context : preferredDoc) !== document) {
+ setDocument(context);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- context = context || document;
- results = results || [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ context = context || document;
+ results = results || [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( !selector || typeof selector !== "string" ) {
- return results;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!selector || typeof selector !== "string") {
+ return results;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
- return [];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((nodeType = context.nodeType) !== 1 && nodeType !== 9) {
+ return [];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( documentIsHTML && !seed ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (documentIsHTML && !seed) {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Shortcuts
- if ( (match = rquickExpr.exec( selector )) ) {
- // Speed-up: Sizzle("#ID")
- if ( (m = match[1]) ) {
- if ( nodeType === 9 ) {
- elem = context.getElementById( m );
- // Check parentNode to catch when Blackberry 4.6 returns
- // nodes that are no longer in the document (jQuery #6963)
- if ( elem && elem.parentNode ) {
- // Handle the case where IE, Opera, and Webkit return items
- // by name instead of ID
- if ( elem.id === m ) {
- results.push( elem );
- return results;
- }
- } else {
- return results;
- }
- } else {
- // Context is not a document
- if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
- contains( context, elem ) && elem.id === m ) {
- results.push( elem );
- return results;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Shortcuts
+ if ((match = rquickExpr.exec(selector))) {
+ // Speed-up: Sizzle("#ID")
+ if ((m = match[1])) {
+ if (nodeType === 9) {
+ elem = context.getElementById(m);
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document (jQuery #6963)
+ if (elem && elem.parentNode) {
+ // Handle the case where IE, Opera, and Webkit return items
+ // by name instead of ID
+ if (elem.id === m) {
+ results.push(elem);
+ return results;
+ }
+ } else {
+ return results;
+ }
+ } else {
+ // Context is not a document
+ if (context.ownerDocument && (elem = context.ownerDocument.getElementById(m)) &&
+ contains(context, elem) && elem.id === m) {
+ results.push(elem);
+ return results;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Speed-up: Sizzle("TAG")
- } else if ( match[2] ) {
- push.apply( results, context.getElementsByTagName( selector ) );
- return results;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Speed-up: Sizzle("TAG")
+ } else if (match[2]) {
+ push.apply(results, context.getElementsByTagName(selector));
+ return results;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Speed-up: Sizzle(".CLASS")
- } else if ( (m = match[3]) && support.getElementsByClassName ) {
- push.apply( results, context.getElementsByClassName( m ) );
- return results;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Speed-up: Sizzle(".CLASS")
+ } else if ((m = match[3]) && support.getElementsByClassName) {
+ push.apply(results, context.getElementsByClassName(m));
+ return results;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // QSA path
- if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
- nid = old = expando;
- newContext = context;
- newSelector = nodeType === 9 && selector;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // QSA path
+ if (support.qsa && (!rbuggyQSA || !rbuggyQSA.test(selector))) {
+ nid = old = expando;
+ newContext = context;
+ newSelector = nodeType === 9 && selector;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // qSA works strangely on Element-rooted queries
- // We can work around this by specifying an extra ID on the root
- // and working up from there (Thanks to Andrew Dupont for the technique)
- // IE 8 doesn't work on object elements
- if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
- groups = tokenize( selector );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // qSA works strangely on Element-rooted queries
+ // We can work around this by specifying an extra ID on the root
+ // and working up from there (Thanks to Andrew Dupont for the technique)
+ // IE 8 doesn't work on object elements
+ if (nodeType === 1 && context.nodeName.toLowerCase() !== "object") {
+ groups = tokenize(selector);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( (old = context.getAttribute("id")) ) {
- nid = old.replace( rescape, "\\$&" );
- } else {
- context.setAttribute( "id", nid );
- }
- nid = "[id='" + nid + "'] ";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((old = context.getAttribute("id"))) {
+ nid = old.replace(rescape, "\\$&");
+ } else {
+ context.setAttribute("id", nid);
+ }
+ nid = "[id='" + nid + "'] ";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- i = groups.length;
- while ( i-- ) {
- groups[i] = nid + toSelector( groups[i] );
- }
- newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
- newSelector = groups.join(",");
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ i = groups.length;
+ while (i--) {
+ groups[i] = nid + toSelector(groups[i]);
+ }
+ newContext = rsibling.test(selector) && testContext(context.parentNode) || context;
+ newSelector = groups.join(",");
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( newSelector ) {
- try {
- push.apply( results,
- newContext.querySelectorAll( newSelector )
- );
- return results;
- } catch(qsaError) {
- } finally {
- if ( !old ) {
- context.removeAttribute("id");
- }
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (newSelector) {
+ try {
+ push.apply(results,
+ newContext.querySelectorAll(newSelector)
+ );
+ return results;
+ } catch (qsaError) {
+ } finally {
+ if (!old) {
+ context.removeAttribute("id");
+ }
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // All others
- return select( selector.replace( rtrim, "$1" ), context, results, seed );
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // All others
+ return select(selector.replace(rtrim, "$1"), context, results, seed);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Create key-value caches of limited size
- * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
- * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
- * deleting the oldest entry
- */
-function createCache() {
- var keys = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Create key-value caches of limited size
+ * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
+ * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
+ * deleting the oldest entry
+ */
+ function createCache() {
+ var keys = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function cache( key, value ) {
- // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
- if ( keys.push( key + " " ) > Expr.cacheLength ) {
- // Only keep the most recent entries
- delete cache[ keys.shift() ];
- }
- return (cache[ key + " " ] = value);
- }
- return cache;
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function cache(key, value) {
+ // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
+ if (keys.push(key + " ") > Expr.cacheLength) {
+ // Only keep the most recent entries
+ delete cache[keys.shift()];
+ }
+ return (cache[key + " "] = value);
+ }
+ return cache;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Mark a function for special use by Sizzle
- * @param {Function} fn The function to mark
- */
-function markFunction( fn ) {
- fn[ expando ] = true;
- return fn;
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Mark a function for special use by Sizzle
+ * @param {Function} fn The function to mark
+ */
+ function markFunction(fn) {
+ fn[expando] = true;
+ return fn;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Support testing using an element
- * @param {Function} fn Passed the created div and expects a boolean result
- */
-function assert( fn ) {
- var div = document.createElement("div");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Support testing using an element
+ * @param {Function} fn Passed the created div and expects a boolean result
+ */
+ function assert(fn) {
+ var div = document.createElement("div");
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- try {
- return !!fn( div );
- } catch (e) {
- return false;
- } finally {
- // Remove from its parent by default
- if ( div.parentNode ) {
- div.parentNode.removeChild( div );
- }
- // release memory in IE
- div = null;
- }
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ try {
+ return !!fn(div);
+ } catch (e) {
+ return false;
+ } finally {
+ // Remove from its parent by default
+ if (div.parentNode) {
+ div.parentNode.removeChild(div);
+ }
+ // release memory in IE
+ div = null;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Adds the same handler for all of the specified attrs
- * @param {String} attrs Pipe-separated list of attributes
- * @param {Function} handler The method that will be applied
- */
-function addHandle( attrs, handler ) {
- var arr = attrs.split("|"),
- i = attrs.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds the same handler for all of the specified attrs
+ * @param {String} attrs Pipe-separated list of attributes
+ * @param {Function} handler The method that will be applied
+ */
+ function addHandle(attrs, handler) {
+ var arr = attrs.split("|"),
+ i = attrs.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while ( i-- ) {
- Expr.attrHandle[ arr[i] ] = handler;
- }
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ Expr.attrHandle[arr[i]] = handler;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Checks document order of two siblings
- * @param {Element} a
- * @param {Element} b
- * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
- */
-function siblingCheck( a, b ) {
- var cur = b && a,
- diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
- ( ~b.sourceIndex || MAX_NEGATIVE ) -
- ( ~a.sourceIndex || MAX_NEGATIVE );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Checks document order of two siblings
+ * @param {Element} a
+ * @param {Element} b
+ * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
+ */
+ function siblingCheck(a, b) {
+ var cur = b && a,
+ diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
+ (~b.sourceIndex || MAX_NEGATIVE) -
+ (~a.sourceIndex || MAX_NEGATIVE);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Use IE sourceIndex if available on both nodes
- if ( diff ) {
- return diff;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Use IE sourceIndex if available on both nodes
+ if (diff) {
+ return diff;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if b follows a
- if ( cur ) {
- while ( (cur = cur.nextSibling) ) {
- if ( cur === b ) {
- return -1;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if b follows a
+ if (cur) {
+ while ((cur = cur.nextSibling)) {
+ if (cur === b) {
+ return -1;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return a ? 1 : -1;
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return a ? 1 : -1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Returns a function to use in pseudos for input types
- * @param {String} type
- */
-function createInputPseudo( type ) {
- return function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return name === "input" && elem.type === type;
- };
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a function to use in pseudos for input types
+ * @param {String} type
+ */
+ function createInputPseudo(type) {
+ return function (elem) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === type;
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Returns a function to use in pseudos for buttons
- * @param {String} type
- */
-function createButtonPseudo( type ) {
- return function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return (name === "input" || name === "button") && elem.type === type;
- };
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a function to use in pseudos for buttons
+ * @param {String} type
+ */
+ function createButtonPseudo(type) {
+ return function (elem) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && elem.type === type;
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Returns a function to use in pseudos for positionals
- * @param {Function} fn
- */
-function createPositionalPseudo( fn ) {
- return markFunction(function( argument ) {
- argument = +argument;
- return markFunction(function( seed, matches ) {
- var j,
- matchIndexes = fn( [], seed.length, argument ),
- i = matchIndexes.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a function to use in pseudos for positionals
+ * @param {Function} fn
+ */
+ function createPositionalPseudo(fn) {
+ return markFunction(function (argument) {
+ argument = +argument;
+ return markFunction(function (seed, matches) {
+ var j,
+ matchIndexes = fn([], seed.length, argument),
+ i = matchIndexes.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Match elements found at the specified indexes
- while ( i-- ) {
- if ( seed[ (j = matchIndexes[i]) ] ) {
- seed[j] = !(matches[j] = seed[j]);
- }
- }
- });
- });
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Match elements found at the specified indexes
+ while (i--) {
+ if (seed[(j = matchIndexes[i])]) {
+ seed[j] = !(matches[j] = seed[j]);
+ }
+ }
+ });
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Checks a node for validity as a Sizzle context
- * @param {Element|Object=} context
- * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
- */
-function testContext( context ) {
- return context && typeof context.getElementsByTagName !== strundefined && context;
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Checks a node for validity as a Sizzle context
+ * @param {Element|Object=} context
+ * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
+ */
+ function testContext(context) {
+ return context && typeof context.getElementsByTagName !== strundefined && context;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Expose support vars for convenience
-support = Sizzle.support = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Expose support vars for convenience
+ support = Sizzle.support = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Detects XML nodes
- * @param {Element|Object} elem An element or a document
- * @returns {Boolean} True iff elem is a non-HTML XML node
- */
-isXML = Sizzle.isXML = function( elem ) {
- // documentElement is verified for cases where it doesn't yet exist
- // (such as loading iframes in IE - #4833)
- var documentElement = elem && (elem.ownerDocument || elem).documentElement;
- return documentElement ? documentElement.nodeName !== "HTML" : false;
-};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Detects XML nodes
+ * @param {Element|Object} elem An element or a document
+ * @returns {Boolean} True iff elem is a non-HTML XML node
+ */
+ isXML = Sizzle.isXML = function (elem) {
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Sets document-related variables once based on the current document
- * @param {Element|Object} [doc] An element or document object to use to set the document
- * @returns {Object} Returns the current document
- */
-setDocument = Sizzle.setDocument = function( node ) {
- var hasCompare,
- doc = node ? node.ownerDocument || node : preferredDoc,
- parent = doc.defaultView;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets document-related variables once based on the current document
+ * @param {Element|Object} [doc] An element or document object to use to set the document
+ * @returns {Object} Returns the current document
+ */
+ setDocument = Sizzle.setDocument = function (node) {
+ var hasCompare,
+ doc = node ? node.ownerDocument || node : preferredDoc,
+ parent = doc.defaultView;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getTop(win) {
- // Edge throws a lovely Object expected if you try to get top on a detached reference see #2642
- try {
- return win.top;
- } catch (ex) {
- // Ignore
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getTop(win) {
+ // Edge throws a lovely Object expected if you try to get top on a detached reference see #2642
+ try {
+ return win.top;
+ } catch (ex) {
+ // Ignore
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If no document and documentElement is available, return
- if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
- return document;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If no document and documentElement is available, return
+ if (doc === document || doc.nodeType !== 9 || !doc.documentElement) {
+ return document;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set our document
- document = doc;
- docElem = doc.documentElement;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set our document
+ document = doc;
+ docElem = doc.documentElement;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Support tests
- documentIsHTML = !isXML( doc );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Support tests
+ documentIsHTML = !isXML(doc);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Support: IE>8
- // If iframe document is assigned to "document" variable and if iframe has been reloaded,
- // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
- // IE6-8 do not support the defaultView property so parent will be undefined
- if ( parent && parent !== getTop(parent) ) {
- // IE11 does not have attachEvent, so all must suffer
- if ( parent.addEventListener ) {
- parent.addEventListener( "unload", function() {
- setDocument();
- }, false );
- } else if ( parent.attachEvent ) {
- parent.attachEvent( "onunload", function() {
- setDocument();
- });
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Support: IE>8
+ // If iframe document is assigned to "document" variable and if iframe has been reloaded,
+ // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
+ // IE6-8 do not support the defaultView property so parent will be undefined
+ if (parent && parent !== getTop(parent)) {
+ // IE11 does not have attachEvent, so all must suffer
+ if (parent.addEventListener) {
+ parent.addEventListener("unload", function () {
+ setDocument();
+ }, false);
+ } else if (parent.attachEvent) {
+ parent.attachEvent("onunload", function () {
+ setDocument();
+ });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /* Attributes
- ---------------------------------------------------------------------- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /* Attributes
+ ---------------------------------------------------------------------- */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Support: IE<8
- // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans)
- support.attributes = assert(function( div ) {
- div.className = "i";
- return !div.getAttribute("className");
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Support: IE<8
+ // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans)
+ support.attributes = assert(function (div) {
+ div.className = "i";
+ return !div.getAttribute("className");
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /* getElement(s)By*
- ---------------------------------------------------------------------- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /* getElement(s)By*
+ ---------------------------------------------------------------------- */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if getElementsByTagName("*") returns only elements
- support.getElementsByTagName = assert(function( div ) {
- div.appendChild( doc.createComment("") );
- return !div.getElementsByTagName("*").length;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if getElementsByTagName("*") returns only elements
+ support.getElementsByTagName = assert(function (div) {
+ div.appendChild(doc.createComment(""));
+ return !div.getElementsByTagName("*").length;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Support: IE<9
- support.getElementsByClassName = rnative.test( doc.getElementsByClassName );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Support: IE<9
+ support.getElementsByClassName = rnative.test(doc.getElementsByClassName);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Support: IE<10
- // Check if getElementById returns elements by name
- // The broken getElementById methods don't pick up programatically-set names,
- // so use a roundabout getElementsByName test
- support.getById = assert(function( div ) {
- docElem.appendChild( div ).id = expando;
- return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Support: IE<10
+ // Check if getElementById returns elements by name
+ // The broken getElementById methods don't pick up programatically-set names,
+ // so use a roundabout getElementsByName test
+ support.getById = assert(function (div) {
+ docElem.appendChild(div).id = expando;
+ return !doc.getElementsByName || !doc.getElementsByName(expando).length;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // ID find and filter
- if ( support.getById ) {
- Expr.find["ID"] = function( id, context ) {
- if ( typeof context.getElementById !== strundefined && documentIsHTML ) {
- var m = context.getElementById( id );
- // Check parentNode to catch when Blackberry 4.6 returns
- // nodes that are no longer in the document #6963
- return m && m.parentNode ? [ m ] : [];
- }
- };
- Expr.filter["ID"] = function( id ) {
- var attrId = id.replace( runescape, funescape );
- return function( elem ) {
- return elem.getAttribute("id") === attrId;
- };
- };
- } else {
- // Support: IE6/7
- // getElementById is not reliable as a find shortcut
- delete Expr.find["ID"];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // ID find and filter
+ if (support.getById) {
+ Expr.find["ID"] = function (id, context) {
+ if (typeof context.getElementById !== strundefined && documentIsHTML) {
+ var m = context.getElementById(id);
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ return m && m.parentNode ? [m] : [];
+ }
+ };
+ Expr.filter["ID"] = function (id) {
+ var attrId = id.replace(runescape, funescape);
+ return function (elem) {
+ return elem.getAttribute("id") === attrId;
+ };
+ };
+ } else {
+ // Support: IE6/7
+ // getElementById is not reliable as a find shortcut
+ delete Expr.find["ID"];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Expr.filter["ID"] = function( id ) {
- var attrId = id.replace( runescape, funescape );
- return function( elem ) {
- var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
- return node && node.value === attrId;
- };
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Expr.filter["ID"] = function (id) {
+ var attrId = id.replace(runescape, funescape);
+ return function (elem) {
+ var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
+ return node && node.value === attrId;
+ };
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Tag
- Expr.find["TAG"] = support.getElementsByTagName ?
- function( tag, context ) {
- if ( typeof context.getElementsByTagName !== strundefined ) {
- return context.getElementsByTagName( tag );
- }
- } :
- function( tag, context ) {
- var elem,
- tmp = [],
- i = 0,
- results = context.getElementsByTagName( tag );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Tag
+ Expr.find["TAG"] = support.getElementsByTagName ?
+ function (tag, context) {
+ if (typeof context.getElementsByTagName !== strundefined) {
+ return context.getElementsByTagName(tag);
+ }
+ } :
+ function (tag, context) {
+ var elem,
+ tmp = [],
+ i = 0,
+ results = context.getElementsByTagName(tag);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Filter out possible comments
- if ( tag === "*" ) {
- while ( (elem = results[i++]) ) {
- if ( elem.nodeType === 1 ) {
- tmp.push( elem );
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Filter out possible comments
+ if (tag === "*") {
+ while ((elem = results[i++])) {
+ if (elem.nodeType === 1) {
+ tmp.push(elem);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return tmp;
- }
- return results;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return tmp;
+ }
+ return results;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Class
- Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
- if ( documentIsHTML ) {
- return context.getElementsByClassName( className );
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Class
+ Expr.find["CLASS"] = support.getElementsByClassName && function (className, context) {
+ if (documentIsHTML) {
+ return context.getElementsByClassName(className);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /* QSA/matchesSelector
- ---------------------------------------------------------------------- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /* QSA/matchesSelector
+ ---------------------------------------------------------------------- */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // QSA and matchesSelector support
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // QSA and matchesSelector support
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
- rbuggyMatches = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+ rbuggyMatches = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // qSa(:focus) reports false when true (Chrome 21)
- // We allow this because of a bug in IE8/9 that throws an error
- // whenever `document.activeElement` is accessed on an iframe
- // So, we allow :focus to pass through QSA all the time to avoid the IE error
- // See http://bugs.jquery.com/ticket/13378
- rbuggyQSA = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // qSa(:focus) reports false when true (Chrome 21)
+ // We allow this because of a bug in IE8/9 that throws an error
+ // whenever `document.activeElement` is accessed on an iframe
+ // So, we allow :focus to pass through QSA all the time to avoid the IE error
+ // See http://bugs.jquery.com/ticket/13378
+ rbuggyQSA = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
- // Build QSA regex
- // Regex strategy adopted from Diego Perini
- assert(function( div ) {
- // Select is set to empty string on purpose
- // This is to test IE's treatment of not explicitly
- // setting a boolean content attribute,
- // since its presence should be enough
- // http://bugs.jquery.com/ticket/12359
- div.innerHTML = "<select msallowcapture=''><option selected=''></option></select>";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((support.qsa = rnative.test(doc.querySelectorAll))) {
+ // Build QSA regex
+ // Regex strategy adopted from Diego Perini
+ assert(function (div) {
+ // Select is set to empty string on purpose
+ // This is to test IE's treatment of not explicitly
+ // setting a boolean content attribute,
+ // since its presence should be enough
+ // http://bugs.jquery.com/ticket/12359
+ div.innerHTML = "<select msallowcapture=''><option selected=''></option></select>";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Support: IE8, Opera 11-12.16
- // Nothing should be selected when empty strings follow ^= or $= or *=
- // The test attribute must be unknown in Opera but "safe" for WinRT
- // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
- if ( div.querySelectorAll("[msallowcapture^='']").length ) {
- rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Support: IE8, Opera 11-12.16
+ // Nothing should be selected when empty strings follow ^= or $= or *=
+ // The test attribute must be unknown in Opera but "safe" for WinRT
+ // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
+ if (div.querySelectorAll("[msallowcapture^='']").length) {
+ rbuggyQSA.push("[*^$]=" + whitespace + "*(?:''|\"\")");
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Support: IE8
- // Boolean attributes and "value" are not treated correctly
- if ( !div.querySelectorAll("[selected]").length ) {
- rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Support: IE8
+ // Boolean attributes and "value" are not treated correctly
+ if (!div.querySelectorAll("[selected]").length) {
+ rbuggyQSA.push("\\[" + whitespace + "*(?:value|" + booleans + ")");
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Webkit/Opera - :checked should return selected option elements
- // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
- // IE8 throws error here and will not see later tests
- if ( !div.querySelectorAll(":checked").length ) {
- rbuggyQSA.push(":checked");
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Webkit/Opera - :checked should return selected option elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ // IE8 throws error here and will not see later tests
+ if (!div.querySelectorAll(":checked").length) {
+ rbuggyQSA.push(":checked");
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- assert(function( div ) {
- // Support: Windows 8 Native Apps
- // The type and name attributes are restricted during .innerHTML assignment
- var input = doc.createElement("input");
- input.setAttribute( "type", "hidden" );
- div.appendChild( input ).setAttribute( "name", "D" );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ assert(function (div) {
+ // Support: Windows 8 Native Apps
+ // The type and name attributes are restricted during .innerHTML assignment
+ var input = doc.createElement("input");
+ input.setAttribute("type", "hidden");
+ div.appendChild(input).setAttribute("name", "D");
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Support: IE8
- // Enforce case-sensitivity of name attribute
- if ( div.querySelectorAll("[name=d]").length ) {
- rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Support: IE8
+ // Enforce case-sensitivity of name attribute
+ if (div.querySelectorAll("[name=d]").length) {
+ rbuggyQSA.push("name" + whitespace + "*[*^$|!~]?=");
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
- // IE8 throws error here and will not see later tests
- if ( !div.querySelectorAll(":enabled").length ) {
- rbuggyQSA.push( ":enabled", ":disabled" );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+ // IE8 throws error here and will not see later tests
+ if (!div.querySelectorAll(":enabled").length) {
+ rbuggyQSA.push(":enabled", ":disabled");
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Opera 10-11 does not throw on post-comma invalid pseudos
- div.querySelectorAll("*,:x");
- rbuggyQSA.push(",.*:");
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Opera 10-11 does not throw on post-comma invalid pseudos
+ div.querySelectorAll("*,:x");
+ rbuggyQSA.push(",.*:");
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
- docElem.webkitMatchesSelector ||
- docElem.mozMatchesSelector ||
- docElem.oMatchesSelector ||
- docElem.msMatchesSelector) )) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((support.matchesSelector = rnative.test((matches = docElem.matches ||
+ docElem.webkitMatchesSelector ||
+ docElem.mozMatchesSelector ||
+ docElem.oMatchesSelector ||
+ docElem.msMatchesSelector)))) {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- assert(function( div ) {
- // Check to see if it's possible to do matchesSelector
- // on a disconnected node (IE 9)
- support.disconnectedMatch = matches.call( div, "div" );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ assert(function (div) {
+ // Check to see if it's possible to do matchesSelector
+ // on a disconnected node (IE 9)
+ support.disconnectedMatch = matches.call(div, "div");
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // This should fail with an exception
- // Gecko does not error, returns false instead
- matches.call( div, "[s!='']:x" );
- rbuggyMatches.push( "!=", pseudos );
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // This should fail with an exception
+ // Gecko does not error, returns false instead
+ matches.call(div, "[s!='']:x");
+ rbuggyMatches.push("!=", pseudos);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
- rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rbuggyQSA = rbuggyQSA.length && new RegExp(rbuggyQSA.join("|"));
+ rbuggyMatches = rbuggyMatches.length && new RegExp(rbuggyMatches.join("|"));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /* Contains
- ---------------------------------------------------------------------- */
- hasCompare = rnative.test( docElem.compareDocumentPosition );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /* Contains
+ ---------------------------------------------------------------------- */
+ hasCompare = rnative.test(docElem.compareDocumentPosition);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Element contains another
- // Purposefully does not implement inclusive descendent
- // As in, an element does not contain itself
- contains = hasCompare || rnative.test( docElem.contains ) ?
- function( a, b ) {
- var adown = a.nodeType === 9 ? a.documentElement : a,
- bup = b && b.parentNode;
- return a === bup || !!( bup && bup.nodeType === 1 && (
- adown.contains ?
- adown.contains( bup ) :
- a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
- ));
- } :
- function( a, b ) {
- if ( b ) {
- while ( (b = b.parentNode) ) {
- if ( b === a ) {
- return true;
- }
- }
- }
- return false;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Element contains another
+ // Purposefully does not implement inclusive descendent
+ // As in, an element does not contain itself
+ contains = hasCompare || rnative.test(docElem.contains) ?
+ function (a, b) {
+ var adown = a.nodeType === 9 ? a.documentElement : a,
+ bup = b && b.parentNode;
+ return a === bup || !!(bup && bup.nodeType === 1 && (
+ adown.contains ?
+ adown.contains(bup) :
+ a.compareDocumentPosition && a.compareDocumentPosition(bup) & 16
+ ));
+ } :
+ function (a, b) {
+ if (b) {
+ while ((b = b.parentNode)) {
+ if (b === a) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /* Sorting
- ---------------------------------------------------------------------- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /* Sorting
+ ---------------------------------------------------------------------- */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Document order sorting
- sortOrder = hasCompare ?
- function( a, b ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Document order sorting
+ sortOrder = hasCompare ?
+ function (a, b) {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Flag for duplicate removal
- if ( a === b ) {
- hasDuplicate = true;
- return 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Flag for duplicate removal
+ if (a === b) {
+ hasDuplicate = true;
+ return 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Sort on method existence if only one input has compareDocumentPosition
- var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
- if ( compare ) {
- return compare;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Sort on method existence if only one input has compareDocumentPosition
+ var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
+ if (compare) {
+ return compare;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Calculate position if both inputs belong to the same document
- compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
- a.compareDocumentPosition( b ) :
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Calculate position if both inputs belong to the same document
+ compare = (a.ownerDocument || a) === (b.ownerDocument || b) ?
+ a.compareDocumentPosition(b) :
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Otherwise we know they are disconnected
- 1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Otherwise we know they are disconnected
+ 1;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Disconnected nodes
- if ( compare & 1 ||
- (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Disconnected nodes
+ if (compare & 1 ||
+ (!support.sortDetached && b.compareDocumentPosition(a) === compare)) {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Choose the first element that is related to our preferred document
- if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
- return -1;
- }
- if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
- return 1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Choose the first element that is related to our preferred document
+ if (a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a)) {
+ return -1;
+ }
+ if (b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b)) {
+ return 1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Maintain original order
- return sortInput ?
- ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
- 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Maintain original order
+ return sortInput ?
+ (indexOf.call(sortInput, a) - indexOf.call(sortInput, b)) :
+ 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return compare & 4 ? -1 : 1;
- } :
- function( a, b ) {
- // Exit early if the nodes are identical
- if ( a === b ) {
- hasDuplicate = true;
- return 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return compare & 4 ? -1 : 1;
+ } :
+ function (a, b) {
+ // Exit early if the nodes are identical
+ if (a === b) {
+ hasDuplicate = true;
+ return 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var cur,
- i = 0,
- aup = a.parentNode,
- bup = b.parentNode,
- ap = [ a ],
- bp = [ b ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var cur,
+ i = 0,
+ aup = a.parentNode,
+ bup = b.parentNode,
+ ap = [a],
+ bp = [b];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Parentless nodes are either documents or disconnected
- if ( !aup || !bup ) {
- return a === doc ? -1 :
- b === doc ? 1 :
- aup ? -1 :
- bup ? 1 :
- sortInput ?
- ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
- 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Parentless nodes are either documents or disconnected
+ if (!aup || !bup) {
+ return a === doc ? -1 :
+ b === doc ? 1 :
+ aup ? -1 :
+ bup ? 1 :
+ sortInput ?
+ (indexOf.call(sortInput, a) - indexOf.call(sortInput, b)) :
+ 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If the nodes are siblings, we can do a quick check
- } else if ( aup === bup ) {
- return siblingCheck( a, b );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If the nodes are siblings, we can do a quick check
+ } else if (aup === bup) {
+ return siblingCheck(a, b);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Otherwise we need full lists of their ancestors for comparison
- cur = a;
- while ( (cur = cur.parentNode) ) {
- ap.unshift( cur );
- }
- cur = b;
- while ( (cur = cur.parentNode) ) {
- bp.unshift( cur );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Otherwise we need full lists of their ancestors for comparison
+ cur = a;
+ while ((cur = cur.parentNode)) {
+ ap.unshift(cur);
+ }
+ cur = b;
+ while ((cur = cur.parentNode)) {
+ bp.unshift(cur);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Walk down the tree looking for a discrepancy
- while ( ap[i] === bp[i] ) {
- i++;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Walk down the tree looking for a discrepancy
+ while (ap[i] === bp[i]) {
+ i++;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return i ?
- // Do a sibling check if the nodes have a common ancestor
- siblingCheck( ap[i], bp[i] ) :
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return i ?
+ // Do a sibling check if the nodes have a common ancestor
+ siblingCheck(ap[i], bp[i]) :
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Otherwise nodes in our document sort first
- ap[i] === preferredDoc ? -1 :
- bp[i] === preferredDoc ? 1 :
- 0;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Otherwise nodes in our document sort first
+ ap[i] === preferredDoc ? -1 :
+ bp[i] === preferredDoc ? 1 :
+ 0;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return doc;
-};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return doc;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-Sizzle.matches = function( expr, elements ) {
- return Sizzle( expr, null, null, elements );
-};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Sizzle.matches = function (expr, elements) {
+ return Sizzle(expr, null, null, elements);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-Sizzle.matchesSelector = function( elem, expr ) {
- // Set document vars if needed
- if ( ( elem.ownerDocument || elem ) !== document ) {
- setDocument( elem );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Sizzle.matchesSelector = function (elem, expr) {
+ // Set document vars if needed
+ if ((elem.ownerDocument || elem) !== document) {
+ setDocument(elem);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Make sure that attribute selectors are quoted
- expr = expr.replace( rattributeQuotes, "='$1']" );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Make sure that attribute selectors are quoted
+ expr = expr.replace(rattributeQuotes, "='$1']");
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( support.matchesSelector && documentIsHTML &&
- ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
- ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (support.matchesSelector && documentIsHTML &&
+ (!rbuggyMatches || !rbuggyMatches.test(expr)) &&
+ (!rbuggyQSA || !rbuggyQSA.test(expr))) {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- try {
- var ret = matches.call( elem, expr );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ try {
+ var ret = matches.call(elem, expr);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // IE 9's matchesSelector returns false on disconnected nodes
- if ( ret || support.disconnectedMatch ||
- // As well, disconnected nodes are said to be in a document
- // fragment in IE 9
- elem.document && elem.document.nodeType !== 11 ) {
- return ret;
- }
- } catch(e) {}
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // IE 9's matchesSelector returns false on disconnected nodes
+ if (ret || support.disconnectedMatch ||
+ // As well, disconnected nodes are said to be in a document
+ // fragment in IE 9
+ elem.document && elem.document.nodeType !== 11) {
+ return ret;
+ }
+ } catch (e) { }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Sizzle( expr, document, null, [ elem ] ).length > 0;
-};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Sizzle(expr, document, null, [elem]).length > 0;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-Sizzle.contains = function( context, elem ) {
- // Set document vars if needed
- if ( ( context.ownerDocument || context ) !== document ) {
- setDocument( context );
- }
- return contains( context, elem );
-};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Sizzle.contains = function (context, elem) {
+ // Set document vars if needed
+ if ((context.ownerDocument || context) !== document) {
+ setDocument(context);
+ }
+ return contains(context, elem);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-Sizzle.attr = function( elem, name ) {
- // Set document vars if needed
- if ( ( elem.ownerDocument || elem ) !== document ) {
- setDocument( elem );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Sizzle.attr = function (elem, name) {
+ // Set document vars if needed
+ if ((elem.ownerDocument || elem) !== document) {
+ setDocument(elem);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var fn = Expr.attrHandle[ name.toLowerCase() ],
- // Don't get fooled by Object.prototype properties (jQuery #13807)
- val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
- fn( elem, name, !documentIsHTML ) :
- undefined;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var fn = Expr.attrHandle[name.toLowerCase()],
+ // Don't get fooled by Object.prototype properties (jQuery #13807)
+ val = fn && hasOwn.call(Expr.attrHandle, name.toLowerCase()) ?
+ fn(elem, name, !documentIsHTML) :
+ undefined;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return val !== undefined ?
- val :
- support.attributes || !documentIsHTML ?
- elem.getAttribute( name ) :
- (val = elem.getAttributeNode(name)) && val.specified ?
- val.value :
- null;
-};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return val !== undefined ?
+ val :
+ support.attributes || !documentIsHTML ?
+ elem.getAttribute(name) :
+ (val = elem.getAttributeNode(name)) && val.specified ?
+ val.value :
+ null;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-Sizzle.error = function( msg ) {
- throw new Error( "Syntax error, unrecognized expression: " + msg );
-};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Sizzle.error = function (msg) {
+ throw new Error("Syntax error, unrecognized expression: " + msg);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Document sorting and removing duplicates
- * @param {ArrayLike} results
- */
-Sizzle.uniqueSort = function( results ) {
- var elem,
- duplicates = [],
- j = 0,
- i = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Document sorting and removing duplicates
+ * @param {ArrayLike} results
+ */
+ Sizzle.uniqueSort = function (results) {
+ var elem,
+ duplicates = [],
+ j = 0,
+ i = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Unless we *know* we can detect duplicates, assume their presence
- hasDuplicate = !support.detectDuplicates;
- sortInput = !support.sortStable && results.slice( 0 );
- results.sort( sortOrder );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Unless we *know* we can detect duplicates, assume their presence
+ hasDuplicate = !support.detectDuplicates;
+ sortInput = !support.sortStable && results.slice(0);
+ results.sort(sortOrder);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( hasDuplicate ) {
- while ( (elem = results[i++]) ) {
- if ( elem === results[ i ] ) {
- j = duplicates.push( i );
- }
- }
- while ( j-- ) {
- results.splice( duplicates[ j ], 1 );
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (hasDuplicate) {
+ while ((elem = results[i++])) {
+ if (elem === results[i]) {
+ j = duplicates.push(i);
+ }
+ }
+ while (j--) {
+ results.splice(duplicates[j], 1);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Clear input after sorting to release objects
- // See https://github.com/jquery/sizzle/pull/225
- sortInput = null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Clear input after sorting to release objects
+ // See https://github.com/jquery/sizzle/pull/225
+ sortInput = null;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return results;
-};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return results;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Utility function for retrieving the text value of an array of DOM nodes
- * @param {Array|Element} elem
- */
-getText = Sizzle.getText = function( elem ) {
- var node,
- ret = "",
- i = 0,
- nodeType = elem.nodeType;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+ getText = Sizzle.getText = function (elem) {
+ var node,
+ ret = "",
+ i = 0,
+ nodeType = elem.nodeType;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( !nodeType ) {
- // If no nodeType, this is expected to be an array
- while ( (node = elem[i++]) ) {
- // Do not traverse comment nodes
- ret += getText( node );
- }
- } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
- // Use textContent for elements
- // innerText usage removed for consistency of new lines (jQuery #11153)
- if ( typeof elem.textContent === "string" ) {
- return elem.textContent;
- } else {
- // Traverse its children
- for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
- ret += getText( elem );
- }
- }
- } else if ( nodeType === 3 || nodeType === 4 ) {
- return elem.nodeValue;
- }
- // Do not include comment or processing instruction nodes
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!nodeType) {
+ // If no nodeType, this is expected to be an array
+ while ((node = elem[i++])) {
+ // Do not traverse comment nodes
+ ret += getText(node);
+ }
+ } else if (nodeType === 1 || nodeType === 9 || nodeType === 11) {
+ // Use textContent for elements
+ // innerText usage removed for consistency of new lines (jQuery #11153)
+ if (typeof elem.textContent === "string") {
+ return elem.textContent;
+ } else {
+ // Traverse its children
+ for (elem = elem.firstChild; elem; elem = elem.nextSibling) {
+ ret += getText(elem);
+ }
+ }
+ } else if (nodeType === 3 || nodeType === 4) {
+ return elem.nodeValue;
+ }
+ // Do not include comment or processing instruction nodes
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return ret;
-};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return ret;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-Expr = Sizzle.selectors = {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Expr = Sizzle.selectors = {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Can be adjusted by the user
- cacheLength: 50,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Can be adjusted by the user
+ cacheLength: 50,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- createPseudo: markFunction,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ createPseudo: markFunction,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- match: matchExpr,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ match: matchExpr,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- attrHandle: {},
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ attrHandle: {},
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- find: {},
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ find: {},
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- relative: {
- ">": { dir: "parentNode", first: true },
- " ": { dir: "parentNode" },
- "+": { dir: "previousSibling", first: true },
- "~": { dir: "previousSibling" }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ relative: {
+ ">": { dir: "parentNode", first: true },
+ " ": { dir: "parentNode" },
+ "+": { dir: "previousSibling", first: true },
+ "~": { dir: "previousSibling" }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- preFilter: {
- "ATTR": function( match ) {
- match[1] = match[1].replace( runescape, funescape );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ preFilter: {
+ "ATTR": function (match) {
+ match[1] = match[1].replace(runescape, funescape);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move the given value to match[3] whether quoted or unquoted
- match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move the given value to match[3] whether quoted or unquoted
+ match[3] = (match[3] || match[4] || match[5] || "").replace(runescape, funescape);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( match[2] === "~=" ) {
- match[3] = " " + match[3] + " ";
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (match[2] === "~=") {
+ match[3] = " " + match[3] + " ";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return match.slice( 0, 4 );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return match.slice(0, 4);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "CHILD": function( match ) {
- /* matches from matchExpr["CHILD"]
- 1 type (only|nth|...)
- 2 what (child|of-type)
- 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
- 4 xn-component of xn+y argument ([+-]?\d*n|)
- 5 sign of xn-component
- 6 x of xn-component
- 7 sign of y-component
- 8 y of y-component
- */
- match[1] = match[1].toLowerCase();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "CHILD": function (match) {
+ /* matches from matchExpr["CHILD"]
+ 1 type (only|nth|...)
+ 2 what (child|of-type)
+ 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+ 4 xn-component of xn+y argument ([+-]?\d*n|)
+ 5 sign of xn-component
+ 6 x of xn-component
+ 7 sign of y-component
+ 8 y of y-component
+ */
+ match[1] = match[1].toLowerCase();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( match[1].slice( 0, 3 ) === "nth" ) {
- // nth-* requires argument
- if ( !match[3] ) {
- Sizzle.error( match[0] );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (match[1].slice(0, 3) === "nth") {
+ // nth-* requires argument
+ if (!match[3]) {
+ Sizzle.error(match[0]);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // numeric x and y parameters for Expr.filter.CHILD
- // remember that false/true cast respectively to 0/1
- match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
- match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // numeric x and y parameters for Expr.filter.CHILD
+ // remember that false/true cast respectively to 0/1
+ match[4] = +(match[4] ? match[5] + (match[6] || 1) : 2 * (match[3] === "even" || match[3] === "odd"));
+ match[5] = +((match[7] + match[8]) || match[3] === "odd");
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // other types prohibit arguments
- } else if ( match[3] ) {
- Sizzle.error( match[0] );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // other types prohibit arguments
+ } else if (match[3]) {
+ Sizzle.error(match[0]);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return match;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return match;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "PSEUDO": function( match ) {
- var excess,
- unquoted = !match[6] && match[2];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "PSEUDO": function (match) {
+ var excess,
+ unquoted = !match[6] && match[2];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( matchExpr["CHILD"].test( match[0] ) ) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (matchExpr["CHILD"].test(match[0])) {
+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Accept quoted arguments as-is
- if ( match[3] ) {
- match[2] = match[4] || match[5] || "";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Accept quoted arguments as-is
+ if (match[3]) {
+ match[2] = match[4] || match[5] || "";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Strip excess characters from unquoted arguments
- } else if ( unquoted && rpseudo.test( unquoted ) &&
- // Get excess from tokenize (recursively)
- (excess = tokenize( unquoted, true )) &&
- // advance to the next closing parenthesis
- (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Strip excess characters from unquoted arguments
+ } else if (unquoted && rpseudo.test(unquoted) &&
+ // Get excess from tokenize (recursively)
+ (excess = tokenize(unquoted, true)) &&
+ // advance to the next closing parenthesis
+ (excess = unquoted.indexOf(")", unquoted.length - excess) - unquoted.length)) {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // excess is a negative index
- match[0] = match[0].slice( 0, excess );
- match[2] = unquoted.slice( 0, excess );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // excess is a negative index
+ match[0] = match[0].slice(0, excess);
+ match[2] = unquoted.slice(0, excess);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Return only captures needed by the pseudo filter method (type and argument)
- return match.slice( 0, 3 );
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Return only captures needed by the pseudo filter method (type and argument)
+ return match.slice(0, 3);
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- filter: {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ filter: {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "TAG": function( nodeNameSelector ) {
- var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
- return nodeNameSelector === "*" ?
- function() { return true; } :
- function( elem ) {
- return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
- };
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "TAG": function (nodeNameSelector) {
+ var nodeName = nodeNameSelector.replace(runescape, funescape).toLowerCase();
+ return nodeNameSelector === "*" ?
+ function () { return true; } :
+ function (elem) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+ };
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "CLASS": function( className ) {
- var pattern = classCache[ className + " " ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "CLASS": function (className) {
+ var pattern = classCache[className + " "];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return pattern ||
- (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
- classCache( className, function( elem ) {
- return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" );
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return pattern ||
+ (pattern = new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)")) &&
+ classCache(className, function (elem) {
+ return pattern.test(typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "");
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "ATTR": function( name, operator, check ) {
- return function( elem ) {
- var result = Sizzle.attr( elem, name );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "ATTR": function (name, operator, check) {
+ return function (elem) {
+ var result = Sizzle.attr(elem, name);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( result == null ) {
- return operator === "!=";
- }
- if ( !operator ) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (result == null) {
+ return operator === "!=";
+ }
+ if (!operator) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- result += "";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ result += "";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return operator === "=" ? result === check :
- operator === "!=" ? result !== check :
- operator === "^=" ? check && result.indexOf( check ) === 0 :
- operator === "*=" ? check && result.indexOf( check ) > -1 :
- operator === "$=" ? check && result.slice( -check.length ) === check :
- operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
- operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
- false;
- };
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return operator === "=" ? result === check :
+ operator === "!=" ? result !== check :
+ operator === "^=" ? check && result.indexOf(check) === 0 :
+ operator === "*=" ? check && result.indexOf(check) > -1 :
+ operator === "$=" ? check && result.slice(-check.length) === check :
+ operator === "~=" ? (" " + result + " ").indexOf(check) > -1 :
+ operator === "|=" ? result === check || result.slice(0, check.length + 1) === check + "-" :
+ false;
+ };
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "CHILD": function( type, what, argument, first, last ) {
- var simple = type.slice( 0, 3 ) !== "nth",
- forward = type.slice( -4 ) !== "last",
- ofType = what === "of-type";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "CHILD": function (type, what, argument, first, last) {
+ var simple = type.slice(0, 3) !== "nth",
+ forward = type.slice(-4) !== "last",
+ ofType = what === "of-type";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return first === 1 && last === 0 ?
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return first === 1 && last === 0 ?
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Shortcut for :nth-*(n)
- function( elem ) {
- return !!elem.parentNode;
- } :
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Shortcut for :nth-*(n)
+ function (elem) {
+ return !!elem.parentNode;
+ } :
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function( elem, context, xml ) {
- var cache, outerCache, node, diff, nodeIndex, start,
- dir = simple !== forward ? "nextSibling" : "previousSibling",
- parent = elem.parentNode,
- name = ofType && elem.nodeName.toLowerCase(),
- useCache = !xml && !ofType;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function (elem, context, xml) {
+ var cache, outerCache, node, diff, nodeIndex, start,
+ dir = simple !== forward ? "nextSibling" : "previousSibling",
+ parent = elem.parentNode,
+ name = ofType && elem.nodeName.toLowerCase(),
+ useCache = !xml && !ofType;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( parent ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parent) {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // :(first|last|only)-(child|of-type)
- if ( simple ) {
- while ( dir ) {
- node = elem;
- while ( (node = node[ dir ]) ) {
- if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
- return false;
- }
- }
- // Reverse direction for :only-* (if we haven't yet done so)
- start = dir = type === "only" && !start && "nextSibling";
- }
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // :(first|last|only)-(child|of-type)
+ if (simple) {
+ while (dir) {
+ node = elem;
+ while ((node = node[dir])) {
+ if (ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) {
+ return false;
+ }
+ }
+ // Reverse direction for :only-* (if we haven't yet done so)
+ start = dir = type === "only" && !start && "nextSibling";
+ }
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- start = [ forward ? parent.firstChild : parent.lastChild ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ start = [forward ? parent.firstChild : parent.lastChild];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // non-xml :nth-child(...) stores cache data on `parent`
- if ( forward && useCache ) {
- // Seek `elem` from a previously-cached index
- outerCache = parent[ expando ] || (parent[ expando ] = {});
- cache = outerCache[ type ] || [];
- nodeIndex = cache[0] === dirruns && cache[1];
- diff = cache[0] === dirruns && cache[2];
- node = nodeIndex && parent.childNodes[ nodeIndex ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // non-xml :nth-child(...) stores cache data on `parent`
+ if (forward && useCache) {
+ // Seek `elem` from a previously-cached index
+ outerCache = parent[expando] || (parent[expando] = {});
+ cache = outerCache[type] || [];
+ nodeIndex = cache[0] === dirruns && cache[1];
+ diff = cache[0] === dirruns && cache[2];
+ node = nodeIndex && parent.childNodes[nodeIndex];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while ( (node = ++nodeIndex && node && node[ dir ] ||
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while ((node = ++nodeIndex && node && node[dir] ||
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Fallback to seeking `elem` from the start
- (diff = nodeIndex = 0) || start.pop()) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Fallback to seeking `elem` from the start
+ (diff = nodeIndex = 0) || start.pop())) {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // When found, cache indexes on `parent` and break
- if ( node.nodeType === 1 && ++diff && node === elem ) {
- outerCache[ type ] = [ dirruns, nodeIndex, diff ];
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // When found, cache indexes on `parent` and break
+ if (node.nodeType === 1 && ++diff && node === elem) {
+ outerCache[type] = [dirruns, nodeIndex, diff];
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Use previously-cached element index if available
- } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
- diff = cache[1];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Use previously-cached element index if available
+ } else if (useCache && (cache = (elem[expando] || (elem[expando] = {}))[type]) && cache[0] === dirruns) {
+ diff = cache[1];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
- } else {
- // Use the same loop as above to seek `elem` from the start
- while ( (node = ++nodeIndex && node && node[ dir ] ||
- (diff = nodeIndex = 0) || start.pop()) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
+ } else {
+ // Use the same loop as above to seek `elem` from the start
+ while ((node = ++nodeIndex && node && node[dir] ||
+ (diff = nodeIndex = 0) || start.pop())) {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
- // Cache the index of each encountered element
- if ( useCache ) {
- (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) && ++diff) {
+ // Cache the index of each encountered element
+ if (useCache) {
+ (node[expando] || (node[expando] = {}))[type] = [dirruns, diff];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( node === elem ) {
- break;
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node === elem) {
+ break;
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Incorporate the offset, then check against cycle size
- diff -= last;
- return diff === first || ( diff % first === 0 && diff / first >= 0 );
- }
- };
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Incorporate the offset, then check against cycle size
+ diff -= last;
+ return diff === first || (diff % first === 0 && diff / first >= 0);
+ }
+ };
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "PSEUDO": function( pseudo, argument ) {
- // pseudo-class names are case-insensitive
- // http://www.w3.org/TR/selectors/#pseudo-classes
- // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
- // Remember that setFilters inherits from pseudos
- var args,
- fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
- Sizzle.error( "unsupported pseudo: " + pseudo );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "PSEUDO": function (pseudo, argument) {
+ // pseudo-class names are case-insensitive
+ // http://www.w3.org/TR/selectors/#pseudo-classes
+ // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+ // Remember that setFilters inherits from pseudos
+ var args,
+ fn = Expr.pseudos[pseudo] || Expr.setFilters[pseudo.toLowerCase()] ||
+ Sizzle.error("unsupported pseudo: " + pseudo);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // The user may use createPseudo to indicate that
- // arguments are needed to create the filter function
- // just as Sizzle does
- if ( fn[ expando ] ) {
- return fn( argument );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // The user may use createPseudo to indicate that
+ // arguments are needed to create the filter function
+ // just as Sizzle does
+ if (fn[expando]) {
+ return fn(argument);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // But maintain support for old signatures
- if ( fn.length > 1 ) {
- args = [ pseudo, pseudo, "", argument ];
- return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
- markFunction(function( seed, matches ) {
- var idx,
- matched = fn( seed, argument ),
- i = matched.length;
- while ( i-- ) {
- idx = indexOf.call( seed, matched[i] );
- seed[ idx ] = !( matches[ idx ] = matched[i] );
- }
- }) :
- function( elem ) {
- return fn( elem, 0, args );
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // But maintain support for old signatures
+ if (fn.length > 1) {
+ args = [pseudo, pseudo, "", argument];
+ return Expr.setFilters.hasOwnProperty(pseudo.toLowerCase()) ?
+ markFunction(function (seed, matches) {
+ var idx,
+ matched = fn(seed, argument),
+ i = matched.length;
+ while (i--) {
+ idx = indexOf.call(seed, matched[i]);
+ seed[idx] = !(matches[idx] = matched[i]);
+ }
+ }) :
+ function (elem) {
+ return fn(elem, 0, args);
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return fn;
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return fn;
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- pseudos: {
- // Potentially complex pseudos
- "not": markFunction(function( selector ) {
- // Trim the selector passed to compile
- // to avoid treating leading and trailing
- // spaces as combinators
- var input = [],
- results = [],
- matcher = compile( selector.replace( rtrim, "$1" ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ pseudos: {
+ // Potentially complex pseudos
+ "not": markFunction(function (selector) {
+ // Trim the selector passed to compile
+ // to avoid treating leading and trailing
+ // spaces as combinators
+ var input = [],
+ results = [],
+ matcher = compile(selector.replace(rtrim, "$1"));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return matcher[ expando ] ?
- markFunction(function( seed, matches, context, xml ) {
- var elem,
- unmatched = matcher( seed, null, xml, [] ),
- i = seed.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return matcher[expando] ?
+ markFunction(function (seed, matches, context, xml) {
+ var elem,
+ unmatched = matcher(seed, null, xml, []),
+ i = seed.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Match elements unmatched by `matcher`
- while ( i-- ) {
- if ( (elem = unmatched[i]) ) {
- seed[i] = !(matches[i] = elem);
- }
- }
- }) :
- function( elem, context, xml ) {
- input[0] = elem;
- matcher( input, null, xml, results );
- return !results.pop();
- };
- }),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Match elements unmatched by `matcher`
+ while (i--) {
+ if ((elem = unmatched[i])) {
+ seed[i] = !(matches[i] = elem);
+ }
+ }
+ }) :
+ function (elem, context, xml) {
+ input[0] = elem;
+ matcher(input, null, xml, results);
+ return !results.pop();
+ };
+ }),
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "has": markFunction(function( selector ) {
- return function( elem ) {
- return Sizzle( selector, elem ).length > 0;
- };
- }),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "has": markFunction(function (selector) {
+ return function (elem) {
+ return Sizzle(selector, elem).length > 0;
+ };
+ }),
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "contains": markFunction(function( text ) {
- text = text.replace( runescape, funescape );
- return function( elem ) {
- return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
- };
- }),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "contains": markFunction(function (text) {
+ text = text.replace(runescape, funescape);
+ return function (elem) {
+ return (elem.textContent || elem.innerText || getText(elem)).indexOf(text) > -1;
+ };
+ }),
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // "Whether an element is represented by a :lang() selector
- // is based solely on the element's language value
- // being equal to the identifier C,
- // or beginning with the identifier C immediately followed by "-".
- // The matching of C against the element's language value is performed case-insensitively.
- // The identifier C does not have to be a valid language name."
- // http://www.w3.org/TR/selectors/#lang-pseudo
- "lang": markFunction( function( lang ) {
- // lang value must be a valid identifier
- if ( !ridentifier.test(lang || "") ) {
- Sizzle.error( "unsupported lang: " + lang );
- }
- lang = lang.replace( runescape, funescape ).toLowerCase();
- return function( elem ) {
- var elemLang;
- do {
- if ( (elemLang = documentIsHTML ?
- elem.lang :
- elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // "Whether an element is represented by a :lang() selector
+ // is based solely on the element's language value
+ // being equal to the identifier C,
+ // or beginning with the identifier C immediately followed by "-".
+ // The matching of C against the element's language value is performed case-insensitively.
+ // The identifier C does not have to be a valid language name."
+ // http://www.w3.org/TR/selectors/#lang-pseudo
+ "lang": markFunction(function (lang) {
+ // lang value must be a valid identifier
+ if (!ridentifier.test(lang || "")) {
+ Sizzle.error("unsupported lang: " + lang);
+ }
+ lang = lang.replace(runescape, funescape).toLowerCase();
+ return function (elem) {
+ var elemLang;
+ do {
+ if ((elemLang = documentIsHTML ?
+ elem.lang :
+ elem.getAttribute("xml:lang") || elem.getAttribute("lang"))) {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elemLang = elemLang.toLowerCase();
- return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
- }
- } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
- return false;
- };
- }),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elemLang = elemLang.toLowerCase();
+ return elemLang === lang || elemLang.indexOf(lang + "-") === 0;
+ }
+ } while ((elem = elem.parentNode) && elem.nodeType === 1);
+ return false;
+ };
+ }),
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Miscellaneous
- "target": function( elem ) {
- var hash = window.location && window.location.hash;
- return hash && hash.slice( 1 ) === elem.id;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Miscellaneous
+ "target": function (elem) {
+ var hash = window.location && window.location.hash;
+ return hash && hash.slice(1) === elem.id;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "root": function( elem ) {
- return elem === docElem;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "root": function (elem) {
+ return elem === docElem;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "focus": function( elem ) {
- return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "focus": function (elem) {
+ return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Boolean properties
- "enabled": function( elem ) {
- return elem.disabled === false;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Boolean properties
+ "enabled": function (elem) {
+ return elem.disabled === false;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "disabled": function( elem ) {
- return elem.disabled === true;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "disabled": function (elem) {
+ return elem.disabled === true;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "checked": function( elem ) {
- // In CSS3, :checked should return both checked and selected elements
- // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
- var nodeName = elem.nodeName.toLowerCase();
- return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "checked": function (elem) {
+ // In CSS3, :checked should return both checked and selected elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ var nodeName = elem.nodeName.toLowerCase();
+ return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "selected": function( elem ) {
- // Accessing this property makes selected-by-default
- // options in Safari work properly
- if ( elem.parentNode ) {
- elem.parentNode.selectedIndex;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "selected": function (elem) {
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ if (elem.parentNode) {
+ elem.parentNode.selectedIndex;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return elem.selected === true;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return elem.selected === true;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Contents
- "empty": function( elem ) {
- // http://www.w3.org/TR/selectors/#empty-pseudo
- // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
- // but not by others (comment: 8; processing instruction: 7; etc.)
- // nodeType < 6 works because attributes (2) do not appear as children
- for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
- if ( elem.nodeType < 6 ) {
- return false;
- }
- }
- return true;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Contents
+ "empty": function (elem) {
+ // http://www.w3.org/TR/selectors/#empty-pseudo
+ // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
+ // but not by others (comment: 8; processing instruction: 7; etc.)
+ // nodeType < 6 works because attributes (2) do not appear as children
+ for (elem = elem.firstChild; elem; elem = elem.nextSibling) {
+ if (elem.nodeType < 6) {
+ return false;
+ }
+ }
+ return true;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "parent": function( elem ) {
- return !Expr.pseudos["empty"]( elem );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "parent": function (elem) {
+ return !Expr.pseudos["empty"](elem);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Element/input types
- "header": function( elem ) {
- return rheader.test( elem.nodeName );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Element/input types
+ "header": function (elem) {
+ return rheader.test(elem.nodeName);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "input": function( elem ) {
- return rinputs.test( elem.nodeName );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "input": function (elem) {
+ return rinputs.test(elem.nodeName);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "button": function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return name === "input" && elem.type === "button" || name === "button";
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "button": function (elem) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === "button" || name === "button";
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "text": function( elem ) {
- var attr;
- return elem.nodeName.toLowerCase() === "input" &&
- elem.type === "text" &&
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "text": function (elem) {
+ var attr;
+ return elem.nodeName.toLowerCase() === "input" &&
+ elem.type === "text" &&
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Support: IE<8
- // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
- ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Support: IE<8
+ // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
+ ((attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text");
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Position-in-collection
- "first": createPositionalPseudo(function() {
- return [ 0 ];
- }),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Position-in-collection
+ "first": createPositionalPseudo(function () {
+ return [0];
+ }),
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "last": createPositionalPseudo(function( matchIndexes, length ) {
- return [ length - 1 ];
- }),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "last": createPositionalPseudo(function (matchIndexes, length) {
+ return [length - 1];
+ }),
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
- return [ argument < 0 ? argument + length : argument ];
- }),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "eq": createPositionalPseudo(function (matchIndexes, length, argument) {
+ return [argument < 0 ? argument + length : argument];
+ }),
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "even": createPositionalPseudo(function( matchIndexes, length ) {
- var i = 0;
- for ( ; i < length; i += 2 ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- }),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "even": createPositionalPseudo(function (matchIndexes, length) {
+ var i = 0;
+ for (; i < length; i += 2) {
+ matchIndexes.push(i);
+ }
+ return matchIndexes;
+ }),
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "odd": createPositionalPseudo(function( matchIndexes, length ) {
- var i = 1;
- for ( ; i < length; i += 2 ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- }),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "odd": createPositionalPseudo(function (matchIndexes, length) {
+ var i = 1;
+ for (; i < length; i += 2) {
+ matchIndexes.push(i);
+ }
+ return matchIndexes;
+ }),
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
- var i = argument < 0 ? argument + length : argument;
- for ( ; --i >= 0; ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- }),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "lt": createPositionalPseudo(function (matchIndexes, length, argument) {
+ var i = argument < 0 ? argument + length : argument;
+ for (; --i >= 0;) {
+ matchIndexes.push(i);
+ }
+ return matchIndexes;
+ }),
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
- var i = argument < 0 ? argument + length : argument;
- for ( ; ++i < length; ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- })
- }
-};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "gt": createPositionalPseudo(function (matchIndexes, length, argument) {
+ var i = argument < 0 ? argument + length : argument;
+ for (; ++i < length;) {
+ matchIndexes.push(i);
+ }
+ return matchIndexes;
+ })
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-Expr.pseudos["nth"] = Expr.pseudos["eq"];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Expr.pseudos["nth"] = Expr.pseudos["eq"];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Add button/input type pseudos
-for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
- Expr.pseudos[ i ] = createInputPseudo( i );
-}
-for ( i in { submit: true, reset: true } ) {
- Expr.pseudos[ i ] = createButtonPseudo( i );
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add button/input type pseudos
+ for (i in { radio: true, checkbox: true, file: true, password: true, image: true }) {
+ Expr.pseudos[i] = createInputPseudo(i);
+ }
+ for (i in { submit: true, reset: true }) {
+ Expr.pseudos[i] = createButtonPseudo(i);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Easy API for creating new setFilters
-function setFilters() {}
-setFilters.prototype = Expr.filters = Expr.pseudos;
-Expr.setFilters = new setFilters();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Easy API for creating new setFilters
+ function setFilters() { }
+ setFilters.prototype = Expr.filters = Expr.pseudos;
+ Expr.setFilters = new setFilters();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
- var matched, match, tokens, type,
- soFar, groups, preFilters,
- cached = tokenCache[ selector + " " ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ tokenize = Sizzle.tokenize = function (selector, parseOnly) {
+ var matched, match, tokens, type,
+ soFar, groups, preFilters,
+ cached = tokenCache[selector + " "];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( cached ) {
- return parseOnly ? 0 : cached.slice( 0 );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (cached) {
+ return parseOnly ? 0 : cached.slice(0);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- soFar = selector;
- groups = [];
- preFilters = Expr.preFilter;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ soFar = selector;
+ groups = [];
+ preFilters = Expr.preFilter;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while ( soFar ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (soFar) {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Comma and first run
- if ( !matched || (match = rcomma.exec( soFar )) ) {
- if ( match ) {
- // Don't consume trailing commas as valid
- soFar = soFar.slice( match[0].length ) || soFar;
- }
- groups.push( (tokens = []) );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Comma and first run
+ if (!matched || (match = rcomma.exec(soFar))) {
+ if (match) {
+ // Don't consume trailing commas as valid
+ soFar = soFar.slice(match[0].length) || soFar;
+ }
+ groups.push((tokens = []));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- matched = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ matched = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Combinators
- if ( (match = rcombinators.exec( soFar )) ) {
- matched = match.shift();
- tokens.push({
- value: matched,
- // Cast descendant combinators to space
- type: match[0].replace( rtrim, " " )
- });
- soFar = soFar.slice( matched.length );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Combinators
+ if ((match = rcombinators.exec(soFar))) {
+ matched = match.shift();
+ tokens.push({
+ value: matched,
+ // Cast descendant combinators to space
+ type: match[0].replace(rtrim, " ")
+ });
+ soFar = soFar.slice(matched.length);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Filters
- for ( type in Expr.filter ) {
- if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
- (match = preFilters[ type ]( match ))) ) {
- matched = match.shift();
- tokens.push({
- value: matched,
- type: type,
- matches: match
- });
- soFar = soFar.slice( matched.length );
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Filters
+ for (type in Expr.filter) {
+ if ((match = matchExpr[type].exec(soFar)) && (!preFilters[type] ||
+ (match = preFilters[type](match)))) {
+ matched = match.shift();
+ tokens.push({
+ value: matched,
+ type: type,
+ matches: match
+ });
+ soFar = soFar.slice(matched.length);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( !matched ) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!matched) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Return the length of the invalid excess
- // if we're just parsing
- // Otherwise, throw an error or return tokens
- return parseOnly ?
- soFar.length :
- soFar ?
- Sizzle.error( selector ) :
- // Cache the tokens
- tokenCache( selector, groups ).slice( 0 );
-};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Return the length of the invalid excess
+ // if we're just parsing
+ // Otherwise, throw an error or return tokens
+ return parseOnly ?
+ soFar.length :
+ soFar ?
+ Sizzle.error(selector) :
+ // Cache the tokens
+ tokenCache(selector, groups).slice(0);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function toSelector( tokens ) {
- var i = 0,
- len = tokens.length,
- selector = "";
- for ( ; i < len; i++ ) {
- selector += tokens[i].value;
- }
- return selector;
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function toSelector(tokens) {
+ var i = 0,
+ len = tokens.length,
+ selector = "";
+ for (; i < len; i++) {
+ selector += tokens[i].value;
+ }
+ return selector;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function addCombinator( matcher, combinator, base ) {
- var dir = combinator.dir,
- checkNonElements = base && dir === "parentNode",
- doneName = done++;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function addCombinator(matcher, combinator, base) {
+ var dir = combinator.dir,
+ checkNonElements = base && dir === "parentNode",
+ doneName = done++;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return combinator.first ?
- // Check against closest ancestor/preceding element
- function( elem, context, xml ) {
- while ( (elem = elem[ dir ]) ) {
- if ( elem.nodeType === 1 || checkNonElements ) {
- return matcher( elem, context, xml );
- }
- }
- } :
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return combinator.first ?
+ // Check against closest ancestor/preceding element
+ function (elem, context, xml) {
+ while ((elem = elem[dir])) {
+ if (elem.nodeType === 1 || checkNonElements) {
+ return matcher(elem, context, xml);
+ }
+ }
+ } :
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check against all ancestor/preceding elements
- function( elem, context, xml ) {
- var oldCache, outerCache,
- newCache = [ dirruns, doneName ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check against all ancestor/preceding elements
+ function (elem, context, xml) {
+ var oldCache, outerCache,
+ newCache = [dirruns, doneName];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
- if ( xml ) {
- while ( (elem = elem[ dir ]) ) {
- if ( elem.nodeType === 1 || checkNonElements ) {
- if ( matcher( elem, context, xml ) ) {
- return true;
- }
- }
- }
- } else {
- while ( (elem = elem[ dir ]) ) {
- if ( elem.nodeType === 1 || checkNonElements ) {
- outerCache = elem[ expando ] || (elem[ expando ] = {});
- if ( (oldCache = outerCache[ dir ]) &&
- oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
+ if (xml) {
+ while ((elem = elem[dir])) {
+ if (elem.nodeType === 1 || checkNonElements) {
+ if (matcher(elem, context, xml)) {
+ return true;
+ }
+ }
+ }
+ } else {
+ while ((elem = elem[dir])) {
+ if (elem.nodeType === 1 || checkNonElements) {
+ outerCache = elem[expando] || (elem[expando] = {});
+ if ((oldCache = outerCache[dir]) &&
+ oldCache[0] === dirruns && oldCache[1] === doneName) {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Assign to newCache so results back-propagate to previous elements
- return (newCache[ 2 ] = oldCache[ 2 ]);
- } else {
- // Reuse newcache so results back-propagate to previous elements
- outerCache[ dir ] = newCache;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Assign to newCache so results back-propagate to previous elements
+ return (newCache[2] = oldCache[2]);
+ } else {
+ // Reuse newcache so results back-propagate to previous elements
+ outerCache[dir] = newCache;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // A match means we're done; a fail means we have to keep checking
- if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
- return true;
- }
- }
- }
- }
- }
- };
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // A match means we're done; a fail means we have to keep checking
+ if ((newCache[2] = matcher(elem, context, xml))) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function elementMatcher( matchers ) {
- return matchers.length > 1 ?
- function( elem, context, xml ) {
- var i = matchers.length;
- while ( i-- ) {
- if ( !matchers[i]( elem, context, xml ) ) {
- return false;
- }
- }
- return true;
- } :
- matchers[0];
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function elementMatcher(matchers) {
+ return matchers.length > 1 ?
+ function (elem, context, xml) {
+ var i = matchers.length;
+ while (i--) {
+ if (!matchers[i](elem, context, xml)) {
+ return false;
+ }
+ }
+ return true;
+ } :
+ matchers[0];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function multipleContexts( selector, contexts, results ) {
- var i = 0,
- len = contexts.length;
- for ( ; i < len; i++ ) {
- Sizzle( selector, contexts[i], results );
- }
- return results;
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function multipleContexts(selector, contexts, results) {
+ var i = 0,
+ len = contexts.length;
+ for (; i < len; i++) {
+ Sizzle(selector, contexts[i], results);
+ }
+ return results;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function condense( unmatched, map, filter, context, xml ) {
- var elem,
- newUnmatched = [],
- i = 0,
- len = unmatched.length,
- mapped = map != null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function condense(unmatched, map, filter, context, xml) {
+ var elem,
+ newUnmatched = [],
+ i = 0,
+ len = unmatched.length,
+ mapped = map != null;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for ( ; i < len; i++ ) {
- if ( (elem = unmatched[i]) ) {
- if ( !filter || filter( elem, context, xml ) ) {
- newUnmatched.push( elem );
- if ( mapped ) {
- map.push( i );
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (; i < len; i++) {
+ if ((elem = unmatched[i])) {
+ if (!filter || filter(elem, context, xml)) {
+ newUnmatched.push(elem);
+ if (mapped) {
+ map.push(i);
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return newUnmatched;
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return newUnmatched;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
- if ( postFilter && !postFilter[ expando ] ) {
- postFilter = setMatcher( postFilter );
- }
- if ( postFinder && !postFinder[ expando ] ) {
- postFinder = setMatcher( postFinder, postSelector );
- }
- return markFunction(function( seed, results, context, xml ) {
- var temp, i, elem,
- preMap = [],
- postMap = [],
- preexisting = results.length,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setMatcher(preFilter, selector, matcher, postFilter, postFinder, postSelector) {
+ if (postFilter && !postFilter[expando]) {
+ postFilter = setMatcher(postFilter);
+ }
+ if (postFinder && !postFinder[expando]) {
+ postFinder = setMatcher(postFinder, postSelector);
+ }
+ return markFunction(function (seed, results, context, xml) {
+ var temp, i, elem,
+ preMap = [],
+ postMap = [],
+ preexisting = results.length,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Get initial elements from seed or context
- elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get initial elements from seed or context
+ elems = seed || multipleContexts(selector || "*", context.nodeType ? [context] : context, []),
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Prefilter to get matcher input, preserving a map for seed-results synchronization
- matcherIn = preFilter && ( seed || !selector ) ?
- condense( elems, preMap, preFilter, context, xml ) :
- elems,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Prefilter to get matcher input, preserving a map for seed-results synchronization
+ matcherIn = preFilter && (seed || !selector) ?
+ condense(elems, preMap, preFilter, context, xml) :
+ elems,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- matcherOut = matcher ?
- // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
- postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ matcherOut = matcher ?
+ // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+ postFinder || (seed ? preFilter : preexisting || postFilter) ?
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // ...intermediate processing is necessary
- [] :
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // ...intermediate processing is necessary
+ [] :
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // ...otherwise use results directly
- results :
- matcherIn;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // ...otherwise use results directly
+ results :
+ matcherIn;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Find primary matches
- if ( matcher ) {
- matcher( matcherIn, matcherOut, context, xml );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find primary matches
+ if (matcher) {
+ matcher(matcherIn, matcherOut, context, xml);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Apply postFilter
- if ( postFilter ) {
- temp = condense( matcherOut, postMap );
- postFilter( temp, [], context, xml );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Apply postFilter
+ if (postFilter) {
+ temp = condense(matcherOut, postMap);
+ postFilter(temp, [], context, xml);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Un-match failing elements by moving them back to matcherIn
- i = temp.length;
- while ( i-- ) {
- if ( (elem = temp[i]) ) {
- matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Un-match failing elements by moving them back to matcherIn
+ i = temp.length;
+ while (i--) {
+ if ((elem = temp[i])) {
+ matcherOut[postMap[i]] = !(matcherIn[postMap[i]] = elem);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( seed ) {
- if ( postFinder || preFilter ) {
- if ( postFinder ) {
- // Get the final matcherOut by condensing this intermediate into postFinder contexts
- temp = [];
- i = matcherOut.length;
- while ( i-- ) {
- if ( (elem = matcherOut[i]) ) {
- // Restore matcherIn since elem is not yet a final match
- temp.push( (matcherIn[i] = elem) );
- }
- }
- postFinder( null, (matcherOut = []), temp, xml );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (seed) {
+ if (postFinder || preFilter) {
+ if (postFinder) {
+ // Get the final matcherOut by condensing this intermediate into postFinder contexts
+ temp = [];
+ i = matcherOut.length;
+ while (i--) {
+ if ((elem = matcherOut[i])) {
+ // Restore matcherIn since elem is not yet a final match
+ temp.push((matcherIn[i] = elem));
+ }
+ }
+ postFinder(null, (matcherOut = []), temp, xml);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move matched elements from seed to results to keep them synchronized
- i = matcherOut.length;
- while ( i-- ) {
- if ( (elem = matcherOut[i]) &&
- (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move matched elements from seed to results to keep them synchronized
+ i = matcherOut.length;
+ while (i--) {
+ if ((elem = matcherOut[i]) &&
+ (temp = postFinder ? indexOf.call(seed, elem) : preMap[i]) > -1) {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- seed[temp] = !(results[temp] = elem);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ seed[temp] = !(results[temp] = elem);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add elements to results, through postFinder if defined
- } else {
- matcherOut = condense(
- matcherOut === results ?
- matcherOut.splice( preexisting, matcherOut.length ) :
- matcherOut
- );
- if ( postFinder ) {
- postFinder( null, results, matcherOut, xml );
- } else {
- push.apply( results, matcherOut );
- }
- }
- });
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add elements to results, through postFinder if defined
+ } else {
+ matcherOut = condense(
+ matcherOut === results ?
+ matcherOut.splice(preexisting, matcherOut.length) :
+ matcherOut
+ );
+ if (postFinder) {
+ postFinder(null, results, matcherOut, xml);
+ } else {
+ push.apply(results, matcherOut);
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function matcherFromTokens( tokens ) {
- var checkContext, matcher, j,
- len = tokens.length,
- leadingRelative = Expr.relative[ tokens[0].type ],
- implicitRelative = leadingRelative || Expr.relative[" "],
- i = leadingRelative ? 1 : 0,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function matcherFromTokens(tokens) {
+ var checkContext, matcher, j,
+ len = tokens.length,
+ leadingRelative = Expr.relative[tokens[0].type],
+ implicitRelative = leadingRelative || Expr.relative[" "],
+ i = leadingRelative ? 1 : 0,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // The foundational matcher ensures that elements are reachable from top-level context(s)
- matchContext = addCombinator( function( elem ) {
- return elem === checkContext;
- }, implicitRelative, true ),
- matchAnyContext = addCombinator( function( elem ) {
- return indexOf.call( checkContext, elem ) > -1;
- }, implicitRelative, true ),
- matchers = [ function( elem, context, xml ) {
- return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
- (checkContext = context).nodeType ?
- matchContext( elem, context, xml ) :
- matchAnyContext( elem, context, xml ) );
- } ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // The foundational matcher ensures that elements are reachable from top-level context(s)
+ matchContext = addCombinator(function (elem) {
+ return elem === checkContext;
+ }, implicitRelative, true),
+ matchAnyContext = addCombinator(function (elem) {
+ return indexOf.call(checkContext, elem) > -1;
+ }, implicitRelative, true),
+ matchers = [function (elem, context, xml) {
+ return (!leadingRelative && (xml || context !== outermostContext)) || (
+ (checkContext = context).nodeType ?
+ matchContext(elem, context, xml) :
+ matchAnyContext(elem, context, xml));
+ }];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for ( ; i < len; i++ ) {
- if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
- matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
- } else {
- matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (; i < len; i++) {
+ if ((matcher = Expr.relative[tokens[i].type])) {
+ matchers = [addCombinator(elementMatcher(matchers), matcher)];
+ } else {
+ matcher = Expr.filter[tokens[i].type].apply(null, tokens[i].matches);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Return special upon seeing a positional matcher
- if ( matcher[ expando ] ) {
- // Find the next relative operator (if any) for proper handling
- j = ++i;
- for ( ; j < len; j++ ) {
- if ( Expr.relative[ tokens[j].type ] ) {
- break;
- }
- }
- return setMatcher(
- i > 1 && elementMatcher( matchers ),
- i > 1 && toSelector(
- // If the preceding token was a descendant combinator, insert an implicit any-element `*`
- tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
- ).replace( rtrim, "$1" ),
- matcher,
- i < j && matcherFromTokens( tokens.slice( i, j ) ),
- j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
- j < len && toSelector( tokens )
- );
- }
- matchers.push( matcher );
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Return special upon seeing a positional matcher
+ if (matcher[expando]) {
+ // Find the next relative operator (if any) for proper handling
+ j = ++i;
+ for (; j < len; j++) {
+ if (Expr.relative[tokens[j].type]) {
+ break;
+ }
+ }
+ return setMatcher(
+ i > 1 && elementMatcher(matchers),
+ i > 1 && toSelector(
+ // If the preceding token was a descendant combinator, insert an implicit any-element `*`
+ tokens.slice(0, i - 1).concat({ value: tokens[i - 2].type === " " ? "*" : "" })
+ ).replace(rtrim, "$1"),
+ matcher,
+ i < j && matcherFromTokens(tokens.slice(i, j)),
+ j < len && matcherFromTokens((tokens = tokens.slice(j))),
+ j < len && toSelector(tokens)
+ );
+ }
+ matchers.push(matcher);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return elementMatcher( matchers );
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return elementMatcher(matchers);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
- var bySet = setMatchers.length > 0,
- byElement = elementMatchers.length > 0,
- superMatcher = function( seed, context, xml, results, outermost ) {
- var elem, j, matcher,
- matchedCount = 0,
- i = "0",
- unmatched = seed && [],
- setMatched = [],
- contextBackup = outermostContext,
- // We must always have either seed elements or outermost context
- elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
- // Use integer dirruns iff this is the outermost matcher
- dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
- len = elems.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function matcherFromGroupMatchers(elementMatchers, setMatchers) {
+ var bySet = setMatchers.length > 0,
+ byElement = elementMatchers.length > 0,
+ superMatcher = function (seed, context, xml, results, outermost) {
+ var elem, j, matcher,
+ matchedCount = 0,
+ i = "0",
+ unmatched = seed && [],
+ setMatched = [],
+ contextBackup = outermostContext,
+ // We must always have either seed elements or outermost context
+ elems = seed || byElement && Expr.find["TAG"]("*", outermost),
+ // Use integer dirruns iff this is the outermost matcher
+ dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
+ len = elems.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( outermost ) {
- outermostContext = context !== document && context;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (outermost) {
+ outermostContext = context !== document && context;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add elements passing elementMatchers directly to results
- // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
- // Support: IE<9, Safari
- // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
- for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
- if ( byElement && elem ) {
- j = 0;
- while ( (matcher = elementMatchers[j++]) ) {
- if ( matcher( elem, context, xml ) ) {
- results.push( elem );
- break;
- }
- }
- if ( outermost ) {
- dirruns = dirrunsUnique;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add elements passing elementMatchers directly to results
+ // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
+ // Support: IE<9, Safari
+ // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
+ for (; i !== len && (elem = elems[i]) != null; i++) {
+ if (byElement && elem) {
+ j = 0;
+ while ((matcher = elementMatchers[j++])) {
+ if (matcher(elem, context, xml)) {
+ results.push(elem);
+ break;
+ }
+ }
+ if (outermost) {
+ dirruns = dirrunsUnique;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Track unmatched elements for set filters
- if ( bySet ) {
- // They will have gone through all possible matchers
- if ( (elem = !matcher && elem) ) {
- matchedCount--;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Track unmatched elements for set filters
+ if (bySet) {
+ // They will have gone through all possible matchers
+ if ((elem = !matcher && elem)) {
+ matchedCount--;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Lengthen the array for every element, matched or not
- if ( seed ) {
- unmatched.push( elem );
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Lengthen the array for every element, matched or not
+ if (seed) {
+ unmatched.push(elem);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Apply set filters to unmatched elements
- matchedCount += i;
- if ( bySet && i !== matchedCount ) {
- j = 0;
- while ( (matcher = setMatchers[j++]) ) {
- matcher( unmatched, setMatched, context, xml );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Apply set filters to unmatched elements
+ matchedCount += i;
+ if (bySet && i !== matchedCount) {
+ j = 0;
+ while ((matcher = setMatchers[j++])) {
+ matcher(unmatched, setMatched, context, xml);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( seed ) {
- // Reintegrate element matches to eliminate the need for sorting
- if ( matchedCount > 0 ) {
- while ( i-- ) {
- if ( !(unmatched[i] || setMatched[i]) ) {
- setMatched[i] = pop.call( results );
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (seed) {
+ // Reintegrate element matches to eliminate the need for sorting
+ if (matchedCount > 0) {
+ while (i--) {
+ if (!(unmatched[i] || setMatched[i])) {
+ setMatched[i] = pop.call(results);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Discard index placeholder values to get only actual matches
- setMatched = condense( setMatched );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Discard index placeholder values to get only actual matches
+ setMatched = condense(setMatched);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add matches to results
- push.apply( results, setMatched );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add matches to results
+ push.apply(results, setMatched);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Seedless set matches succeeding multiple successful matchers stipulate sorting
- if ( outermost && !seed && setMatched.length > 0 &&
- ( matchedCount + setMatchers.length ) > 1 ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Seedless set matches succeeding multiple successful matchers stipulate sorting
+ if (outermost && !seed && setMatched.length > 0 &&
+ (matchedCount + setMatchers.length) > 1) {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Sizzle.uniqueSort( results );
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Sizzle.uniqueSort(results);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Override manipulation of globals by nested matchers
- if ( outermost ) {
- dirruns = dirrunsUnique;
- outermostContext = contextBackup;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Override manipulation of globals by nested matchers
+ if (outermost) {
+ dirruns = dirrunsUnique;
+ outermostContext = contextBackup;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return unmatched;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return unmatched;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return bySet ?
- markFunction( superMatcher ) :
- superMatcher;
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return bySet ?
+ markFunction(superMatcher) :
+ superMatcher;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
- var i,
- setMatchers = [],
- elementMatchers = [],
- cached = compilerCache[ selector + " " ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ compile = Sizzle.compile = function (selector, match /* Internal Use Only */) {
+ var i,
+ setMatchers = [],
+ elementMatchers = [],
+ cached = compilerCache[selector + " "];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( !cached ) {
- // Generate a function of recursive functions that can be used to check each element
- if ( !match ) {
- match = tokenize( selector );
- }
- i = match.length;
- while ( i-- ) {
- cached = matcherFromTokens( match[i] );
- if ( cached[ expando ] ) {
- setMatchers.push( cached );
- } else {
- elementMatchers.push( cached );
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!cached) {
+ // Generate a function of recursive functions that can be used to check each element
+ if (!match) {
+ match = tokenize(selector);
+ }
+ i = match.length;
+ while (i--) {
+ cached = matcherFromTokens(match[i]);
+ if (cached[expando]) {
+ setMatchers.push(cached);
+ } else {
+ elementMatchers.push(cached);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Cache the compiled function
- cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Cache the compiled function
+ cached = compilerCache(selector, matcherFromGroupMatchers(elementMatchers, setMatchers));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Save selector and tokenization
- cached.selector = selector;
- }
- return cached;
-};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Save selector and tokenization
+ cached.selector = selector;
+ }
+ return cached;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * A low-level selection function that works with Sizzle's compiled
- * selector functions
- * @param {String|Function} selector A selector or a pre-compiled
- * selector function built with Sizzle.compile
- * @param {Element} context
- * @param {Array} [results]
- * @param {Array} [seed] A set of elements to match against
- */
-select = Sizzle.select = function( selector, context, results, seed ) {
- var i, tokens, token, type, find,
- compiled = typeof selector === "function" && selector,
- match = !seed && tokenize( (selector = compiled.selector || selector) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * A low-level selection function that works with Sizzle's compiled
+ * selector functions
+ * @param {String|Function} selector A selector or a pre-compiled
+ * selector function built with Sizzle.compile
+ * @param {Element} context
+ * @param {Array} [results]
+ * @param {Array} [seed] A set of elements to match against
+ */
+ select = Sizzle.select = function (selector, context, results, seed) {
+ var i, tokens, token, type, find,
+ compiled = typeof selector === "function" && selector,
+ match = !seed && tokenize((selector = compiled.selector || selector));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- results = results || [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ results = results || [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Try to minimize operations if there is no seed and only one group
- if ( match.length === 1 ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Try to minimize operations if there is no seed and only one group
+ if (match.length === 1) {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Take a shortcut and set the context if the root selector is an ID
- tokens = match[0] = match[0].slice( 0 );
- if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
- support.getById && context.nodeType === 9 && documentIsHTML &&
- Expr.relative[ tokens[1].type ] ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Take a shortcut and set the context if the root selector is an ID
+ tokens = match[0] = match[0].slice(0);
+ if (tokens.length > 2 && (token = tokens[0]).type === "ID" &&
+ support.getById && context.nodeType === 9 && documentIsHTML &&
+ Expr.relative[tokens[1].type]) {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
- if ( !context ) {
- return results;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ context = (Expr.find["ID"](token.matches[0].replace(runescape, funescape), context) || [])[0];
+ if (!context) {
+ return results;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Precompiled matchers will still verify ancestry, so step up a level
- } else if ( compiled ) {
- context = context.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Precompiled matchers will still verify ancestry, so step up a level
+ } else if (compiled) {
+ context = context.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- selector = selector.slice( tokens.shift().value.length );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ selector = selector.slice(tokens.shift().value.length);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Fetch a seed set for right-to-left matching
- i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
- while ( i-- ) {
- token = tokens[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Fetch a seed set for right-to-left matching
+ i = matchExpr["needsContext"].test(selector) ? 0 : tokens.length;
+ while (i--) {
+ token = tokens[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Abort if we hit a combinator
- if ( Expr.relative[ (type = token.type) ] ) {
- break;
- }
- if ( (find = Expr.find[ type ]) ) {
- // Search, expanding context for leading sibling combinators
- if ( (seed = find(
- token.matches[0].replace( runescape, funescape ),
- rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
- )) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Abort if we hit a combinator
+ if (Expr.relative[(type = token.type)]) {
+ break;
+ }
+ if ((find = Expr.find[type])) {
+ // Search, expanding context for leading sibling combinators
+ if ((seed = find(
+ token.matches[0].replace(runescape, funescape),
+ rsibling.test(tokens[0].type) && testContext(context.parentNode) || context
+ ))) {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If seed is empty or no tokens remain, we can return early
- tokens.splice( i, 1 );
- selector = seed.length && toSelector( tokens );
- if ( !selector ) {
- push.apply( results, seed );
- return results;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If seed is empty or no tokens remain, we can return early
+ tokens.splice(i, 1);
+ selector = seed.length && toSelector(tokens);
+ if (!selector) {
+ push.apply(results, seed);
+ return results;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- break;
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ break;
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Compile and execute a filtering function if one is not provided
- // Provide `match` to avoid retokenization if we modified the selector above
- ( compiled || compile( selector, match ) )(
- seed,
- context,
- !documentIsHTML,
- results,
- rsibling.test( selector ) && testContext( context.parentNode ) || context
- );
- return results;
-};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Compile and execute a filtering function if one is not provided
+ // Provide `match` to avoid retokenization if we modified the selector above
+ (compiled || compile(selector, match))(
+ seed,
+ context,
+ !documentIsHTML,
+ results,
+ rsibling.test(selector) && testContext(context.parentNode) || context
+ );
+ return results;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// One-time assignments
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // One-time assignments
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Sort stability
-support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Sort stability
+ support.sortStable = expando.split("").sort(sortOrder).join("") === expando;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Support: Chrome 14-35+
-// Always assume duplicates if they aren't passed to the comparison function
-support.detectDuplicates = !!hasDuplicate;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Support: Chrome 14-35+
+ // Always assume duplicates if they aren't passed to the comparison function
+ support.detectDuplicates = !!hasDuplicate;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Initialize against the default document
-setDocument();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Initialize against the default document
+ setDocument();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
-// Detached nodes confoundingly follow *each other*
-support.sortDetached = assert(function( div1 ) {
- // Should return 1, but returns 4 (following)
- return div1.compareDocumentPosition( document.createElement("div") ) & 1;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
+ // Detached nodes confoundingly follow *each other*
+ support.sortDetached = assert(function (div1) {
+ // Should return 1, but returns 4 (following)
+ return div1.compareDocumentPosition(document.createElement("div")) & 1;
+ }
+ );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Support: IE<8
-// Prevent attribute/property "interpolation"
-// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
-if ( !assert(function( div ) {
- div.innerHTML = "<a href='#'></a>";
- return div.firstChild.getAttribute("href") === "#" ;
-}) ) {
- addHandle( "type|href|height|width", function( elem, name, isXML ) {
- if ( !isXML ) {
- return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
- }
- });
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Support: IE<8
+ // Prevent attribute/property "interpolation"
+ // http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+ if (!assert(function (div) {
+ div.innerHTML = "<a href='#'></a>";
+ return div.firstChild.getAttribute("href") === "#";
+ })) {
+ addHandle("type|href|height|width", function (elem, name, isXML) {
+ if (!isXML) {
+ return elem.getAttribute(name, name.toLowerCase() === "type" ? 1 : 2);
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Support: IE<9
-// Use defaultValue in place of getAttribute("value")
-if ( !support.attributes || !assert(function( div ) {
- div.innerHTML = "<input/>";
- div.firstChild.setAttribute( "value", "" );
- return div.firstChild.getAttribute( "value" ) === "";
-}) ) {
- addHandle( "value", function( elem, name, isXML ) {
- if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
- return elem.defaultValue;
- }
- });
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Support: IE<9
+ // Use defaultValue in place of getAttribute("value")
+ if (!support.attributes || !assert(function (div) {
+ div.innerHTML = "<input/>";
+ div.firstChild.setAttribute("value", "");
+ return div.firstChild.getAttribute("value") === "";
+ })) {
+ addHandle("value", function (elem, name, isXML) {
+ if (!isXML && elem.nodeName.toLowerCase() === "input") {
+ return elem.defaultValue;
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Support: IE<9
-// Use getAttributeNode to fetch booleans when getAttribute lies
-if ( !assert(function( div ) {
- return div.getAttribute("disabled") == null;
-}) ) {
- addHandle( booleans, function( elem, name, isXML ) {
- var val;
- if ( !isXML ) {
- return elem[ name ] === true ? name.toLowerCase() :
- (val = elem.getAttributeNode( name )) && val.specified ?
- val.value :
- null;
- }
- });
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Support: IE<9
+ // Use getAttributeNode to fetch booleans when getAttribute lies
+ if (!assert(function (div) {
+ return div.getAttribute("disabled") == null;
+ })) {
+ addHandle(booleans, function (elem, name, isXML) {
+ var val;
+ if (!isXML) {
+ return elem[name] === true ? name.toLowerCase() :
+ (val = elem.getAttributeNode(name)) && val.specified ?
+ val.value :
+ null;
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// EXPOSE
-return Sizzle;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // EXPOSE
+ return Sizzle;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /*eslint-enable */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/util/Arr.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Arr.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3582,151 +3587,153 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.util.Arr
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/util/Arr", [], function() {
- var isArray = Array.isArray || function(obj) {
- return Object.prototype.toString.call(obj) === "[object Array]";
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.Arr',
+ [
+ ],
+ function () {
+ var isArray = Array.isArray || function (obj) {
+ return Object.prototype.toString.call(obj) === "[object Array]";
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function toArray(obj) {
- var array = obj, i, l;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function toArray(obj) {
+ var array = obj, i, l;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isArray(obj)) {
- array = [];
- for (i = 0, l = obj.length; i < l; i++) {
- array[i] = obj[i];
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isArray(obj)) {
+ array = [];
+ for (i = 0, l = obj.length; i < l; i++) {
+ array[i] = obj[i];
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return array;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return array;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function each(o, cb, s) {
- var n, l;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function each(o, cb, s) {
+ var n, l;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!o) {
- return 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!o) {
+ return 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- s = s || o;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ s = s || o;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (o.length !== undefined) {
- // Indexed arrays, needed for Safari
- for (n = 0, l = o.length; n < l; n++) {
- if (cb.call(s, o[n], n, o) === false) {
- return 0;
- }
- }
- } else {
- // Hashtables
- for (n in o) {
- if (o.hasOwnProperty(n)) {
- if (cb.call(s, o[n], n, o) === false) {
- return 0;
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (o.length !== undefined) {
+ // Indexed arrays, needed for Safari
+ for (n = 0, l = o.length; n < l; n++) {
+ if (cb.call(s, o[n], n, o) === false) {
+ return 0;
+ }
+ }
+ } else {
+ // Hashtables
+ for (n in o) {
+ if (o.hasOwnProperty(n)) {
+ if (cb.call(s, o[n], n, o) === false) {
+ return 0;
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return 1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return 1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function map(array, callback) {
- var out = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function map(array, callback) {
+ var out = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(array, function(item, index) {
- out.push(callback(item, index, array));
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(array, function (item, index) {
+ out.push(callback(item, index, array));
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return out;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return out;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function filter(a, f) {
- var o = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function filter(a, f) {
+ var o = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(a, function(v, index) {
- if (!f || f(v, index, a)) {
- o.push(v);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(a, function (v, index) {
+ if (!f || f(v, index, a)) {
+ o.push(v);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return o;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return o;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function indexOf(a, v) {
- var i, l;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function indexOf(a, v) {
+ var i, l;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (a) {
- for (i = 0, l = a.length; i < l; i++) {
- if (a[i] === v) {
- return i;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (a) {
+ for (i = 0, l = a.length; i < l; i++) {
+ if (a[i] === v) {
+ return i;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return -1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return -1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function reduce(collection, iteratee, accumulator, thisArg) {
- var i = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function reduce(collection, iteratee, accumulator, thisArg) {
+ var i = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (arguments.length < 3) {
- accumulator = collection[0];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (arguments.length < 3) {
+ accumulator = collection[0];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (; i < collection.length; i++) {
- accumulator = iteratee.call(thisArg, accumulator, collection[i], i);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (; i < collection.length; i++) {
+ accumulator = iteratee.call(thisArg, accumulator, collection[i], i);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return accumulator;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return accumulator;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function findIndex(array, predicate, thisArg) {
- var i, l;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function findIndex(array, predicate, thisArg) {
+ var i, l;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0, l = array.length; i < l; i++) {
- if (predicate.call(thisArg, array[i], i, array)) {
- return i;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0, l = array.length; i < l; i++) {
+ if (predicate.call(thisArg, array[i], i, array)) {
+ return i;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return -1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return -1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function find(array, predicate, thisArg) {
- var idx = findIndex(array, predicate, thisArg);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function find(array, predicate, thisArg) {
+ var idx = findIndex(array, predicate, thisArg);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (idx !== -1) {
- return array[idx];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (idx !== -1) {
+ return array[idx];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return undefined;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return undefined;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function last(collection) {
- return collection[collection.length - 1];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function last(collection) {
+ return collection[collection.length - 1];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- isArray: isArray,
- toArray: toArray,
- each: each,
- map: map,
- filter: filter,
- indexOf: indexOf,
- reduce: reduce,
- findIndex: findIndex,
- find: find,
- last: last
- };
-});
-
-// Included from: js/tinymce/classes/util/Tools.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ isArray: isArray,
+ toArray: toArray,
+ each: each,
+ map: map,
+ filter: filter,
+ indexOf: indexOf,
+ reduce: reduce,
+ findIndex: findIndex,
+ find: find,
+ last: last
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Tools.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3738,455 +3745,456 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.util.Tools
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/util/Tools", [
- "tinymce/Env",
- "tinymce/util/Arr"
-], function(Env, Arr) {
- /**
- * Removes whitespace from the beginning and end of a string.
- *
- * @method trim
- * @param {String} s String to remove whitespace from.
- * @return {String} New string with removed whitespace.
- */
- var whiteSpaceRegExp = /^\s*|\s*$/g;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.Tools',
+ [
+ "tinymce.core.Env",
+ "tinymce.core.util.Arr"
+ ],
+ function (Env, Arr) {
+ /**
+ * Removes whitespace from the beginning and end of a string.
+ *
+ * @method trim
+ * @param {String} s String to remove whitespace from.
+ * @return {String} New string with removed whitespace.
+ */
+ var whiteSpaceRegExp = /^\s*|\s*$/g;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function trim(str) {
- return (str === null || str === undefined) ? '' : ("" + str).replace(whiteSpaceRegExp, '');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function trim(str) {
+ return (str === null || str === undefined) ? '' : ("" + str).replace(whiteSpaceRegExp, '');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Checks if a object is of a specific type for example an array.
- *
- * @method is
- * @param {Object} obj Object to check type of.
- * @param {string} type Optional type to check for.
- * @return {Boolean} true/false if the object is of the specified type.
- */
- function is(obj, type) {
- if (!type) {
- return obj !== undefined;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Checks if a object is of a specific type for example an array.
+ *
+ * @method is
+ * @param {Object} obj Object to check type of.
+ * @param {string} type Optional type to check for.
+ * @return {Boolean} true/false if the object is of the specified type.
+ */
+ function is(obj, type) {
+ if (!type) {
+ return obj !== undefined;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (type == 'array' && Arr.isArray(obj)) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (type == 'array' && Arr.isArray(obj)) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return typeof obj == type;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return typeof obj == type;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Makes a name/object map out of an array with names.
- *
- * @method makeMap
- * @param {Array/String} items Items to make map out of.
- * @param {String} delim Optional delimiter to split string by.
- * @param {Object} map Optional map to add items to.
- * @return {Object} Name/value map of items.
- */
- function makeMap(items, delim, map) {
- var i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Makes a name/object map out of an array with names.
+ *
+ * @method makeMap
+ * @param {Array/String} items Items to make map out of.
+ * @param {String} delim Optional delimiter to split string by.
+ * @param {Object} map Optional map to add items to.
+ * @return {Object} Name/value map of items.
+ */
+ function makeMap(items, delim, map) {
+ var i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- items = items || [];
- delim = delim || ',';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ items = items || [];
+ delim = delim || ',';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof items == "string") {
- items = items.split(delim);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof items == "string") {
+ items = items.split(delim);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- map = map || {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ map = map || {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- i = items.length;
- while (i--) {
- map[items[i]] = {};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ i = items.length;
+ while (i--) {
+ map[items[i]] = {};
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return map;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return map;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * JavaScript does not protect hasOwnProperty method, so it is possible to overwrite it. This is
- * object independent version.
- *
- * @param {Object} obj
- * @param {String} prop
- * @returns {Boolean}
- */
- function hasOwnProperty(obj, prop) {
- return Object.prototype.hasOwnProperty.call(obj, prop);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * JavaScript does not protect hasOwnProperty method, so it is possible to overwrite it. This is
+ * object independent version.
+ *
+ * @param {Object} obj
+ * @param {String} prop
+ * @returns {Boolean}
+ */
+ function hasOwnProperty(obj, prop) {
+ return Object.prototype.hasOwnProperty.call(obj, prop);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates a class, subclass or static singleton.
- * More details on this method can be found in the Wiki.
- *
- * @method create
- * @param {String} s Class name, inheritance and prefix.
- * @param {Object} p Collection of methods to add to the class.
- * @param {Object} root Optional root object defaults to the global window object.
- * @example
- * // Creates a basic class
- * tinymce.create('tinymce.somepackage.SomeClass', {
- * SomeClass: function() {
- * // Class constructor
- * },
- *
- * method: function() {
- * // Some method
- * }
- * });
- *
- * // Creates a basic subclass class
- * tinymce.create('tinymce.somepackage.SomeSubClass:tinymce.somepackage.SomeClass', {
- * SomeSubClass: function() {
- * // Class constructor
- * this.parent(); // Call parent constructor
- * },
- *
- * method: function() {
- * // Some method
- * this.parent(); // Call parent method
- * },
- *
- * 'static': {
- * staticMethod: function() {
- * // Static method
- * }
- * }
- * });
- *
- * // Creates a singleton/static class
- * tinymce.create('static tinymce.somepackage.SomeSingletonClass', {
- * method: function() {
- * // Some method
- * }
- * });
- */
- function create(s, p, root) {
- var self = this, sp, ns, cn, scn, c, de = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates a class, subclass or static singleton.
+ * More details on this method can be found in the Wiki.
+ *
+ * @method create
+ * @param {String} s Class name, inheritance and prefix.
+ * @param {Object} p Collection of methods to add to the class.
+ * @param {Object} root Optional root object defaults to the global window object.
+ * @example
+ * // Creates a basic class
+ * tinymce.create('tinymce.somepackage.SomeClass', {
+ * SomeClass: function() {
+ * // Class constructor
+ * },
+ *
+ * method: function() {
+ * // Some method
+ * }
+ * });
+ *
+ * // Creates a basic subclass class
+ * tinymce.create('tinymce.somepackage.SomeSubClass:tinymce.somepackage.SomeClass', {
+ * SomeSubClass: function() {
+ * // Class constructor
+ * this.parent(); // Call parent constructor
+ * },
+ *
+ * method: function() {
+ * // Some method
+ * this.parent(); // Call parent method
+ * },
+ *
+ * 'static': {
+ * staticMethod: function() {
+ * // Static method
+ * }
+ * }
+ * });
+ *
+ * // Creates a singleton/static class
+ * tinymce.create('static tinymce.somepackage.SomeSingletonClass', {
+ * method: function() {
+ * // Some method
+ * }
+ * });
+ */
+ function create(s, p, root) {
+ var self = this, sp, ns, cn, scn, c, de = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Parse : <prefix> <class>:<super class>
- s = /^((static) )?([\w.]+)(:([\w.]+))?/.exec(s);
- cn = s[3].match(/(^|\.)(\w+)$/i)[2]; // Class name
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Parse : <prefix> <class>:<super class>
+ s = /^((static) )?([\w.]+)(:([\w.]+))?/.exec(s);
+ cn = s[3].match(/(^|\.)(\w+)$/i)[2]; // Class name
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Create namespace for new class
- ns = self.createNS(s[3].replace(/\.\w+$/, ''), root);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Create namespace for new class
+ ns = self.createNS(s[3].replace(/\.\w+$/, ''), root);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Class already exists
- if (ns[cn]) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Class already exists
+ if (ns[cn]) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Make pure static class
- if (s[2] == 'static') {
- ns[cn] = p;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Make pure static class
+ if (s[2] == 'static') {
+ ns[cn] = p;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.onCreate) {
- this.onCreate(s[2], s[3], ns[cn]);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.onCreate) {
+ this.onCreate(s[2], s[3], ns[cn]);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Create default constructor
- if (!p[cn]) {
- p[cn] = function() {};
- de = 1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Create default constructor
+ if (!p[cn]) {
+ p[cn] = function () { };
+ de = 1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add constructor and methods
- ns[cn] = p[cn];
- self.extend(ns[cn].prototype, p);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add constructor and methods
+ ns[cn] = p[cn];
+ self.extend(ns[cn].prototype, p);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Extend
- if (s[5]) {
- sp = self.resolve(s[5]).prototype;
- scn = s[5].match(/\.(\w+)$/i)[1]; // Class name
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Extend
+ if (s[5]) {
+ sp = self.resolve(s[5]).prototype;
+ scn = s[5].match(/\.(\w+)$/i)[1]; // Class name
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Extend constructor
- c = ns[cn];
- if (de) {
- // Add passthrough constructor
- ns[cn] = function() {
- return sp[scn].apply(this, arguments);
- };
- } else {
- // Add inherit constructor
- ns[cn] = function() {
- this.parent = sp[scn];
- return c.apply(this, arguments);
- };
- }
- ns[cn].prototype[cn] = ns[cn];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Extend constructor
+ c = ns[cn];
+ if (de) {
+ // Add passthrough constructor
+ ns[cn] = function () {
+ return sp[scn].apply(this, arguments);
+ };
+ } else {
+ // Add inherit constructor
+ ns[cn] = function () {
+ this.parent = sp[scn];
+ return c.apply(this, arguments);
+ };
+ }
+ ns[cn].prototype[cn] = ns[cn];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add super methods
- self.each(sp, function(f, n) {
- ns[cn].prototype[n] = sp[n];
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add super methods
+ self.each(sp, function (f, n) {
+ ns[cn].prototype[n] = sp[n];
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add overridden methods
- self.each(p, function(f, n) {
- // Extend methods if needed
- if (sp[n]) {
- ns[cn].prototype[n] = function() {
- this.parent = sp[n];
- return f.apply(this, arguments);
- };
- } else {
- if (n != cn) {
- ns[cn].prototype[n] = f;
- }
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add overridden methods
+ self.each(p, function (f, n) {
+ // Extend methods if needed
+ if (sp[n]) {
+ ns[cn].prototype[n] = function () {
+ this.parent = sp[n];
+ return f.apply(this, arguments);
+ };
+ } else {
+ if (n != cn) {
+ ns[cn].prototype[n] = f;
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add static methods
- /*jshint sub:true*/
- /*eslint dot-notation:0*/
- self.each(p['static'], function(f, n) {
- ns[cn][n] = f;
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add static methods
+ /*jshint sub:true*/
+ /*eslint dot-notation:0*/
+ self.each(p['static'], function (f, n) {
+ ns[cn][n] = f;
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function extend(obj, ext) {
- var i, l, name, args = arguments, value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function extend(obj, ext) {
+ var i, l, name, args = arguments, value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 1, l = args.length; i < l; i++) {
- ext = args[i];
- for (name in ext) {
- if (ext.hasOwnProperty(name)) {
- value = ext[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 1, l = args.length; i < l; i++) {
+ ext = args[i];
+ for (name in ext) {
+ if (ext.hasOwnProperty(name)) {
+ value = ext[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value !== undefined) {
- obj[name] = value;
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value !== undefined) {
+ obj[name] = value;
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return obj;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return obj;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Executed the specified function for each item in a object tree.
- *
- * @method walk
- * @param {Object} o Object tree to walk though.
- * @param {function} f Function to call for each item.
- * @param {String} n Optional name of collection inside the objects to walk for example childNodes.
- * @param {String} s Optional scope to execute the function in.
- */
- function walk(o, f, n, s) {
- s = s || this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Executed the specified function for each item in a object tree.
+ *
+ * @method walk
+ * @param {Object} o Object tree to walk though.
+ * @param {function} f Function to call for each item.
+ * @param {String} n Optional name of collection inside the objects to walk for example childNodes.
+ * @param {String} s Optional scope to execute the function in.
+ */
+ function walk(o, f, n, s) {
+ s = s || this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (o) {
- if (n) {
- o = o[n];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (o) {
+ if (n) {
+ o = o[n];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Arr.each(o, function(o, i) {
- if (f.call(s, o, i, n) === false) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Arr.each(o, function (o, i) {
+ if (f.call(s, o, i, n) === false) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- walk(o, f, n, s);
- });
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ walk(o, f, n, s);
+ });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates a namespace on a specific object.
- *
- * @method createNS
- * @param {String} n Namespace to create for example a.b.c.d.
- * @param {Object} o Optional object to add namespace to, defaults to window.
- * @return {Object} New namespace object the last item in path.
- * @example
- * // Create some namespace
- * tinymce.createNS('tinymce.somepackage.subpackage');
- *
- * // Add a singleton
- * var tinymce.somepackage.subpackage.SomeSingleton = {
- * method: function() {
- * // Some method
- * }
- * };
- */
- function createNS(n, o) {
- var i, v;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates a namespace on a specific object.
+ *
+ * @method createNS
+ * @param {String} n Namespace to create for example a.b.c.d.
+ * @param {Object} o Optional object to add namespace to, defaults to window.
+ * @return {Object} New namespace object the last item in path.
+ * @example
+ * // Create some namespace
+ * tinymce.createNS('tinymce.somepackage.subpackage');
+ *
+ * // Add a singleton
+ * var tinymce.somepackage.subpackage.SomeSingleton = {
+ * method: function() {
+ * // Some method
+ * }
+ * };
+ */
+ function createNS(n, o) {
+ var i, v;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- o = o || window;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ o = o || window;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- n = n.split('.');
- for (i = 0; i < n.length; i++) {
- v = n[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ n = n.split('.');
+ for (i = 0; i < n.length; i++) {
+ v = n[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!o[v]) {
- o[v] = {};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!o[v]) {
+ o[v] = {};
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- o = o[v];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ o = o[v];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return o;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return o;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Resolves a string and returns the object from a specific structure.
- *
- * @method resolve
- * @param {String} n Path to resolve for example a.b.c.d.
- * @param {Object} o Optional object to search though, defaults to window.
- * @return {Object} Last object in path or null if it couldn't be resolved.
- * @example
- * // Resolve a path into an object reference
- * var obj = tinymce.resolve('a.b.c.d');
- */
- function resolve(n, o) {
- var i, l;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Resolves a string and returns the object from a specific structure.
+ *
+ * @method resolve
+ * @param {String} n Path to resolve for example a.b.c.d.
+ * @param {Object} o Optional object to search though, defaults to window.
+ * @return {Object} Last object in path or null if it couldn't be resolved.
+ * @example
+ * // Resolve a path into an object reference
+ * var obj = tinymce.resolve('a.b.c.d');
+ */
+ function resolve(n, o) {
+ var i, l;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- o = o || window;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ o = o || window;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- n = n.split('.');
- for (i = 0, l = n.length; i < l; i++) {
- o = o[n[i]];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ n = n.split('.');
+ for (i = 0, l = n.length; i < l; i++) {
+ o = o[n[i]];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!o) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!o) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return o;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return o;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Splits a string but removes the whitespace before and after each value.
- *
- * @method explode
- * @param {string} s String to split.
- * @param {string} d Delimiter to split by.
- * @example
- * // Split a string into an array with a,b,c
- * var arr = tinymce.explode('a, b, c');
- */
- function explode(s, d) {
- if (!s || is(s, 'array')) {
- return s;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Splits a string but removes the whitespace before and after each value.
+ *
+ * @method explode
+ * @param {string} s String to split.
+ * @param {string} d Delimiter to split by.
+ * @example
+ * // Split a string into an array with a,b,c
+ * var arr = tinymce.explode('a, b, c');
+ */
+ function explode(s, d) {
+ if (!s || is(s, 'array')) {
+ return s;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Arr.map(s.split(d || ','), trim);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Arr.map(s.split(d || ','), trim);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function _addCacheSuffix(url) {
- var cacheSuffix = Env.cacheSuffix;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function _addCacheSuffix(url) {
+ var cacheSuffix = Env.cacheSuffix;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (cacheSuffix) {
- url += (url.indexOf('?') === -1 ? '?' : '&') + cacheSuffix;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (cacheSuffix) {
+ url += (url.indexOf('?') === -1 ? '?' : '&') + cacheSuffix;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return url;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return url;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- trim: trim,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ trim: trim,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the object is an array or not.
- *
- * @method isArray
- * @param {Object} obj Object to check.
- * @return {boolean} true/false state if the object is an array or not.
- */
- isArray: Arr.isArray,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the object is an array or not.
+ *
+ * @method isArray
+ * @param {Object} obj Object to check.
+ * @return {boolean} true/false state if the object is an array or not.
+ */
+ isArray: Arr.isArray,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- is: is,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ is: is,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Converts the specified object into a real JavaScript array.
- *
- * @method toArray
- * @param {Object} obj Object to convert into array.
- * @return {Array} Array object based in input.
- */
- toArray: Arr.toArray,
- makeMap: makeMap,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Converts the specified object into a real JavaScript array.
+ *
+ * @method toArray
+ * @param {Object} obj Object to convert into array.
+ * @return {Array} Array object based in input.
+ */
+ toArray: Arr.toArray,
+ makeMap: makeMap,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Performs an iteration of all items in a collection such as an object or array. This method will execure the
- * callback function for each item in the collection, if the callback returns false the iteration will terminate.
- * The callback has the following format: cb(value, key_or_index).
- *
- * @method each
- * @param {Object} o Collection to iterate.
- * @param {function} cb Callback function to execute for each item.
- * @param {Object} s Optional scope to execute the callback in.
- * @example
- * // Iterate an array
- * tinymce.each([1,2,3], function(v, i) {
- * console.debug("Value: " + v + ", Index: " + i);
- * });
- *
- * // Iterate an object
- * tinymce.each({a: 1, b: 2, c: 3], function(v, k) {
- * console.debug("Value: " + v + ", Key: " + k);
- * });
- */
- each: Arr.each,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Performs an iteration of all items in a collection such as an object or array. This method will execure the
+ * callback function for each item in the collection, if the callback returns false the iteration will terminate.
+ * The callback has the following format: cb(value, key_or_index).
+ *
+ * @method each
+ * @param {Object} o Collection to iterate.
+ * @param {function} cb Callback function to execute for each item.
+ * @param {Object} s Optional scope to execute the callback in.
+ * @example
+ * // Iterate an array
+ * tinymce.each([1,2,3], function(v, i) {
+ * console.debug("Value: " + v + ", Index: " + i);
+ * });
+ *
+ * // Iterate an object
+ * tinymce.each({a: 1, b: 2, c: 3], function(v, k) {
+ * console.debug("Value: " + v + ", Key: " + k);
+ * });
+ */
+ each: Arr.each,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates a new array by the return value of each iteration function call. This enables you to convert
- * one array list into another.
- *
- * @method map
- * @param {Array} array Array of items to iterate.
- * @param {function} callback Function to call for each item. It's return value will be the new value.
- * @return {Array} Array with new values based on function return values.
- */
- map: Arr.map,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates a new array by the return value of each iteration function call. This enables you to convert
+ * one array list into another.
+ *
+ * @method map
+ * @param {Array} array Array of items to iterate.
+ * @param {function} callback Function to call for each item. It's return value will be the new value.
+ * @return {Array} Array with new values based on function return values.
+ */
+ map: Arr.map,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Filters out items from the input array by calling the specified function for each item.
- * If the function returns false the item will be excluded if it returns true it will be included.
- *
- * @method grep
- * @param {Array} a Array of items to loop though.
- * @param {function} f Function to call for each item. Include/exclude depends on it's return value.
- * @return {Array} New array with values imported and filtered based in input.
- * @example
- * // Filter out some items, this will return an array with 4 and 5
- * var items = tinymce.grep([1,2,3,4,5], function(v) {return v > 3;});
- */
- grep: Arr.filter,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Filters out items from the input array by calling the specified function for each item.
+ * If the function returns false the item will be excluded if it returns true it will be included.
+ *
+ * @method grep
+ * @param {Array} a Array of items to loop though.
+ * @param {function} f Function to call for each item. Include/exclude depends on it's return value.
+ * @return {Array} New array with values imported and filtered based in input.
+ * @example
+ * // Filter out some items, this will return an array with 4 and 5
+ * var items = tinymce.grep([1,2,3,4,5], function(v) {return v > 3;});
+ */
+ grep: Arr.filter,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns an index of the item or -1 if item is not present in the array.
- *
- * @method inArray
- * @param {any} item Item to search for.
- * @param {Array} arr Array to search in.
- * @return {Number} index of the item or -1 if item was not found.
- */
- inArray: Arr.indexOf,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns an index of the item or -1 if item is not present in the array.
+ *
+ * @method inArray
+ * @param {any} item Item to search for.
+ * @param {Array} arr Array to search in.
+ * @return {Number} index of the item or -1 if item was not found.
+ */
+ inArray: Arr.indexOf,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- hasOwn: hasOwnProperty,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ hasOwn: hasOwnProperty,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- extend: extend,
- create: create,
- walk: walk,
- createNS: createNS,
- resolve: resolve,
- explode: explode,
- _addCacheSuffix: _addCacheSuffix
- };
-});
-
-// Included from: js/tinymce/classes/dom/DomQuery.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ extend: extend,
+ create: create,
+ walk: walk,
+ createNS: createNS,
+ resolve: resolve,
+ explode: explode,
+ _addCacheSuffix: _addCacheSuffix
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * DomQuery.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -4213,1561 +4221,1563 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.dom.DomQuery
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/dom/DomQuery", [
- "tinymce/dom/EventUtils",
- "tinymce/dom/Sizzle",
- "tinymce/util/Tools",
- "tinymce/Env"
-], function(EventUtils, Sizzle, Tools, Env) {
- var doc = document, push = Array.prototype.push, slice = Array.prototype.slice;
- var rquickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/;
- var Event = EventUtils.Event, undef;
- var skipUniques = Tools.makeMap('children,contents,next,prev');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.DomQuery',
+ [
+ "tinymce.core.dom.EventUtils",
+ "tinymce.core.dom.Sizzle",
+ "tinymce.core.util.Tools",
+ "tinymce.core.Env"
+ ],
+ function (EventUtils, Sizzle, Tools, Env) {
+ var doc = document, push = Array.prototype.push, slice = Array.prototype.slice;
+ var rquickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/;
+ var Event = EventUtils.Event, undef;
+ var skipUniques = Tools.makeMap('children,contents,next,prev');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isDefined(obj) {
- return typeof obj !== 'undefined';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isDefined(obj) {
+ return typeof obj !== 'undefined';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isString(obj) {
- return typeof obj === 'string';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isString(obj) {
+ return typeof obj === 'string';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isWindow(obj) {
- return obj && obj == obj.window;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isWindow(obj) {
+ return obj && obj == obj.window;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function createFragment(html, fragDoc) {
- var frag, node, container;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function createFragment(html, fragDoc) {
+ var frag, node, container;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- fragDoc = fragDoc || doc;
- container = fragDoc.createElement('div');
- frag = fragDoc.createDocumentFragment();
- container.innerHTML = html;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ fragDoc = fragDoc || doc;
+ container = fragDoc.createElement('div');
+ frag = fragDoc.createDocumentFragment();
+ container.innerHTML = html;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while ((node = container.firstChild)) {
- frag.appendChild(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while ((node = container.firstChild)) {
+ frag.appendChild(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return frag;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return frag;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function domManipulate(targetNodes, sourceItem, callback, reverse) {
- var i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function domManipulate(targetNodes, sourceItem, callback, reverse) {
+ var i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isString(sourceItem)) {
- sourceItem = createFragment(sourceItem, getElementDocument(targetNodes[0]));
- } else if (sourceItem.length && !sourceItem.nodeType) {
- sourceItem = DomQuery.makeArray(sourceItem);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isString(sourceItem)) {
+ sourceItem = createFragment(sourceItem, getElementDocument(targetNodes[0]));
+ } else if (sourceItem.length && !sourceItem.nodeType) {
+ sourceItem = DomQuery.makeArray(sourceItem);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (reverse) {
- for (i = sourceItem.length - 1; i >= 0; i--) {
- domManipulate(targetNodes, sourceItem[i], callback, reverse);
- }
- } else {
- for (i = 0; i < sourceItem.length; i++) {
- domManipulate(targetNodes, sourceItem[i], callback, reverse);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (reverse) {
+ for (i = sourceItem.length - 1; i >= 0; i--) {
+ domManipulate(targetNodes, sourceItem[i], callback, reverse);
+ }
+ } else {
+ for (i = 0; i < sourceItem.length; i++) {
+ domManipulate(targetNodes, sourceItem[i], callback, reverse);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return targetNodes;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return targetNodes;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (sourceItem.nodeType) {
- i = targetNodes.length;
- while (i--) {
- callback.call(targetNodes[i], sourceItem);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (sourceItem.nodeType) {
+ i = targetNodes.length;
+ while (i--) {
+ callback.call(targetNodes[i], sourceItem);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return targetNodes;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return targetNodes;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hasClass(node, className) {
- return node && className && (' ' + node.className + ' ').indexOf(' ' + className + ' ') !== -1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hasClass(node, className) {
+ return node && className && (' ' + node.className + ' ').indexOf(' ' + className + ' ') !== -1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function wrap(elements, wrapper, all) {
- var lastParent, newWrapper;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function wrap(elements, wrapper, all) {
+ var lastParent, newWrapper;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- wrapper = DomQuery(wrapper)[0];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ wrapper = DomQuery(wrapper)[0];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elements.each(function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elements.each(function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!all || lastParent != self.parentNode) {
- lastParent = self.parentNode;
- newWrapper = wrapper.cloneNode(false);
- self.parentNode.insertBefore(newWrapper, self);
- newWrapper.appendChild(self);
- } else {
- newWrapper.appendChild(self);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!all || lastParent != self.parentNode) {
+ lastParent = self.parentNode;
+ newWrapper = wrapper.cloneNode(false);
+ self.parentNode.insertBefore(newWrapper, self);
+ newWrapper.appendChild(self);
+ } else {
+ newWrapper.appendChild(self);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return elements;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return elements;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var numericCssMap = Tools.makeMap('fillOpacity fontWeight lineHeight opacity orphans widows zIndex zoom', ' ');
- var booleanMap = Tools.makeMap('checked compact declare defer disabled ismap multiple nohref noshade nowrap readonly selected', ' ');
- var propFix = {
- 'for': 'htmlFor',
- 'class': 'className',
- 'readonly': 'readOnly'
- };
- var cssFix = {
- 'float': 'cssFloat'
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var numericCssMap = Tools.makeMap('fillOpacity fontWeight lineHeight opacity orphans widows zIndex zoom', ' ');
+ var booleanMap = Tools.makeMap('checked compact declare defer disabled ismap multiple nohref noshade nowrap readonly selected', ' ');
+ var propFix = {
+ 'for': 'htmlFor',
+ 'class': 'className',
+ 'readonly': 'readOnly'
+ };
+ var cssFix = {
+ 'float': 'cssFloat'
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var attrHooks = {}, cssHooks = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var attrHooks = {}, cssHooks = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function DomQuery(selector, context) {
- /*eslint new-cap:0 */
- return new DomQuery.fn.init(selector, context);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function DomQuery(selector, context) {
+ /*eslint new-cap:0 */
+ return new DomQuery.fn.init(selector, context);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function inArray(item, array) {
- var i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function inArray(item, array) {
+ var i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (array.indexOf) {
- return array.indexOf(item);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (array.indexOf) {
+ return array.indexOf(item);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- i = array.length;
- while (i--) {
- if (array[i] === item) {
- return i;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ i = array.length;
+ while (i--) {
+ if (array[i] === item) {
+ return i;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return -1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return -1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var whiteSpaceRegExp = /^\s*|\s*$/g;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var whiteSpaceRegExp = /^\s*|\s*$/g;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function trim(str) {
- return (str === null || str === undef) ? '' : ("" + str).replace(whiteSpaceRegExp, '');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function trim(str) {
+ return (str === null || str === undef) ? '' : ("" + str).replace(whiteSpaceRegExp, '');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function each(obj, callback) {
- var length, key, i, undef, value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function each(obj, callback) {
+ var length, key, i, undef, value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (obj) {
- length = obj.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (obj) {
+ length = obj.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (length === undef) {
- // Loop object items
- for (key in obj) {
- if (obj.hasOwnProperty(key)) {
- value = obj[key];
- if (callback.call(value, key, value) === false) {
- break;
- }
- }
- }
- } else {
- // Loop array items
- for (i = 0; i < length; i++) {
- value = obj[i];
- if (callback.call(value, i, value) === false) {
- break;
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (length === undef) {
+ // Loop object items
+ for (key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ value = obj[key];
+ if (callback.call(value, key, value) === false) {
+ break;
+ }
+ }
+ }
+ } else {
+ // Loop array items
+ for (i = 0; i < length; i++) {
+ value = obj[i];
+ if (callback.call(value, i, value) === false) {
+ break;
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return obj;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return obj;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function grep(array, callback) {
- var out = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function grep(array, callback) {
+ var out = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(array, function(i, item) {
- if (callback(item, i)) {
- out.push(item);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(array, function (i, item) {
+ if (callback(item, i)) {
+ out.push(item);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return out;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return out;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getElementDocument(element) {
- if (!element) {
- return doc;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getElementDocument(element) {
+ if (!element) {
+ return doc;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (element.nodeType == 9) {
- return element;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (element.nodeType == 9) {
+ return element;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return element.ownerDocument;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return element.ownerDocument;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DomQuery.fn = DomQuery.prototype = {
- constructor: DomQuery,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DomQuery.fn = DomQuery.prototype = {
+ constructor: DomQuery,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Selector for the current set.
- *
- * @property selector
- * @type String
- */
- selector: "",
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Selector for the current set.
+ *
+ * @property selector
+ * @type String
+ */
+ selector: "",
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Context used to create the set.
- *
- * @property context
- * @type Element
- */
- context: null,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Context used to create the set.
+ *
+ * @property context
+ * @type Element
+ */
+ context: null,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Number of items in the current set.
- *
- * @property length
- * @type Number
- */
- length: 0,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Number of items in the current set.
+ *
+ * @property length
+ * @type Number
+ */
+ length: 0,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a new DomQuery instance with the specified selector or context.
- *
- * @constructor
- * @method init
- * @param {String/Array/DomQuery} selector Optional CSS selector/Array or array like object or HTML string.
- * @param {Document/Element} context Optional context to search in.
- */
- init: function(selector, context) {
- var self = this, match, node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a new DomQuery instance with the specified selector or context.
+ *
+ * @constructor
+ * @method init
+ * @param {String/Array/DomQuery} selector Optional CSS selector/Array or array like object or HTML string.
+ * @param {Document/Element} context Optional context to search in.
+ */
+ init: function (selector, context) {
+ var self = this, match, node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!selector) {
- return self;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!selector) {
+ return self;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (selector.nodeType) {
- self.context = self[0] = selector;
- self.length = 1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (selector.nodeType) {
+ self.context = self[0] = selector;
+ self.length = 1;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (context && context.nodeType) {
- self.context = context;
- } else {
- if (context) {
- return DomQuery(selector).attr(context);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (context && context.nodeType) {
+ self.context = context;
+ } else {
+ if (context) {
+ return DomQuery(selector).attr(context);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.context = context = document;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.context = context = document;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isString(selector)) {
- self.selector = selector;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isString(selector)) {
+ self.selector = selector;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (selector.charAt(0) === "<" && selector.charAt(selector.length - 1) === ">" && selector.length >= 3) {
- match = [null, selector, null];
- } else {
- match = rquickExpr.exec(selector);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (selector.charAt(0) === "<" && selector.charAt(selector.length - 1) === ">" && selector.length >= 3) {
+ match = [null, selector, null];
+ } else {
+ match = rquickExpr.exec(selector);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (match) {
- if (match[1]) {
- node = createFragment(selector, getElementDocument(context)).firstChild;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (match) {
+ if (match[1]) {
+ node = createFragment(selector, getElementDocument(context)).firstChild;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (node) {
- push.call(self, node);
- node = node.nextSibling;
- }
- } else {
- node = getElementDocument(context).getElementById(match[2]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (node) {
+ push.call(self, node);
+ node = node.nextSibling;
+ }
+ } else {
+ node = getElementDocument(context).getElementById(match[2]);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!node) {
- return self;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!node) {
+ return self;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.id !== match[2]) {
- return self.find(selector);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.id !== match[2]) {
+ return self.find(selector);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.length = 1;
- self[0] = node;
- }
- } else {
- return DomQuery(context).find(selector);
- }
- } else {
- this.add(selector, false);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.length = 1;
+ self[0] = node;
+ }
+ } else {
+ return DomQuery(context).find(selector);
+ }
+ } else {
+ this.add(selector, false);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Converts the current set to an array.
- *
- * @method toArray
- * @return {Array} Array of all nodes in set.
- */
- toArray: function() {
- return Tools.toArray(this);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Converts the current set to an array.
+ *
+ * @method toArray
+ * @return {Array} Array of all nodes in set.
+ */
+ toArray: function () {
+ return Tools.toArray(this);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds new nodes to the set.
- *
- * @method add
- * @param {Array/tinymce.dom.DomQuery} items Array of all nodes to add to set.
- * @param {Boolean} sort Optional sort flag that enables sorting of elements.
- * @return {tinymce.dom.DomQuery} New instance with nodes added.
- */
- add: function(items, sort) {
- var self = this, nodes, i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds new nodes to the set.
+ *
+ * @method add
+ * @param {Array/tinymce.core.dom.DomQuery} items Array of all nodes to add to set.
+ * @param {Boolean} sort Optional sort flag that enables sorting of elements.
+ * @return {tinymce.dom.DomQuery} New instance with nodes added.
+ */
+ add: function (items, sort) {
+ var self = this, nodes, i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isString(items)) {
- return self.add(DomQuery(items));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isString(items)) {
+ return self.add(DomQuery(items));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (sort !== false) {
- nodes = DomQuery.unique(self.toArray().concat(DomQuery.makeArray(items)));
- self.length = nodes.length;
- for (i = 0; i < nodes.length; i++) {
- self[i] = nodes[i];
- }
- } else {
- push.apply(self, DomQuery.makeArray(items));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (sort !== false) {
+ nodes = DomQuery.unique(self.toArray().concat(DomQuery.makeArray(items)));
+ self.length = nodes.length;
+ for (i = 0; i < nodes.length; i++) {
+ self[i] = nodes[i];
+ }
+ } else {
+ push.apply(self, DomQuery.makeArray(items));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets/gets attributes on the elements in the current set.
- *
- * @method attr
- * @param {String/Object} name Name of attribute to get or an object with attributes to set.
- * @param {String} value Optional value to set.
- * @return {tinymce.dom.DomQuery/String} Current set or the specified attribute when only the name is specified.
- */
- attr: function(name, value) {
- var self = this, hook;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets/gets attributes on the elements in the current set.
+ *
+ * @method attr
+ * @param {String/Object} name Name of attribute to get or an object with attributes to set.
+ * @param {String} value Optional value to set.
+ * @return {tinymce.dom.DomQuery/String} Current set or the specified attribute when only the name is specified.
+ */
+ attr: function (name, value) {
+ var self = this, hook;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof name === "object") {
- each(name, function(name, value) {
- self.attr(name, value);
- });
- } else if (isDefined(value)) {
- this.each(function() {
- var hook;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof name === "object") {
+ each(name, function (name, value) {
+ self.attr(name, value);
+ });
+ } else if (isDefined(value)) {
+ this.each(function () {
+ var hook;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.nodeType === 1) {
- hook = attrHooks[name];
- if (hook && hook.set) {
- hook.set(this, value);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.nodeType === 1) {
+ hook = attrHooks[name];
+ if (hook && hook.set) {
+ hook.set(this, value);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value === null) {
- this.removeAttribute(name, 2);
- } else {
- this.setAttribute(name, value, 2);
- }
- }
- });
- } else {
- if (self[0] && self[0].nodeType === 1) {
- hook = attrHooks[name];
- if (hook && hook.get) {
- return hook.get(self[0], name);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value === null) {
+ this.removeAttribute(name, 2);
+ } else {
+ this.setAttribute(name, value, 2);
+ }
+ }
+ });
+ } else {
+ if (self[0] && self[0].nodeType === 1) {
+ hook = attrHooks[name];
+ if (hook && hook.get) {
+ return hook.get(self[0], name);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (booleanMap[name]) {
- return self.prop(name) ? name : undef;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (booleanMap[name]) {
+ return self.prop(name) ? name : undef;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- value = self[0].getAttribute(name, 2);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ value = self[0].getAttribute(name, 2);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value === null) {
- value = undef;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value === null) {
+ value = undef;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return value;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return value;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes attributse on the elements in the current set.
- *
- * @method removeAttr
- * @param {String/Object} name Name of attribute to remove.
- * @return {tinymce.dom.DomQuery/String} Current set.
- */
- removeAttr: function(name) {
- return this.attr(name, null);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes attributse on the elements in the current set.
+ *
+ * @method removeAttr
+ * @param {String/Object} name Name of attribute to remove.
+ * @return {tinymce.dom.DomQuery/String} Current set.
+ */
+ removeAttr: function (name) {
+ return this.attr(name, null);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets/gets properties on the elements in the current set.
- *
- * @method attr
- * @param {String/Object} name Name of property to get or an object with properties to set.
- * @param {String} value Optional value to set.
- * @return {tinymce.dom.DomQuery/String} Current set or the specified property when only the name is specified.
- */
- prop: function(name, value) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets/gets properties on the elements in the current set.
+ *
+ * @method attr
+ * @param {String/Object} name Name of property to get or an object with properties to set.
+ * @param {String} value Optional value to set.
+ * @return {tinymce.dom.DomQuery/String} Current set or the specified property when only the name is specified.
+ */
+ prop: function (name, value) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- name = propFix[name] || name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ name = propFix[name] || name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof name === "object") {
- each(name, function(name, value) {
- self.prop(name, value);
- });
- } else if (isDefined(value)) {
- this.each(function() {
- if (this.nodeType == 1) {
- this[name] = value;
- }
- });
- } else {
- if (self[0] && self[0].nodeType && name in self[0]) {
- return self[0][name];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof name === "object") {
+ each(name, function (name, value) {
+ self.prop(name, value);
+ });
+ } else if (isDefined(value)) {
+ this.each(function () {
+ if (this.nodeType == 1) {
+ this[name] = value;
+ }
+ });
+ } else {
+ if (self[0] && self[0].nodeType && name in self[0]) {
+ return self[0][name];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return value;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return value;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets/gets styles on the elements in the current set.
- *
- * @method css
- * @param {String/Object} name Name of style to get or an object with styles to set.
- * @param {String} value Optional value to set.
- * @return {tinymce.dom.DomQuery/String} Current set or the specified style when only the name is specified.
- */
- css: function(name, value) {
- var self = this, elm, hook;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets/gets styles on the elements in the current set.
+ *
+ * @method css
+ * @param {String/Object} name Name of style to get or an object with styles to set.
+ * @param {String} value Optional value to set.
+ * @return {tinymce.dom.DomQuery/String} Current set or the specified style when only the name is specified.
+ */
+ css: function (name, value) {
+ var self = this, elm, hook;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function camel(name) {
- return name.replace(/-(\D)/g, function(a, b) {
- return b.toUpperCase();
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function camel(name) {
+ return name.replace(/-(\D)/g, function (a, b) {
+ return b.toUpperCase();
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function dashed(name) {
- return name.replace(/[A-Z]/g, function(a) {
- return '-' + a;
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function dashed(name) {
+ return name.replace(/[A-Z]/g, function (a) {
+ return '-' + a;
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof name === "object") {
- each(name, function(name, value) {
- self.css(name, value);
- });
- } else {
- if (isDefined(value)) {
- name = camel(name);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof name === "object") {
+ each(name, function (name, value) {
+ self.css(name, value);
+ });
+ } else {
+ if (isDefined(value)) {
+ name = camel(name);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Default px suffix on these
- if (typeof value === 'number' && !numericCssMap[name]) {
- value += 'px';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Default px suffix on these
+ if (typeof value === 'number' && !numericCssMap[name]) {
+ value += 'px';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.each(function() {
- var style = this.style;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.each(function () {
+ var style = this.style;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- hook = cssHooks[name];
- if (hook && hook.set) {
- hook.set(this, value);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ hook = cssHooks[name];
+ if (hook && hook.set) {
+ hook.set(this, value);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- try {
- this.style[cssFix[name] || name] = value;
- } catch (ex) {
- // Ignore
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ try {
+ this.style[cssFix[name] || name] = value;
+ } catch (ex) {
+ // Ignore
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value === null || value === '') {
- if (style.removeProperty) {
- style.removeProperty(dashed(name));
- } else {
- style.removeAttribute(name);
- }
- }
- });
- } else {
- elm = self[0];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value === null || value === '') {
+ if (style.removeProperty) {
+ style.removeProperty(dashed(name));
+ } else {
+ style.removeAttribute(name);
+ }
+ }
+ });
+ } else {
+ elm = self[0];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- hook = cssHooks[name];
- if (hook && hook.get) {
- return hook.get(elm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ hook = cssHooks[name];
+ if (hook && hook.get) {
+ return hook.get(elm);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elm.ownerDocument.defaultView) {
- try {
- return elm.ownerDocument.defaultView.getComputedStyle(elm, null).getPropertyValue(dashed(name));
- } catch (ex) {
- return undef;
- }
- } else if (elm.currentStyle) {
- return elm.currentStyle[camel(name)];
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (elm.ownerDocument.defaultView) {
+ try {
+ return elm.ownerDocument.defaultView.getComputedStyle(elm, null).getPropertyValue(dashed(name));
+ } catch (ex) {
+ return undef;
+ }
+ } else if (elm.currentStyle) {
+ return elm.currentStyle[camel(name)];
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes all nodes in set from the document.
- *
- * @method remove
- * @return {tinymce.dom.DomQuery} Current set with the removed nodes.
- */
- remove: function() {
- var self = this, node, i = this.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes all nodes in set from the document.
+ *
+ * @method remove
+ * @return {tinymce.dom.DomQuery} Current set with the removed nodes.
+ */
+ remove: function () {
+ var self = this, node, i = this.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = self[i];
- Event.clean(node);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = self[i];
+ Event.clean(node);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.parentNode) {
- node.parentNode.removeChild(node);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.parentNode) {
+ node.parentNode.removeChild(node);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Empties all elements in set.
- *
- * @method empty
- * @return {tinymce.dom.DomQuery} Current set with the empty nodes.
- */
- empty: function() {
- var self = this, node, i = this.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Empties all elements in set.
+ *
+ * @method empty
+ * @return {tinymce.dom.DomQuery} Current set with the empty nodes.
+ */
+ empty: function () {
+ var self = this, node, i = this.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = self[i];
- while (node.firstChild) {
- node.removeChild(node.firstChild);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = self[i];
+ while (node.firstChild) {
+ node.removeChild(node.firstChild);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets or gets the HTML of the current set or first set node.
- *
- * @method html
- * @param {String} value Optional innerHTML value to set on each element.
- * @return {tinymce.dom.DomQuery/String} Current set or the innerHTML of the first element.
- */
- html: function(value) {
- var self = this, i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets or gets the HTML of the current set or first set node.
+ *
+ * @method html
+ * @param {String} value Optional innerHTML value to set on each element.
+ * @return {tinymce.dom.DomQuery/String} Current set or the innerHTML of the first element.
+ */
+ html: function (value) {
+ var self = this, i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isDefined(value)) {
- i = self.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isDefined(value)) {
+ i = self.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- try {
- while (i--) {
- self[i].innerHTML = value;
- }
- } catch (ex) {
- // Workaround for "Unknown runtime error" when DIV is added to P on IE
- DomQuery(self[i]).empty().append(value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ try {
+ while (i--) {
+ self[i].innerHTML = value;
+ }
+ } catch (ex) {
+ // Workaround for "Unknown runtime error" when DIV is added to P on IE
+ DomQuery(self[i]).empty().append(value);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self[0] ? self[0].innerHTML : '';
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self[0] ? self[0].innerHTML : '';
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets or gets the text of the current set or first set node.
- *
- * @method text
- * @param {String} value Optional innerText value to set on each element.
- * @return {tinymce.dom.DomQuery/String} Current set or the innerText of the first element.
- */
- text: function(value) {
- var self = this, i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets or gets the text of the current set or first set node.
+ *
+ * @method text
+ * @param {String} value Optional innerText value to set on each element.
+ * @return {tinymce.dom.DomQuery/String} Current set or the innerText of the first element.
+ */
+ text: function (value) {
+ var self = this, i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isDefined(value)) {
- i = self.length;
- while (i--) {
- if ("innerText" in self[i]) {
- self[i].innerText = value;
- } else {
- self[0].textContent = value;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isDefined(value)) {
+ i = self.length;
+ while (i--) {
+ if ("innerText" in self[i]) {
+ self[i].innerText = value;
+ } else {
+ self[0].textContent = value;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self[0] ? (self[0].innerText || self[0].textContent) : '';
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self[0] ? (self[0].innerText || self[0].textContent) : '';
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Appends the specified node/html or node set to the current set nodes.
- *
- * @method append
- * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to append to each element in set.
- * @return {tinymce.dom.DomQuery} Current set.
- */
- append: function() {
- return domManipulate(this, arguments, function(node) {
- // Either element or Shadow Root
- if (this.nodeType === 1 || (this.host && this.host.nodeType === 1)) {
- this.appendChild(node);
- }
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Appends the specified node/html or node set to the current set nodes.
+ *
+ * @method append
+ * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to append to each element in set.
+ * @return {tinymce.dom.DomQuery} Current set.
+ */
+ append: function () {
+ return domManipulate(this, arguments, function (node) {
+ // Either element or Shadow Root
+ if (this.nodeType === 1 || (this.host && this.host.nodeType === 1)) {
+ this.appendChild(node);
+ }
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Prepends the specified node/html or node set to the current set nodes.
- *
- * @method prepend
- * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to prepend to each element in set.
- * @return {tinymce.dom.DomQuery} Current set.
- */
- prepend: function() {
- return domManipulate(this, arguments, function(node) {
- // Either element or Shadow Root
- if (this.nodeType === 1 || (this.host && this.host.nodeType === 1)) {
- this.insertBefore(node, this.firstChild);
- }
- }, true);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Prepends the specified node/html or node set to the current set nodes.
+ *
+ * @method prepend
+ * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to prepend to each element in set.
+ * @return {tinymce.dom.DomQuery} Current set.
+ */
+ prepend: function () {
+ return domManipulate(this, arguments, function (node) {
+ // Either element or Shadow Root
+ if (this.nodeType === 1 || (this.host && this.host.nodeType === 1)) {
+ this.insertBefore(node, this.firstChild);
+ }
+ }, true);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds the specified elements before current set nodes.
- *
- * @method before
- * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to add before to each element in set.
- * @return {tinymce.dom.DomQuery} Current set.
- */
- before: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds the specified elements before current set nodes.
+ *
+ * @method before
+ * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to add before to each element in set.
+ * @return {tinymce.dom.DomQuery} Current set.
+ */
+ before: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self[0] && self[0].parentNode) {
- return domManipulate(self, arguments, function(node) {
- this.parentNode.insertBefore(node, this);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self[0] && self[0].parentNode) {
+ return domManipulate(self, arguments, function (node) {
+ this.parentNode.insertBefore(node, this);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds the specified elements after current set nodes.
- *
- * @method after
- * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to add after to each element in set.
- * @return {tinymce.dom.DomQuery} Current set.
- */
- after: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds the specified elements after current set nodes.
+ *
+ * @method after
+ * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to add after to each element in set.
+ * @return {tinymce.dom.DomQuery} Current set.
+ */
+ after: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self[0] && self[0].parentNode) {
- return domManipulate(self, arguments, function(node) {
- this.parentNode.insertBefore(node, this.nextSibling);
- }, true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self[0] && self[0].parentNode) {
+ return domManipulate(self, arguments, function (node) {
+ this.parentNode.insertBefore(node, this.nextSibling);
+ }, true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Appends the specified set nodes to the specified selector/instance.
- *
- * @method appendTo
- * @param {String/Element/Array/tinymce.dom.DomQuery} val Item to append the current set to.
- * @return {tinymce.dom.DomQuery} Current set with the appended nodes.
- */
- appendTo: function(val) {
- DomQuery(val).append(this);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Appends the specified set nodes to the specified selector/instance.
+ *
+ * @method appendTo
+ * @param {String/Element/Array/tinymce.dom.DomQuery} val Item to append the current set to.
+ * @return {tinymce.dom.DomQuery} Current set with the appended nodes.
+ */
+ appendTo: function (val) {
+ DomQuery(val).append(this);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Prepends the specified set nodes to the specified selector/instance.
- *
- * @method prependTo
- * @param {String/Element/Array/tinymce.dom.DomQuery} val Item to prepend the current set to.
- * @return {tinymce.dom.DomQuery} Current set with the prepended nodes.
- */
- prependTo: function(val) {
- DomQuery(val).prepend(this);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Prepends the specified set nodes to the specified selector/instance.
+ *
+ * @method prependTo
+ * @param {String/Element/Array/tinymce.dom.DomQuery} val Item to prepend the current set to.
+ * @return {tinymce.dom.DomQuery} Current set with the prepended nodes.
+ */
+ prependTo: function (val) {
+ DomQuery(val).prepend(this);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Replaces the nodes in set with the specified content.
- *
- * @method replaceWith
- * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to replace nodes with.
- * @return {tinymce.dom.DomQuery} Set with replaced nodes.
- */
- replaceWith: function(content) {
- return this.before(content).remove();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Replaces the nodes in set with the specified content.
+ *
+ * @method replaceWith
+ * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to replace nodes with.
+ * @return {tinymce.dom.DomQuery} Set with replaced nodes.
+ */
+ replaceWith: function (content) {
+ return this.before(content).remove();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Wraps all elements in set with the specified wrapper.
- *
- * @method wrap
- * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to wrap nodes with.
- * @return {tinymce.dom.DomQuery} Set with wrapped nodes.
- */
- wrap: function(content) {
- return wrap(this, content);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Wraps all elements in set with the specified wrapper.
+ *
+ * @method wrap
+ * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to wrap nodes with.
+ * @return {tinymce.dom.DomQuery} Set with wrapped nodes.
+ */
+ wrap: function (content) {
+ return wrap(this, content);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Wraps all nodes in set with the specified wrapper. If the nodes are siblings all of them
- * will be wrapped in the same wrapper.
- *
- * @method wrapAll
- * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to wrap nodes with.
- * @return {tinymce.dom.DomQuery} Set with wrapped nodes.
- */
- wrapAll: function(content) {
- return wrap(this, content, true);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Wraps all nodes in set with the specified wrapper. If the nodes are siblings all of them
+ * will be wrapped in the same wrapper.
+ *
+ * @method wrapAll
+ * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to wrap nodes with.
+ * @return {tinymce.dom.DomQuery} Set with wrapped nodes.
+ */
+ wrapAll: function (content) {
+ return wrap(this, content, true);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Wraps all elements inner contents in set with the specified wrapper.
- *
- * @method wrapInner
- * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to wrap nodes with.
- * @return {tinymce.dom.DomQuery} Set with wrapped nodes.
- */
- wrapInner: function(content) {
- this.each(function() {
- DomQuery(this).contents().wrapAll(content);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Wraps all elements inner contents in set with the specified wrapper.
+ *
+ * @method wrapInner
+ * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to wrap nodes with.
+ * @return {tinymce.dom.DomQuery} Set with wrapped nodes.
+ */
+ wrapInner: function (content) {
+ this.each(function () {
+ DomQuery(this).contents().wrapAll(content);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Unwraps all elements by removing the parent element of each item in set.
- *
- * @method unwrap
- * @return {tinymce.dom.DomQuery} Set with unwrapped nodes.
- */
- unwrap: function() {
- return this.parent().each(function() {
- DomQuery(this).replaceWith(this.childNodes);
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Unwraps all elements by removing the parent element of each item in set.
+ *
+ * @method unwrap
+ * @return {tinymce.dom.DomQuery} Set with unwrapped nodes.
+ */
+ unwrap: function () {
+ return this.parent().each(function () {
+ DomQuery(this).replaceWith(this.childNodes);
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Clones all nodes in set.
- *
- * @method clone
- * @return {tinymce.dom.DomQuery} Set with cloned nodes.
- */
- clone: function() {
- var result = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Clones all nodes in set.
+ *
+ * @method clone
+ * @return {tinymce.dom.DomQuery} Set with cloned nodes.
+ */
+ clone: function () {
+ var result = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.each(function() {
- result.push(this.cloneNode(true));
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.each(function () {
+ result.push(this.cloneNode(true));
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return DomQuery(result);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return DomQuery(result);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds the specified class name to the current set elements.
- *
- * @method addClass
- * @param {String} className Class name to add.
- * @return {tinymce.dom.DomQuery} Current set.
- */
- addClass: function(className) {
- return this.toggleClass(className, true);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds the specified class name to the current set elements.
+ *
+ * @method addClass
+ * @param {String} className Class name to add.
+ * @return {tinymce.dom.DomQuery} Current set.
+ */
+ addClass: function (className) {
+ return this.toggleClass(className, true);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes the specified class name to the current set elements.
- *
- * @method removeClass
- * @param {String} className Class name to remove.
- * @return {tinymce.dom.DomQuery} Current set.
- */
- removeClass: function(className) {
- return this.toggleClass(className, false);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes the specified class name to the current set elements.
+ *
+ * @method removeClass
+ * @param {String} className Class name to remove.
+ * @return {tinymce.dom.DomQuery} Current set.
+ */
+ removeClass: function (className) {
+ return this.toggleClass(className, false);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Toggles the specified class name on the current set elements.
- *
- * @method toggleClass
- * @param {String} className Class name to add/remove.
- * @param {Boolean} state Optional state to toggle on/off.
- * @return {tinymce.dom.DomQuery} Current set.
- */
- toggleClass: function(className, state) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Toggles the specified class name on the current set elements.
+ *
+ * @method toggleClass
+ * @param {String} className Class name to add/remove.
+ * @param {Boolean} state Optional state to toggle on/off.
+ * @return {tinymce.dom.DomQuery} Current set.
+ */
+ toggleClass: function (className, state) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Functions are not supported
- if (typeof className != 'string') {
- return self;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Functions are not supported
+ if (typeof className != 'string') {
+ return self;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (className.indexOf(' ') !== -1) {
- each(className.split(' '), function() {
- self.toggleClass(this, state);
- });
- } else {
- self.each(function(index, node) {
- var existingClassName, classState;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (className.indexOf(' ') !== -1) {
+ each(className.split(' '), function () {
+ self.toggleClass(this, state);
+ });
+ } else {
+ self.each(function (index, node) {
+ var existingClassName, classState;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- classState = hasClass(node, className);
- if (classState !== state) {
- existingClassName = node.className;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ classState = hasClass(node, className);
+ if (classState !== state) {
+ existingClassName = node.className;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (classState) {
- node.className = trim((" " + existingClassName + " ").replace(' ' + className + ' ', ' '));
- } else {
- node.className += existingClassName ? ' ' + className : className;
- }
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (classState) {
+ node.className = trim((" " + existingClassName + " ").replace(' ' + className + ' ', ' '));
+ } else {
+ node.className += existingClassName ? ' ' + className : className;
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the first item in set has the specified class.
- *
- * @method hasClass
- * @param {String} className Class name to check for.
- * @return {Boolean} True/false if the set has the specified class.
- */
- hasClass: function(className) {
- return hasClass(this[0], className);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the first item in set has the specified class.
+ *
+ * @method hasClass
+ * @param {String} className Class name to check for.
+ * @return {Boolean} True/false if the set has the specified class.
+ */
+ hasClass: function (className) {
+ return hasClass(this[0], className);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Executes the callback function for each item DomQuery collection. If you return false in the
- * callback it will break the loop.
- *
- * @method each
- * @param {function} callback Callback function to execute for each item.
- * @return {tinymce.dom.DomQuery} Current set.
- */
- each: function(callback) {
- return each(this, callback);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Executes the callback function for each item DomQuery collection. If you return false in the
+ * callback it will break the loop.
+ *
+ * @method each
+ * @param {function} callback Callback function to execute for each item.
+ * @return {tinymce.dom.DomQuery} Current set.
+ */
+ each: function (callback) {
+ return each(this, callback);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Binds an event with callback function to the elements in set.
- *
- * @method on
- * @param {String} name Name of the event to bind.
- * @param {function} callback Callback function to execute when the event occurs.
- * @return {tinymce.dom.DomQuery} Current set.
- */
- on: function(name, callback) {
- return this.each(function() {
- Event.bind(this, name, callback);
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Binds an event with callback function to the elements in set.
+ *
+ * @method on
+ * @param {String} name Name of the event to bind.
+ * @param {function} callback Callback function to execute when the event occurs.
+ * @return {tinymce.dom.DomQuery} Current set.
+ */
+ on: function (name, callback) {
+ return this.each(function () {
+ Event.bind(this, name, callback);
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Unbinds an event with callback function to the elements in set.
- *
- * @method off
- * @param {String} name Optional name of the event to bind.
- * @param {function} callback Optional callback function to execute when the event occurs.
- * @return {tinymce.dom.DomQuery} Current set.
- */
- off: function(name, callback) {
- return this.each(function() {
- Event.unbind(this, name, callback);
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Unbinds an event with callback function to the elements in set.
+ *
+ * @method off
+ * @param {String} name Optional name of the event to bind.
+ * @param {function} callback Optional callback function to execute when the event occurs.
+ * @return {tinymce.dom.DomQuery} Current set.
+ */
+ off: function (name, callback) {
+ return this.each(function () {
+ Event.unbind(this, name, callback);
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Triggers the specified event by name or event object.
- *
- * @method trigger
- * @param {String/Object} name Name of the event to trigger or event object.
- * @return {tinymce.dom.DomQuery} Current set.
- */
- trigger: function(name) {
- return this.each(function() {
- if (typeof name == 'object') {
- Event.fire(this, name.type, name);
- } else {
- Event.fire(this, name);
- }
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Triggers the specified event by name or event object.
+ *
+ * @method trigger
+ * @param {String/Object} name Name of the event to trigger or event object.
+ * @return {tinymce.dom.DomQuery} Current set.
+ */
+ trigger: function (name) {
+ return this.each(function () {
+ if (typeof name == 'object') {
+ Event.fire(this, name.type, name);
+ } else {
+ Event.fire(this, name);
+ }
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Shows all elements in set.
- *
- * @method show
- * @return {tinymce.dom.DomQuery} Current set.
- */
- show: function() {
- return this.css('display', '');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Shows all elements in set.
+ *
+ * @method show
+ * @return {tinymce.dom.DomQuery} Current set.
+ */
+ show: function () {
+ return this.css('display', '');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Hides all elements in set.
- *
- * @method hide
- * @return {tinymce.dom.DomQuery} Current set.
- */
- hide: function() {
- return this.css('display', 'none');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Hides all elements in set.
+ *
+ * @method hide
+ * @return {tinymce.dom.DomQuery} Current set.
+ */
+ hide: function () {
+ return this.css('display', 'none');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Slices the current set.
- *
- * @method slice
- * @param {Number} start Start index to slice at.
- * @param {Number} end Optional end index to end slice at.
- * @return {tinymce.dom.DomQuery} Sliced set.
- */
- slice: function() {
- return new DomQuery(slice.apply(this, arguments));
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Slices the current set.
+ *
+ * @method slice
+ * @param {Number} start Start index to slice at.
+ * @param {Number} end Optional end index to end slice at.
+ * @return {tinymce.dom.DomQuery} Sliced set.
+ */
+ slice: function () {
+ return new DomQuery(slice.apply(this, arguments));
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Makes the set equal to the specified index.
- *
- * @method eq
- * @param {Number} index Index to set it equal to.
- * @return {tinymce.dom.DomQuery} Single item set.
- */
- eq: function(index) {
- return index === -1 ? this.slice(index) : this.slice(index, +index + 1);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Makes the set equal to the specified index.
+ *
+ * @method eq
+ * @param {Number} index Index to set it equal to.
+ * @return {tinymce.dom.DomQuery} Single item set.
+ */
+ eq: function (index) {
+ return index === -1 ? this.slice(index) : this.slice(index, +index + 1);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Makes the set equal to first element in set.
- *
- * @method first
- * @return {tinymce.dom.DomQuery} Single item set.
- */
- first: function() {
- return this.eq(0);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Makes the set equal to first element in set.
+ *
+ * @method first
+ * @return {tinymce.dom.DomQuery} Single item set.
+ */
+ first: function () {
+ return this.eq(0);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Makes the set equal to last element in set.
- *
- * @method last
- * @return {tinymce.dom.DomQuery} Single item set.
- */
- last: function() {
- return this.eq(-1);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Makes the set equal to last element in set.
+ *
+ * @method last
+ * @return {tinymce.dom.DomQuery} Single item set.
+ */
+ last: function () {
+ return this.eq(-1);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Finds elements by the specified selector for each element in set.
- *
- * @method find
- * @param {String} selector Selector to find elements by.
- * @return {tinymce.dom.DomQuery} Set with matches elements.
- */
- find: function(selector) {
- var i, l, ret = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Finds elements by the specified selector for each element in set.
+ *
+ * @method find
+ * @param {String} selector Selector to find elements by.
+ * @return {tinymce.dom.DomQuery} Set with matches elements.
+ */
+ find: function (selector) {
+ var i, l, ret = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0, l = this.length; i < l; i++) {
- DomQuery.find(selector, this[i], ret);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0, l = this.length; i < l; i++) {
+ DomQuery.find(selector, this[i], ret);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return DomQuery(ret);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return DomQuery(ret);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Filters the current set with the specified selector.
- *
- * @method filter
- * @param {String/function} selector Selector to filter elements by.
- * @return {tinymce.dom.DomQuery} Set with filtered elements.
- */
- filter: function(selector) {
- if (typeof selector == 'function') {
- return DomQuery(grep(this.toArray(), function(item, i) {
- return selector(i, item);
- }));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Filters the current set with the specified selector.
+ *
+ * @method filter
+ * @param {String/function} selector Selector to filter elements by.
+ * @return {tinymce.dom.DomQuery} Set with filtered elements.
+ */
+ filter: function (selector) {
+ if (typeof selector == 'function') {
+ return DomQuery(grep(this.toArray(), function (item, i) {
+ return selector(i, item);
+ }));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return DomQuery(DomQuery.filter(selector, this.toArray()));
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return DomQuery(DomQuery.filter(selector, this.toArray()));
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Gets the current node or any parent matching the specified selector.
- *
- * @method closest
- * @param {String/Element/tinymce.dom.DomQuery} selector Selector or element to find.
- * @return {tinymce.dom.DomQuery} Set with closest elements.
- */
- closest: function(selector) {
- var result = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Gets the current node or any parent matching the specified selector.
+ *
+ * @method closest
+ * @param {String/Element/tinymce.dom.DomQuery} selector Selector or element to find.
+ * @return {tinymce.dom.DomQuery} Set with closest elements.
+ */
+ closest: function (selector) {
+ var result = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (selector instanceof DomQuery) {
- selector = selector[0];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (selector instanceof DomQuery) {
+ selector = selector[0];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.each(function(i, node) {
- while (node) {
- if (typeof selector == 'string' && DomQuery(node).is(selector)) {
- result.push(node);
- break;
- } else if (node == selector) {
- result.push(node);
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.each(function (i, node) {
+ while (node) {
+ if (typeof selector == 'string' && DomQuery(node).is(selector)) {
+ result.push(node);
+ break;
+ } else if (node == selector) {
+ result.push(node);
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.parentNode;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node.parentNode;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return DomQuery(result);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return DomQuery(result);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the offset of the first element in set or sets the top/left css properties of all elements in set.
- *
- * @method offset
- * @param {Object} offset Optional offset object to set on each item.
- * @return {Object/tinymce.dom.DomQuery} Returns the first element offset or the current set if you specified an offset.
- */
- offset: function(offset) {
- var elm, doc, docElm;
- var x = 0, y = 0, pos;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the offset of the first element in set or sets the top/left css properties of all elements in set.
+ *
+ * @method offset
+ * @param {Object} offset Optional offset object to set on each item.
+ * @return {Object/tinymce.dom.DomQuery} Returns the first element offset or the current set if you specified an offset.
+ */
+ offset: function (offset) {
+ var elm, doc, docElm;
+ var x = 0, y = 0, pos;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!offset) {
- elm = this[0];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!offset) {
+ elm = this[0];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elm) {
- doc = elm.ownerDocument;
- docElm = doc.documentElement;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (elm) {
+ doc = elm.ownerDocument;
+ docElm = doc.documentElement;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elm.getBoundingClientRect) {
- pos = elm.getBoundingClientRect();
- x = pos.left + (docElm.scrollLeft || doc.body.scrollLeft) - docElm.clientLeft;
- y = pos.top + (docElm.scrollTop || doc.body.scrollTop) - docElm.clientTop;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (elm.getBoundingClientRect) {
+ pos = elm.getBoundingClientRect();
+ x = pos.left + (docElm.scrollLeft || doc.body.scrollLeft) - docElm.clientLeft;
+ y = pos.top + (docElm.scrollTop || doc.body.scrollTop) - docElm.clientTop;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- left: x,
- top: y
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ left: x,
+ top: y
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this.css(offset);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this.css(offset);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- push: push,
- sort: [].sort,
- splice: [].splice
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ push: push,
+ sort: [].sort,
+ splice: [].splice
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Static members
- Tools.extend(DomQuery, {
- /**
- * Extends the specified object with one or more objects.
- *
- * @static
- * @method extend
- * @param {Object} target Target object to extend with new items.
- * @param {Object..} object Object to extend the target with.
- * @return {Object} Extended input object.
- */
- extend: Tools.extend,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Static members
+ Tools.extend(DomQuery, {
+ /**
+ * Extends the specified object with one or more objects.
+ *
+ * @static
+ * @method extend
+ * @param {Object} target Target object to extend with new items.
+ * @param {Object..} object Object to extend the target with.
+ * @return {Object} Extended input object.
+ */
+ extend: Tools.extend,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates an array out of an array like object.
- *
- * @static
- * @method makeArray
- * @param {Object} object Object to convert to array.
- * @return {Array} Array produced from object.
- */
- makeArray: function(object) {
- if (isWindow(object) || object.nodeType) {
- return [object];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates an array out of an array like object.
+ *
+ * @static
+ * @method makeArray
+ * @param {Object} object Object to convert to array.
+ * @return {Array} Array produced from object.
+ */
+ makeArray: function (object) {
+ if (isWindow(object) || object.nodeType) {
+ return [object];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Tools.toArray(object);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Tools.toArray(object);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the index of the specified item inside the array.
- *
- * @static
- * @method inArray
- * @param {Object} item Item to look for.
- * @param {Array} array Array to look for item in.
- * @return {Number} Index of the item or -1.
- */
- inArray: inArray,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the index of the specified item inside the array.
+ *
+ * @static
+ * @method inArray
+ * @param {Object} item Item to look for.
+ * @param {Array} array Array to look for item in.
+ * @return {Number} Index of the item or -1.
+ */
+ inArray: inArray,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the specified object is an array or not.
- *
- * @static
- * @method isArray
- * @param {Object} array Object to check if it's an array or not.
- * @return {Boolean} True/false if the object is an array.
- */
- isArray: Tools.isArray,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the specified object is an array or not.
+ *
+ * @static
+ * @method isArray
+ * @param {Object} array Object to check if it's an array or not.
+ * @return {Boolean} True/false if the object is an array.
+ */
+ isArray: Tools.isArray,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Executes the callback function for each item in array/object. If you return false in the
- * callback it will break the loop.
- *
- * @static
- * @method each
- * @param {Object} obj Object to iterate.
- * @param {function} callback Callback function to execute for each item.
- */
- each: each,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Executes the callback function for each item in array/object. If you return false in the
+ * callback it will break the loop.
+ *
+ * @static
+ * @method each
+ * @param {Object} obj Object to iterate.
+ * @param {function} callback Callback function to execute for each item.
+ */
+ each: each,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes whitespace from the beginning and end of a string.
- *
- * @static
- * @method trim
- * @param {String} str String to remove whitespace from.
- * @return {String} New string with removed whitespace.
- */
- trim: trim,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes whitespace from the beginning and end of a string.
+ *
+ * @static
+ * @method trim
+ * @param {String} str String to remove whitespace from.
+ * @return {String} New string with removed whitespace.
+ */
+ trim: trim,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Filters out items from the input array by calling the specified function for each item.
- * If the function returns false the item will be excluded if it returns true it will be included.
- *
- * @static
- * @method grep
- * @param {Array} array Array of items to loop though.
- * @param {function} callback Function to call for each item. Include/exclude depends on it's return value.
- * @return {Array} New array with values imported and filtered based in input.
- * @example
- * // Filter out some items, this will return an array with 4 and 5
- * var items = DomQuery.grep([1, 2, 3, 4, 5], function(v) {return v > 3;});
- */
- grep: grep,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Filters out items from the input array by calling the specified function for each item.
+ * If the function returns false the item will be excluded if it returns true it will be included.
+ *
+ * @static
+ * @method grep
+ * @param {Array} array Array of items to loop though.
+ * @param {function} callback Function to call for each item. Include/exclude depends on it's return value.
+ * @return {Array} New array with values imported and filtered based in input.
+ * @example
+ * // Filter out some items, this will return an array with 4 and 5
+ * var items = DomQuery.grep([1, 2, 3, 4, 5], function(v) {return v > 3;});
+ */
+ grep: grep,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Sizzle
- find: Sizzle,
- expr: Sizzle.selectors,
- unique: Sizzle.uniqueSort,
- text: Sizzle.getText,
- contains: Sizzle.contains,
- filter: function(expr, elems, not) {
- var i = elems.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Sizzle
+ find: Sizzle,
+ expr: Sizzle.selectors,
+ unique: Sizzle.uniqueSort,
+ text: Sizzle.getText,
+ contains: Sizzle.contains,
+ filter: function (expr, elems, not) {
+ var i = elems.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (not) {
- expr = ":not(" + expr + ")";
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (not) {
+ expr = ":not(" + expr + ")";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- if (elems[i].nodeType != 1) {
- elems.splice(i, 1);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ if (elems[i].nodeType != 1) {
+ elems.splice(i, 1);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elems.length === 1) {
- elems = DomQuery.find.matchesSelector(elems[0], expr) ? [elems[0]] : [];
- } else {
- elems = DomQuery.find.matches(expr, elems);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (elems.length === 1) {
+ elems = DomQuery.find.matchesSelector(elems[0], expr) ? [elems[0]] : [];
+ } else {
+ elems = DomQuery.find.matches(expr, elems);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return elems;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return elems;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function dir(el, prop, until) {
- var matched = [], cur = el[prop];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function dir(el, prop, until) {
+ var matched = [], cur = el[prop];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof until != 'string' && until instanceof DomQuery) {
- until = until[0];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof until != 'string' && until instanceof DomQuery) {
+ until = until[0];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (cur && cur.nodeType !== 9) {
- if (until !== undefined) {
- if (cur === until) {
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (cur && cur.nodeType !== 9) {
+ if (until !== undefined) {
+ if (cur === until) {
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof until == 'string' && DomQuery(cur).is(until)) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof until == 'string' && DomQuery(cur).is(until)) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (cur.nodeType === 1) {
- matched.push(cur);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (cur.nodeType === 1) {
+ matched.push(cur);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- cur = cur[prop];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ cur = cur[prop];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return matched;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return matched;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function sibling(node, siblingName, nodeType, until) {
- var result = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function sibling(node, siblingName, nodeType, until) {
+ var result = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (until instanceof DomQuery) {
- until = until[0];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (until instanceof DomQuery) {
+ until = until[0];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (; node; node = node[siblingName]) {
- if (nodeType && node.nodeType !== nodeType) {
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (; node; node = node[siblingName]) {
+ if (nodeType && node.nodeType !== nodeType) {
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (until !== undefined) {
- if (node === until) {
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (until !== undefined) {
+ if (node === until) {
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof until == 'string' && DomQuery(node).is(until)) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof until == 'string' && DomQuery(node).is(until)) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- result.push(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ result.push(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return result;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return result;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function firstSibling(node, siblingName, nodeType) {
- for (node = node[siblingName]; node; node = node[siblingName]) {
- if (node.nodeType == nodeType) {
- return node;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function firstSibling(node, siblingName, nodeType) {
+ for (node = node[siblingName]; node; node = node[siblingName]) {
+ if (node.nodeType == nodeType) {
+ return node;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each({
- /**
- * Returns a new collection with the parent of each item in current collection matching the optional selector.
- *
- * @method parent
- * @param {Element/tinymce.dom.DomQuery} node Node to match parents against.
- * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching parents.
- */
- parent: function(node) {
- var parent = node.parentNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each({
+ /**
+ * Returns a new collection with the parent of each item in current collection matching the optional selector.
+ *
+ * @method parent
+ * @param {Element/tinymce.dom.DomQuery} node Node to match parents against.
+ * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching parents.
+ */
+ parent: function (node) {
+ var parent = node.parentNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return parent && parent.nodeType !== 11 ? parent : null;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return parent && parent.nodeType !== 11 ? parent : null;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a new collection with the all the parents of each item in current collection matching the optional selector.
- *
- * @method parents
- * @param {Element/tinymce.dom.DomQuery} node Node to match parents against.
- * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching parents.
- */
- parents: function(node) {
- return dir(node, "parentNode");
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a new collection with the all the parents of each item in current collection matching the optional selector.
+ *
+ * @method parents
+ * @param {Element/tinymce.dom.DomQuery} node Node to match parents against.
+ * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching parents.
+ */
+ parents: function (node) {
+ return dir(node, "parentNode");
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a new collection with next sibling of each item in current collection matching the optional selector.
- *
- * @method next
- * @param {Element/tinymce.dom.DomQuery} node Node to match the next element against.
- * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching elements.
- */
- next: function(node) {
- return firstSibling(node, 'nextSibling', 1);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a new collection with next sibling of each item in current collection matching the optional selector.
+ *
+ * @method next
+ * @param {Element/tinymce.dom.DomQuery} node Node to match the next element against.
+ * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching elements.
+ */
+ next: function (node) {
+ return firstSibling(node, 'nextSibling', 1);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a new collection with previous sibling of each item in current collection matching the optional selector.
- *
- * @method prev
- * @param {Element/tinymce.dom.DomQuery} node Node to match the previous element against.
- * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching elements.
- */
- prev: function(node) {
- return firstSibling(node, 'previousSibling', 1);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a new collection with previous sibling of each item in current collection matching the optional selector.
+ *
+ * @method prev
+ * @param {Element/tinymce.dom.DomQuery} node Node to match the previous element against.
+ * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching elements.
+ */
+ prev: function (node) {
+ return firstSibling(node, 'previousSibling', 1);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns all child elements matching the optional selector.
- *
- * @method children
- * @param {Element/tinymce.dom.DomQuery} node Node to match the elements against.
- * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching elements.
- */
- children: function(node) {
- return sibling(node.firstChild, 'nextSibling', 1);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns all child elements matching the optional selector.
+ *
+ * @method children
+ * @param {Element/tinymce.dom.DomQuery} node Node to match the elements against.
+ * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching elements.
+ */
+ children: function (node) {
+ return sibling(node.firstChild, 'nextSibling', 1);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns all child nodes matching the optional selector.
- *
- * @method contents
- * @param {Element/tinymce.dom.DomQuery} node Node to get the contents of.
- * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching elements.
- */
- contents: function(node) {
- return Tools.toArray((node.nodeName === "iframe" ? node.contentDocument || node.contentWindow.document : node).childNodes);
- }
- }, function(name, fn) {
- DomQuery.fn[name] = function(selector) {
- var self = this, result = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns all child nodes matching the optional selector.
+ *
+ * @method contents
+ * @param {Element/tinymce.dom.DomQuery} node Node to get the contents of.
+ * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching elements.
+ */
+ contents: function (node) {
+ return Tools.toArray((node.nodeName === "iframe" ? node.contentDocument || node.contentWindow.document : node).childNodes);
+ }
+ }, function (name, fn) {
+ DomQuery.fn[name] = function (selector) {
+ var self = this, result = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.each(function() {
- var nodes = fn.call(result, this, selector, result);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.each(function () {
+ var nodes = fn.call(result, this, selector, result);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (nodes) {
- if (DomQuery.isArray(nodes)) {
- result.push.apply(result, nodes);
- } else {
- result.push(nodes);
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (nodes) {
+ if (DomQuery.isArray(nodes)) {
+ result.push.apply(result, nodes);
+ } else {
+ result.push(nodes);
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If traversing on multiple elements we might get the same elements twice
- if (this.length > 1) {
- if (!skipUniques[name]) {
- result = DomQuery.unique(result);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If traversing on multiple elements we might get the same elements twice
+ if (this.length > 1) {
+ if (!skipUniques[name]) {
+ result = DomQuery.unique(result);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name.indexOf('parents') === 0) {
- result = result.reverse();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name.indexOf('parents') === 0) {
+ result = result.reverse();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- result = DomQuery(result);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ result = DomQuery(result);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (selector) {
- return result.filter(selector);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (selector) {
+ return result.filter(selector);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return result;
- };
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return result;
+ };
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each({
- /**
- * Returns a new collection with the all the parents until the matching selector/element
- * of each item in current collection matching the optional selector.
- *
- * @method parentsUntil
- * @param {Element/tinymce.dom.DomQuery} node Node to find parent of.
- * @param {String/Element/tinymce.dom.DomQuery} until Until the matching selector or element.
- * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching parents.
- */
- parentsUntil: function(node, until) {
- return dir(node, "parentNode", until);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each({
+ /**
+ * Returns a new collection with the all the parents until the matching selector/element
+ * of each item in current collection matching the optional selector.
+ *
+ * @method parentsUntil
+ * @param {Element/tinymce.dom.DomQuery} node Node to find parent of.
+ * @param {String/Element/tinymce.dom.DomQuery} until Until the matching selector or element.
+ * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching parents.
+ */
+ parentsUntil: function (node, until) {
+ return dir(node, "parentNode", until);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a new collection with all next siblings of each item in current collection matching the optional selector.
- *
- * @method nextUntil
- * @param {Element/tinymce.dom.DomQuery} node Node to find next siblings on.
- * @param {String/Element/tinymce.dom.DomQuery} until Until the matching selector or element.
- * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching elements.
- */
- nextUntil: function(node, until) {
- return sibling(node, 'nextSibling', 1, until).slice(1);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a new collection with all next siblings of each item in current collection matching the optional selector.
+ *
+ * @method nextUntil
+ * @param {Element/tinymce.dom.DomQuery} node Node to find next siblings on.
+ * @param {String/Element/tinymce.dom.DomQuery} until Until the matching selector or element.
+ * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching elements.
+ */
+ nextUntil: function (node, until) {
+ return sibling(node, 'nextSibling', 1, until).slice(1);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a new collection with all previous siblings of each item in current collection matching the optional selector.
- *
- * @method prevUntil
- * @param {Element/tinymce.dom.DomQuery} node Node to find previous siblings on.
- * @param {String/Element/tinymce.dom.DomQuery} until Until the matching selector or element.
- * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching elements.
- */
- prevUntil: function(node, until) {
- return sibling(node, 'previousSibling', 1, until).slice(1);
- }
- }, function(name, fn) {
- DomQuery.fn[name] = function(selector, filter) {
- var self = this, result = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a new collection with all previous siblings of each item in current collection matching the optional selector.
+ *
+ * @method prevUntil
+ * @param {Element/tinymce.dom.DomQuery} node Node to find previous siblings on.
+ * @param {String/Element/tinymce.dom.DomQuery} until Until the matching selector or element.
+ * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching elements.
+ */
+ prevUntil: function (node, until) {
+ return sibling(node, 'previousSibling', 1, until).slice(1);
+ }
+ }, function (name, fn) {
+ DomQuery.fn[name] = function (selector, filter) {
+ var self = this, result = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.each(function() {
- var nodes = fn.call(result, this, selector, result);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.each(function () {
+ var nodes = fn.call(result, this, selector, result);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (nodes) {
- if (DomQuery.isArray(nodes)) {
- result.push.apply(result, nodes);
- } else {
- result.push(nodes);
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (nodes) {
+ if (DomQuery.isArray(nodes)) {
+ result.push.apply(result, nodes);
+ } else {
+ result.push(nodes);
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If traversing on multiple elements we might get the same elements twice
- if (this.length > 1) {
- result = DomQuery.unique(result);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If traversing on multiple elements we might get the same elements twice
+ if (this.length > 1) {
+ result = DomQuery.unique(result);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name.indexOf('parents') === 0 || name === 'prevUntil') {
- result = result.reverse();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name.indexOf('parents') === 0 || name === 'prevUntil') {
+ result = result.reverse();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- result = DomQuery(result);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ result = DomQuery(result);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (filter) {
- return result.filter(filter);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (filter) {
+ return result.filter(filter);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return result;
- };
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return result;
+ };
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the current set items matches the selector.
- *
- * @method is
- * @param {String} selector Selector to match the elements against.
- * @return {Boolean} True/false if the current set matches the selector.
- */
- DomQuery.fn.is = function(selector) {
- return !!selector && this.filter(selector).length > 0;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the current set items matches the selector.
+ *
+ * @method is
+ * @param {String} selector Selector to match the elements against.
+ * @return {Boolean} True/false if the current set matches the selector.
+ */
+ DomQuery.fn.is = function (selector) {
+ return !!selector && this.filter(selector).length > 0;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DomQuery.fn.init.prototype = DomQuery.fn;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DomQuery.fn.init.prototype = DomQuery.fn;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DomQuery.overrideDefaults = function(callback) {
- var defaults;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DomQuery.overrideDefaults = function (callback) {
+ var defaults;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function sub(selector, context) {
- defaults = defaults || callback();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function sub(selector, context) {
+ defaults = defaults || callback();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (arguments.length === 0) {
- selector = defaults.element;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (arguments.length === 0) {
+ selector = defaults.element;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!context) {
- context = defaults.context;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!context) {
+ context = defaults.context;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return new sub.fn.init(selector, context);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return new sub.fn.init(selector, context);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DomQuery.extend(sub, this);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DomQuery.extend(sub, this);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return sub;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return sub;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function appendHooks(targetHooks, prop, hooks) {
- each(hooks, function(name, func) {
- targetHooks[name] = targetHooks[name] || {};
- targetHooks[name][prop] = func;
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function appendHooks(targetHooks, prop, hooks) {
+ each(hooks, function (name, func) {
+ targetHooks[name] = targetHooks[name] || {};
+ targetHooks[name][prop] = func;
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (Env.ie && Env.ie < 8) {
- appendHooks(attrHooks, 'get', {
- maxlength: function(elm) {
- var value = elm.maxLength;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (Env.ie && Env.ie < 8) {
+ appendHooks(attrHooks, 'get', {
+ maxlength: function (elm) {
+ var value = elm.maxLength;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value === 0x7fffffff) {
- return undef;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value === 0x7fffffff) {
+ return undef;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return value;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return value;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- size: function(elm) {
- var value = elm.size;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ size: function (elm) {
+ var value = elm.size;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value === 20) {
- return undef;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value === 20) {
+ return undef;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return value;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return value;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'class': function(elm) {
- return elm.className;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'class': function (elm) {
+ return elm.className;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- style: function(elm) {
- var value = elm.style.cssText;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ style: function (elm) {
+ var value = elm.style.cssText;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value.length === 0) {
- return undef;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value.length === 0) {
+ return undef;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return value;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return value;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- appendHooks(attrHooks, 'set', {
- 'class': function(elm, value) {
- elm.className = value;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ appendHooks(attrHooks, 'set', {
+ 'class': function (elm, value) {
+ elm.className = value;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- style: function(elm, value) {
- elm.style.cssText = value;
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ style: function (elm, value) {
+ elm.style.cssText = value;
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (Env.ie && Env.ie < 9) {
- /*jshint sub:true */
- /*eslint dot-notation: 0*/
- cssFix['float'] = 'styleFloat';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (Env.ie && Env.ie < 9) {
+ /*jshint sub:true */
+ /*eslint dot-notation: 0*/
+ cssFix['float'] = 'styleFloat';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- appendHooks(cssHooks, 'set', {
- opacity: function(elm, value) {
- var style = elm.style;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ appendHooks(cssHooks, 'set', {
+ opacity: function (elm, value) {
+ var style = elm.style;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value === null || value === '') {
- style.removeAttribute('filter');
- } else {
- style.zoom = 1;
- style.filter = 'alpha(opacity=' + (value * 100) + ')';
- }
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value === null || value === '') {
+ style.removeAttribute('filter');
+ } else {
+ style.zoom = 1;
+ style.filter = 'alpha(opacity=' + (value * 100) + ')';
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DomQuery.attrHooks = attrHooks;
- DomQuery.cssHooks = cssHooks;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DomQuery.attrHooks = attrHooks;
+ DomQuery.cssHooks = cssHooks;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return DomQuery;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return DomQuery;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/html/Styles.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Styles.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -5791,358 +5801,361 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.html.Styles
</span><span class="cx" style="display: block; padding: 0 10px"> * @version 3.4
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/html/Styles", [], function() {
- return function(settings, schema) {
- /*jshint maxlen:255 */
- /*eslint max-len:0 */
- var rgbRegExp = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi,
- urlOrStrRegExp = /(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,
- styleRegExp = /\s*([^:]+):\s*([^;]+);?/g,
- trimRightRegExp = /\s+$/,
- i, encodingLookup = {}, encodingItems, validStyles, invalidStyles, invisibleChar = '\uFEFF';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.html.Styles',
+ [
+ ],
+ function () {
+ return function (settings, schema) {
+ /*jshint maxlen:255 */
+ /*eslint max-len:0 */
+ var rgbRegExp = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi,
+ urlOrStrRegExp = /(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,
+ styleRegExp = /\s*([^:]+):\s*([^;]+);?/g,
+ trimRightRegExp = /\s+$/,
+ i, encodingLookup = {}, encodingItems, validStyles, invalidStyles, invisibleChar = '\uFEFF';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- settings = settings || {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ settings = settings || {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (schema) {
- validStyles = schema.getValidStyles();
- invalidStyles = schema.getInvalidStyles();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (schema) {
+ validStyles = schema.getValidStyles();
+ invalidStyles = schema.getInvalidStyles();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- encodingItems = ('\\" \\\' \\; \\: ; : ' + invisibleChar).split(' ');
- for (i = 0; i < encodingItems.length; i++) {
- encodingLookup[encodingItems[i]] = invisibleChar + i;
- encodingLookup[invisibleChar + i] = encodingItems[i];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ encodingItems = ('\\" \\\' \\; \\: ; : ' + invisibleChar).split(' ');
+ for (i = 0; i < encodingItems.length; i++) {
+ encodingLookup[encodingItems[i]] = invisibleChar + i;
+ encodingLookup[invisibleChar + i] = encodingItems[i];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function toHex(match, r, g, b) {
- function hex(val) {
- val = parseInt(val, 10).toString(16);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function toHex(match, r, g, b) {
+ function hex(val) {
+ val = parseInt(val, 10).toString(16);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return val.length > 1 ? val : '0' + val; // 0 -> 00
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return val.length > 1 ? val : '0' + val; // 0 -> 00
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return '#' + hex(r) + hex(g) + hex(b);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return '#' + hex(r) + hex(g) + hex(b);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- /**
- * Parses the specified RGB color value and returns a hex version of that color.
- *
- * @method toHex
- * @param {String} color RGB string value like rgb(1,2,3)
- * @return {String} Hex version of that RGB value like #FF00FF.
- */
- toHex: function(color) {
- return color.replace(rgbRegExp, toHex);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ /**
+ * Parses the specified RGB color value and returns a hex version of that color.
+ *
+ * @method toHex
+ * @param {String} color RGB string value like rgb(1,2,3)
+ * @return {String} Hex version of that RGB value like #FF00FF.
+ */
+ toHex: function (color) {
+ return color.replace(rgbRegExp, toHex);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Parses the specified style value into an object collection. This parser will also
- * merge and remove any redundant items that browsers might have added. It will also convert non hex
- * colors to hex values. Urls inside the styles will also be converted to absolute/relative based on settings.
- *
- * @method parse
- * @param {String} css Style value to parse for example: border:1px solid red;.
- * @return {Object} Object representation of that style like {border: '1px solid red'}
- */
- parse: function(css) {
- var styles = {}, matches, name, value, isEncoded, urlConverter = settings.url_converter;
- var urlConverterScope = settings.url_converter_scope || this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Parses the specified style value into an object collection. This parser will also
+ * merge and remove any redundant items that browsers might have added. It will also convert non hex
+ * colors to hex values. Urls inside the styles will also be converted to absolute/relative based on settings.
+ *
+ * @method parse
+ * @param {String} css Style value to parse for example: border:1px solid red;.
+ * @return {Object} Object representation of that style like {border: '1px solid red'}
+ */
+ parse: function (css) {
+ var styles = {}, matches, name, value, isEncoded, urlConverter = settings.url_converter;
+ var urlConverterScope = settings.url_converter_scope || this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function compress(prefix, suffix, noJoin) {
- var top, right, bottom, left;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function compress(prefix, suffix, noJoin) {
+ var top, right, bottom, left;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- top = styles[prefix + '-top' + suffix];
- if (!top) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ top = styles[prefix + '-top' + suffix];
+ if (!top) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- right = styles[prefix + '-right' + suffix];
- if (!right) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ right = styles[prefix + '-right' + suffix];
+ if (!right) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bottom = styles[prefix + '-bottom' + suffix];
- if (!bottom) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bottom = styles[prefix + '-bottom' + suffix];
+ if (!bottom) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- left = styles[prefix + '-left' + suffix];
- if (!left) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ left = styles[prefix + '-left' + suffix];
+ if (!left) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var box = [top, right, bottom, left];
- i = box.length - 1;
- while (i--) {
- if (box[i] !== box[i + 1]) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var box = [top, right, bottom, left];
+ i = box.length - 1;
+ while (i--) {
+ if (box[i] !== box[i + 1]) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (i > -1 && noJoin) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (i > -1 && noJoin) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- styles[prefix + suffix] = i == -1 ? box[0] : box.join(' ');
- delete styles[prefix + '-top' + suffix];
- delete styles[prefix + '-right' + suffix];
- delete styles[prefix + '-bottom' + suffix];
- delete styles[prefix + '-left' + suffix];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ styles[prefix + suffix] = i == -1 ? box[0] : box.join(' ');
+ delete styles[prefix + '-top' + suffix];
+ delete styles[prefix + '-right' + suffix];
+ delete styles[prefix + '-bottom' + suffix];
+ delete styles[prefix + '-left' + suffix];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Checks if the specific style can be compressed in other words if all border-width are equal.
- */
- function canCompress(key) {
- var value = styles[key], i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Checks if the specific style can be compressed in other words if all border-width are equal.
+ */
+ function canCompress(key) {
+ var value = styles[key], i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!value) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!value) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- value = value.split(' ');
- i = value.length;
- while (i--) {
- if (value[i] !== value[0]) {
- return false;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ value = value.split(' ');
+ i = value.length;
+ while (i--) {
+ if (value[i] !== value[0]) {
+ return false;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- styles[key] = value[0];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ styles[key] = value[0];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Compresses multiple styles into one style.
- */
- function compress2(target, a, b, c) {
- if (!canCompress(a)) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Compresses multiple styles into one style.
+ */
+ function compress2(target, a, b, c) {
+ if (!canCompress(a)) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!canCompress(b)) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!canCompress(b)) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!canCompress(c)) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!canCompress(c)) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Compress
- styles[target] = styles[a] + ' ' + styles[b] + ' ' + styles[c];
- delete styles[a];
- delete styles[b];
- delete styles[c];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Compress
+ styles[target] = styles[a] + ' ' + styles[b] + ' ' + styles[c];
+ delete styles[a];
+ delete styles[b];
+ delete styles[c];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Encodes the specified string by replacing all \" \' ; : with _<num>
- function encode(str) {
- isEncoded = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Encodes the specified string by replacing all \" \' ; : with _<num>
+ function encode(str) {
+ isEncoded = true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return encodingLookup[str];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return encodingLookup[str];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Decodes the specified string by replacing all _<num> with it's original value \" \' etc
- // It will also decode the \" \' if keep_slashes is set to fale or omitted
- function decode(str, keep_slashes) {
- if (isEncoded) {
- str = str.replace(/\uFEFF[0-9]/g, function(str) {
- return encodingLookup[str];
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Decodes the specified string by replacing all _<num> with it's original value \" \' etc
+ // It will also decode the \" \' if keepSlashes is set to fale or omitted
+ function decode(str, keepSlashes) {
+ if (isEncoded) {
+ str = str.replace(/\uFEFF[0-9]/g, function (str) {
+ return encodingLookup[str];
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!keep_slashes) {
- str = str.replace(/\\([\'\";:])/g, "$1");
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!keepSlashes) {
+ str = str.replace(/\\([\'\";:])/g, "$1");
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return str;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return str;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function decodeSingleHexSequence(escSeq) {
- return String.fromCharCode(parseInt(escSeq.slice(1), 16));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function decodeSingleHexSequence(escSeq) {
+ return String.fromCharCode(parseInt(escSeq.slice(1), 16));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function decodeHexSequences(value) {
- return value.replace(/\\[0-9a-f]+/gi, decodeSingleHexSequence);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function decodeHexSequences(value) {
+ return value.replace(/\\[0-9a-f]+/gi, decodeSingleHexSequence);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function processUrl(match, url, url2, url3, str, str2) {
- str = str || str2;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function processUrl(match, url, url2, url3, str, str2) {
+ str = str || str2;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (str) {
- str = decode(str);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (str) {
+ str = decode(str);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Force strings into single quote format
- return "'" + str.replace(/\'/g, "\\'") + "'";
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Force strings into single quote format
+ return "'" + str.replace(/\'/g, "\\'") + "'";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- url = decode(url || url2 || url3);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ url = decode(url || url2 || url3);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!settings.allow_script_urls) {
- var scriptUrl = url.replace(/[\s\r\n]+/g, '');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!settings.allow_script_urls) {
+ var scriptUrl = url.replace(/[\s\r\n]+/g, '');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (/(java|vb)script:/i.test(scriptUrl)) {
- return "";
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (/(java|vb)script:/i.test(scriptUrl)) {
+ return "";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!settings.allow_svg_data_urls && /^data:image\/svg/i.test(scriptUrl)) {
- return "";
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!settings.allow_svg_data_urls && /^data:image\/svg/i.test(scriptUrl)) {
+ return "";
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Convert the URL to relative/absolute depending on config
- if (urlConverter) {
- url = urlConverter.call(urlConverterScope, url, 'style');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Convert the URL to relative/absolute depending on config
+ if (urlConverter) {
+ url = urlConverter.call(urlConverterScope, url, 'style');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Output new URL format
- return "url('" + url.replace(/\'/g, "\\'") + "')";
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Output new URL format
+ return "url('" + url.replace(/\'/g, "\\'") + "')";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (css) {
- css = css.replace(/[\u0000-\u001F]/g, '');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (css) {
+ css = css.replace(/[\u0000-\u001F]/g, '');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Encode \" \' % and ; and : inside strings so they don't interfere with the style parsing
- css = css.replace(/\\[\"\';:\uFEFF]/g, encode).replace(/\"[^\"]+\"|\'[^\']+\'/g, function(str) {
- return str.replace(/[;:]/g, encode);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Encode \" \' % and ; and : inside strings so they don't interfere with the style parsing
+ css = css.replace(/\\[\"\';:\uFEFF]/g, encode).replace(/\"[^\"]+\"|\'[^\']+\'/g, function (str) {
+ return str.replace(/[;:]/g, encode);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Parse styles
- while ((matches = styleRegExp.exec(css))) {
- styleRegExp.lastIndex = matches.index + matches[0].length;
- name = matches[1].replace(trimRightRegExp, '').toLowerCase();
- value = matches[2].replace(trimRightRegExp, '');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Parse styles
+ while ((matches = styleRegExp.exec(css))) {
+ styleRegExp.lastIndex = matches.index + matches[0].length;
+ name = matches[1].replace(trimRightRegExp, '').toLowerCase();
+ value = matches[2].replace(trimRightRegExp, '');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name && value) {
- // Decode escaped sequences like \65 -> e
- name = decodeHexSequences(name);
- value = decodeHexSequences(value);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name && value) {
+ // Decode escaped sequences like \65 -> e
+ name = decodeHexSequences(name);
+ value = decodeHexSequences(value);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Skip properties with double quotes and sequences like \" \' in their names
- // See 'mXSS Attacks: Attacking well-secured Web-Applications by using innerHTML Mutations'
- // https://cure53.de/fp170.pdf
- if (name.indexOf(invisibleChar) !== -1 || name.indexOf('"') !== -1) {
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Skip properties with double quotes and sequences like \" \' in their names
+ // See 'mXSS Attacks: Attacking well-secured Web-Applications by using innerHTML Mutations'
+ // https://cure53.de/fp170.pdf
+ if (name.indexOf(invisibleChar) !== -1 || name.indexOf('"') !== -1) {
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Don't allow behavior name or expression/comments within the values
- if (!settings.allow_script_urls && (name == "behavior" || /expression\s*\(|\/\*|\*\//.test(value))) {
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't allow behavior name or expression/comments within the values
+ if (!settings.allow_script_urls && (name == "behavior" || /expression\s*\(|\/\*|\*\//.test(value))) {
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Opera will produce 700 instead of bold in their style values
- if (name === 'font-weight' && value === '700') {
- value = 'bold';
- } else if (name === 'color' || name === 'background-color') { // Lowercase colors like RED
- value = value.toLowerCase();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Opera will produce 700 instead of bold in their style values
+ if (name === 'font-weight' && value === '700') {
+ value = 'bold';
+ } else if (name === 'color' || name === 'background-color') { // Lowercase colors like RED
+ value = value.toLowerCase();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Convert RGB colors to HEX
- value = value.replace(rgbRegExp, toHex);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Convert RGB colors to HEX
+ value = value.replace(rgbRegExp, toHex);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Convert URLs and force them into url('value') format
- value = value.replace(urlOrStrRegExp, processUrl);
- styles[name] = isEncoded ? decode(value, true) : value;
- }
- }
- // Compress the styles to reduce it's size for example IE will expand styles
- compress("border", "", true);
- compress("border", "-width");
- compress("border", "-color");
- compress("border", "-style");
- compress("padding", "");
- compress("margin", "");
- compress2('border', 'border-width', 'border-style', 'border-color');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Convert URLs and force them into url('value') format
+ value = value.replace(urlOrStrRegExp, processUrl);
+ styles[name] = isEncoded ? decode(value, true) : value;
+ }
+ }
+ // Compress the styles to reduce it's size for example IE will expand styles
+ compress("border", "", true);
+ compress("border", "-width");
+ compress("border", "-color");
+ compress("border", "-style");
+ compress("padding", "");
+ compress("margin", "");
+ compress2('border', 'border-width', 'border-style', 'border-color');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove pointless border, IE produces these
- if (styles.border === 'medium none') {
- delete styles.border;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove pointless border, IE produces these
+ if (styles.border === 'medium none') {
+ delete styles.border;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // IE 11 will produce a border-image: none when getting the style attribute from <p style="border: 1px solid red"></p>
- // So let us assume it shouldn't be there
- if (styles['border-image'] === 'none') {
- delete styles['border-image'];
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // IE 11 will produce a border-image: none when getting the style attribute from <p style="border: 1px solid red"></p>
+ // So let us assume it shouldn't be there
+ if (styles['border-image'] === 'none') {
+ delete styles['border-image'];
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return styles;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return styles;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Serializes the specified style object into a string.
- *
- * @method serialize
- * @param {Object} styles Object to serialize as string for example: {border: '1px solid red'}
- * @param {String} elementName Optional element name, if specified only the styles that matches the schema will be serialized.
- * @return {String} String representation of the style object for example: border: 1px solid red.
- */
- serialize: function(styles, elementName) {
- var css = '', name, value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Serializes the specified style object into a string.
+ *
+ * @method serialize
+ * @param {Object} styles Object to serialize as string for example: {border: '1px solid red'}
+ * @param {String} elementName Optional element name, if specified only the styles that matches the schema will be serialized.
+ * @return {String} String representation of the style object for example: border: 1px solid red.
+ */
+ serialize: function (styles, elementName) {
+ var css = '', name, value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function serializeStyles(name) {
- var styleList, i, l, value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function serializeStyles(name) {
+ var styleList, i, l, value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- styleList = validStyles[name];
- if (styleList) {
- for (i = 0, l = styleList.length; i < l; i++) {
- name = styleList[i];
- value = styles[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ styleList = validStyles[name];
+ if (styleList) {
+ for (i = 0, l = styleList.length; i < l; i++) {
+ name = styleList[i];
+ value = styles[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value) {
- css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';';
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value) {
+ css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';';
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isValid(name, elementName) {
- var styleMap;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isValid(name, elementName) {
+ var styleMap;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- styleMap = invalidStyles['*'];
- if (styleMap && styleMap[name]) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ styleMap = invalidStyles['*'];
+ if (styleMap && styleMap[name]) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- styleMap = invalidStyles[elementName];
- if (styleMap && styleMap[name]) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ styleMap = invalidStyles[elementName];
+ if (styleMap && styleMap[name]) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Serialize styles according to schema
- if (elementName && validStyles) {
- // Serialize global styles and element specific styles
- serializeStyles('*');
- serializeStyles(elementName);
- } else {
- // Output the styles in the order they are inside the object
- for (name in styles) {
- value = styles[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Serialize styles according to schema
+ if (elementName && validStyles) {
+ // Serialize global styles and element specific styles
+ serializeStyles('*');
+ serializeStyles(elementName);
+ } else {
+ // Output the styles in the order they are inside the object
+ for (name in styles) {
+ value = styles[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value && (!invalidStyles || isValid(name, elementName))) {
- css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';';
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value && (!invalidStyles || isValid(name, elementName))) {
+ css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';';
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return css;
- }
- };
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return css;
+ }
+ };
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/dom/TreeWalker.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * TreeWalker.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -6159,120 +6172,396 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * console.log(walker.current());
</span><span class="cx" style="display: block; padding: 0 10px"> * } while (walker.next());
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/dom/TreeWalker", [], function() {
- /**
- * Constructs a new TreeWalker instance.
- *
- * @constructor
- * @method TreeWalker
- * @param {Node} startNode Node to start walking from.
- * @param {node} rootNode Optional root node to never walk out of.
- */
- return function(startNode, rootNode) {
- var node = startNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.TreeWalker',
+ [
+ ],
+ function () {
+ /**
+ * Constructs a new TreeWalker instance.
+ *
+ * @constructor
+ * @method TreeWalker
+ * @param {Node} startNode Node to start walking from.
+ * @param {node} rootNode Optional root node to never walk out of.
+ */
+ return function (startNode, rootNode) {
+ var node = startNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function findSibling(node, startName, siblingName, shallow) {
- var sibling, parent;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function findSibling(node, startName, siblingName, shallow) {
+ var sibling, parent;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node) {
- // Walk into nodes if it has a start
- if (!shallow && node[startName]) {
- return node[startName];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node) {
+ // Walk into nodes if it has a start
+ if (!shallow && node[startName]) {
+ return node[startName];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Return the sibling if it has one
- if (node != rootNode) {
- sibling = node[siblingName];
- if (sibling) {
- return sibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Return the sibling if it has one
+ if (node != rootNode) {
+ sibling = node[siblingName];
+ if (sibling) {
+ return sibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Walk up the parents to look for siblings
- for (parent = node.parentNode; parent && parent != rootNode; parent = parent.parentNode) {
- sibling = parent[siblingName];
- if (sibling) {
- return sibling;
- }
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Walk up the parents to look for siblings
+ for (parent = node.parentNode; parent && parent != rootNode; parent = parent.parentNode) {
+ sibling = parent[siblingName];
+ if (sibling) {
+ return sibling;
+ }
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function findPreviousNode(node, startName, siblingName, shallow) {
- var sibling, parent, child;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function findPreviousNode(node, startName, siblingName, shallow) {
+ var sibling, parent, child;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node) {
- sibling = node[siblingName];
- if (rootNode && sibling === rootNode) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node) {
+ sibling = node[siblingName];
+ if (rootNode && sibling === rootNode) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (sibling) {
- if (!shallow) {
- // Walk up the parents to look for siblings
- for (child = sibling[startName]; child; child = child[startName]) {
- if (!child[startName]) {
- return child;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (sibling) {
+ if (!shallow) {
+ // Walk up the parents to look for siblings
+ for (child = sibling[startName]; child; child = child[startName]) {
+ if (!child[startName]) {
+ return child;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return sibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return sibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parent = node.parentNode;
- if (parent && parent !== rootNode) {
- return parent;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parent = node.parentNode;
+ if (parent && parent !== rootNode) {
+ return parent;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the current node.
- *
- * @method current
- * @return {Node} Current node where the walker is.
- */
- this.current = function() {
- return node;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the current node.
+ *
+ * @method current
+ * @return {Node} Current node where the walker is.
+ */
+ this.current = function () {
+ return node;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Walks to the next node in tree.
- *
- * @method next
- * @return {Node} Current node where the walker is after moving to the next node.
- */
- this.next = function(shallow) {
- node = findSibling(node, 'firstChild', 'nextSibling', shallow);
- return node;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Walks to the next node in tree.
+ *
+ * @method next
+ * @return {Node} Current node where the walker is after moving to the next node.
+ */
+ this.next = function (shallow) {
+ node = findSibling(node, 'firstChild', 'nextSibling', shallow);
+ return node;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Walks to the previous node in tree.
- *
- * @method prev
- * @return {Node} Current node where the walker is after moving to the previous node.
- */
- this.prev = function(shallow) {
- node = findSibling(node, 'lastChild', 'previousSibling', shallow);
- return node;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Walks to the previous node in tree.
+ *
+ * @method prev
+ * @return {Node} Current node where the walker is after moving to the previous node.
+ */
+ this.prev = function (shallow) {
+ node = findSibling(node, 'lastChild', 'previousSibling', shallow);
+ return node;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.prev2 = function(shallow) {
- node = findPreviousNode(node, 'lastChild', 'previousSibling', shallow);
- return node;
- };
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.prev2 = function (shallow) {
+ node = findPreviousNode(node, 'lastChild', 'previousSibling', shallow);
+ return node;
+ };
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/dom/Range.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Entities.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/*jshint bitwise:false */
+/*eslint no-bitwise:0 */
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Entity encoder class.
+ *
+ * @class tinymce.html.Entities
+ * @static
+ * @version 3.4
+ */
+define(
+ 'tinymce.core.html.Entities',
+ [
+ "tinymce.core.util.Tools"
+ ],
+ function (Tools) {
+ var makeMap = Tools.makeMap;
+
+ var namedEntities, baseEntities, reverseEntities,
+ attrsCharsRegExp = /[&<>\"\u0060\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
+ textCharsRegExp = /[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
+ rawCharsRegExp = /[<>&\"\']/g,
+ entityRegExp = /&#([a-z0-9]+);?|&([a-z0-9]+);/gi,
+ asciiMap = {
+ 128: "\u20AC", 130: "\u201A", 131: "\u0192", 132: "\u201E", 133: "\u2026", 134: "\u2020",
+ 135: "\u2021", 136: "\u02C6", 137: "\u2030", 138: "\u0160", 139: "\u2039", 140: "\u0152",
+ 142: "\u017D", 145: "\u2018", 146: "\u2019", 147: "\u201C", 148: "\u201D", 149: "\u2022",
+ 150: "\u2013", 151: "\u2014", 152: "\u02DC", 153: "\u2122", 154: "\u0161", 155: "\u203A",
+ 156: "\u0153", 158: "\u017E", 159: "\u0178"
+ };
+
+ // Raw entities
+ baseEntities = {
+ '\"': '"', // Needs to be escaped since the YUI compressor would otherwise break the code
+ "'": ''',
+ '<': '<',
+ '>': '>',
+ '&': '&',
+ '\u0060': '`'
+ };
+
+ // Reverse lookup table for raw entities
+ reverseEntities = {
+ '<': '<',
+ '>': '>',
+ '&': '&',
+ '"': '"',
+ ''': "'"
+ };
+
+ // Decodes text by using the browser
+ function nativeDecode(text) {
+ var elm;
+
+ elm = document.createElement("div");
+ elm.innerHTML = text;
+
+ return elm.textContent || elm.innerText || text;
+ }
+
+ // Build a two way lookup table for the entities
+ function buildEntitiesLookup(items, radix) {
+ var i, chr, entity, lookup = {};
+
+ if (items) {
+ items = items.split(',');
+ radix = radix || 10;
+
+ // Build entities lookup table
+ for (i = 0; i < items.length; i += 2) {
+ chr = String.fromCharCode(parseInt(items[i], radix));
+
+ // Only add non base entities
+ if (!baseEntities[chr]) {
+ entity = '&' + items[i + 1] + ';';
+ lookup[chr] = entity;
+ lookup[entity] = chr;
+ }
+ }
+
+ return lookup;
+ }
+ }
+
+ // Unpack entities lookup where the numbers are in radix 32 to reduce the size
+ namedEntities = buildEntitiesLookup(
+ '50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,' +
+ '5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,' +
+ '5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,' +
+ '5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,' +
+ '68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,' +
+ '6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,' +
+ '6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,' +
+ '75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,' +
+ '7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,' +
+ '7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,' +
+ 'sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,' +
+ 'st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,' +
+ 't9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,' +
+ 'tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,' +
+ 'u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,' +
+ '81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,' +
+ '8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,' +
+ '8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,' +
+ '8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,' +
+ '8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,' +
+ 'nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,' +
+ 'rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,' +
+ 'Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,' +
+ '80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,' +
+ '811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro', 32);
+
+ var Entities = {
+ /**
+ * Encodes the specified string using raw entities. This means only the required XML base entities will be encoded.
+ *
+ * @method encodeRaw
+ * @param {String} text Text to encode.
+ * @param {Boolean} attr Optional flag to specify if the text is attribute contents.
+ * @return {String} Entity encoded text.
+ */
+ encodeRaw: function (text, attr) {
+ return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function (chr) {
+ return baseEntities[chr] || chr;
+ });
+ },
+
+ /**
+ * Encoded the specified text with both the attributes and text entities. This function will produce larger text contents
+ * since it doesn't know if the context is within a attribute or text node. This was added for compatibility
+ * and is exposed as the DOMUtils.encode function.
+ *
+ * @method encodeAllRaw
+ * @param {String} text Text to encode.
+ * @return {String} Entity encoded text.
+ */
+ encodeAllRaw: function (text) {
+ return ('' + text).replace(rawCharsRegExp, function (chr) {
+ return baseEntities[chr] || chr;
+ });
+ },
+
+ /**
+ * Encodes the specified string using numeric entities. The core entities will be
+ * encoded as named ones but all non lower ascii characters will be encoded into numeric entities.
+ *
+ * @method encodeNumeric
+ * @param {String} text Text to encode.
+ * @param {Boolean} attr Optional flag to specify if the text is attribute contents.
+ * @return {String} Entity encoded text.
+ */
+ encodeNumeric: function (text, attr) {
+ return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function (chr) {
+ // Multi byte sequence convert it to a single entity
+ if (chr.length > 1) {
+ return '&#' + (((chr.charCodeAt(0) - 0xD800) * 0x400) + (chr.charCodeAt(1) - 0xDC00) + 0x10000) + ';';
+ }
+
+ return baseEntities[chr] || '&#' + chr.charCodeAt(0) + ';';
+ });
+ },
+
+ /**
+ * Encodes the specified string using named entities. The core entities will be encoded
+ * as named ones but all non lower ascii characters will be encoded into named entities.
+ *
+ * @method encodeNamed
+ * @param {String} text Text to encode.
+ * @param {Boolean} attr Optional flag to specify if the text is attribute contents.
+ * @param {Object} entities Optional parameter with entities to use.
+ * @return {String} Entity encoded text.
+ */
+ encodeNamed: function (text, attr, entities) {
+ entities = entities || namedEntities;
+
+ return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function (chr) {
+ return baseEntities[chr] || entities[chr] || chr;
+ });
+ },
+
+ /**
+ * Returns an encode function based on the name(s) and it's optional entities.
+ *
+ * @method getEncodeFunc
+ * @param {String} name Comma separated list of encoders for example named,numeric.
+ * @param {String} entities Optional parameter with entities to use instead of the built in set.
+ * @return {function} Encode function to be used.
+ */
+ getEncodeFunc: function (name, entities) {
+ entities = buildEntitiesLookup(entities) || namedEntities;
+
+ function encodeNamedAndNumeric(text, attr) {
+ return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function (chr) {
+ return baseEntities[chr] || entities[chr] || '&#' + chr.charCodeAt(0) + ';' || chr;
+ });
+ }
+
+ function encodeCustomNamed(text, attr) {
+ return Entities.encodeNamed(text, attr, entities);
+ }
+
+ // Replace + with , to be compatible with previous TinyMCE versions
+ name = makeMap(name.replace(/\+/g, ','));
+
+ // Named and numeric encoder
+ if (name.named && name.numeric) {
+ return encodeNamedAndNumeric;
+ }
+
+ // Named encoder
+ if (name.named) {
+ // Custom names
+ if (entities) {
+ return encodeCustomNamed;
+ }
+
+ return Entities.encodeNamed;
+ }
+
+ // Numeric
+ if (name.numeric) {
+ return Entities.encodeNumeric;
+ }
+
+ // Raw encoder
+ return Entities.encodeRaw;
+ },
+
+ /**
+ * Decodes the specified string, this will replace entities with raw UTF characters.
+ *
+ * @method decode
+ * @param {String} text Text to entity decode.
+ * @return {String} Entity decoded string.
+ */
+ decode: function (text) {
+ return text.replace(entityRegExp, function (all, numeric) {
+ if (numeric) {
+ if (numeric.charAt(0).toLowerCase() === 'x') {
+ numeric = parseInt(numeric.substr(1), 16);
+ } else {
+ numeric = parseInt(numeric, 10);
+ }
+
+ // Support upper UTF
+ if (numeric > 0xFFFF) {
+ numeric -= 0x10000;
+
+ return String.fromCharCode(0xD800 + (numeric >> 10), 0xDC00 + (numeric & 0x3FF));
+ }
+
+ return asciiMap[numeric] || String.fromCharCode(numeric);
+ }
+
+ return reverseEntities[all] || namedEntities[all] || nativeDecode(all);
+ });
+ }
+ };
+
+ return Entities;
+ }
+);
+
+/**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Range.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -6284,1247 +6573,3020 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.dom.Range
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/dom/Range", [
- "tinymce/util/Tools"
-], function(Tools) {
- // Range constructor
- function Range(dom) {
- var self = this,
- doc = dom.doc,
- EXTRACT = 0,
- CLONE = 1,
- DELETE = 2,
- TRUE = true,
- FALSE = false,
- START_OFFSET = 'startOffset',
- START_CONTAINER = 'startContainer',
- END_CONTAINER = 'endContainer',
- END_OFFSET = 'endOffset',
- extend = Tools.extend,
- nodeIndex = dom.nodeIndex;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.Range',
+ [
+ "tinymce.core.util.Tools"
+ ],
+ function (Tools) {
+ // Range constructor
+ function Range(dom) {
+ var self = this,
+ doc = dom.doc,
+ EXTRACT = 0,
+ CLONE = 1,
+ DELETE = 2,
+ TRUE = true,
+ FALSE = false,
+ START_OFFSET = 'startOffset',
+ START_CONTAINER = 'startContainer',
+ END_CONTAINER = 'endContainer',
+ END_OFFSET = 'endOffset',
+ extend = Tools.extend,
+ nodeIndex = dom.nodeIndex;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function createDocumentFragment() {
- return doc.createDocumentFragment();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function createDocumentFragment() {
+ return doc.createDocumentFragment();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setStart(n, o) {
- _setEndPoint(TRUE, n, o);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setStart(n, o) {
+ _setEndPoint(TRUE, n, o);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setEnd(n, o) {
- _setEndPoint(FALSE, n, o);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setEnd(n, o) {
+ _setEndPoint(FALSE, n, o);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setStartBefore(n) {
- setStart(n.parentNode, nodeIndex(n));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setStartBefore(n) {
+ setStart(n.parentNode, nodeIndex(n));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setStartAfter(n) {
- setStart(n.parentNode, nodeIndex(n) + 1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setStartAfter(n) {
+ setStart(n.parentNode, nodeIndex(n) + 1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setEndBefore(n) {
- setEnd(n.parentNode, nodeIndex(n));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setEndBefore(n) {
+ setEnd(n.parentNode, nodeIndex(n));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setEndAfter(n) {
- setEnd(n.parentNode, nodeIndex(n) + 1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setEndAfter(n) {
+ setEnd(n.parentNode, nodeIndex(n) + 1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function collapse(ts) {
- if (ts) {
- self[END_CONTAINER] = self[START_CONTAINER];
- self[END_OFFSET] = self[START_OFFSET];
- } else {
- self[START_CONTAINER] = self[END_CONTAINER];
- self[START_OFFSET] = self[END_OFFSET];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function collapse(ts) {
+ if (ts) {
+ self[END_CONTAINER] = self[START_CONTAINER];
+ self[END_OFFSET] = self[START_OFFSET];
+ } else {
+ self[START_CONTAINER] = self[END_CONTAINER];
+ self[START_OFFSET] = self[END_OFFSET];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.collapsed = TRUE;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.collapsed = TRUE;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function selectNode(n) {
- setStartBefore(n);
- setEndAfter(n);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function selectNode(n) {
+ setStartBefore(n);
+ setEndAfter(n);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function selectNodeContents(n) {
- setStart(n, 0);
- setEnd(n, n.nodeType === 1 ? n.childNodes.length : n.nodeValue.length);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function selectNodeContents(n) {
+ setStart(n, 0);
+ setEnd(n, n.nodeType === 1 ? n.childNodes.length : n.nodeValue.length);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function compareBoundaryPoints(h, r) {
- var sc = self[START_CONTAINER], so = self[START_OFFSET], ec = self[END_CONTAINER], eo = self[END_OFFSET],
- rsc = r.startContainer, rso = r.startOffset, rec = r.endContainer, reo = r.endOffset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function compareBoundaryPoints(h, r) {
+ var sc = self[START_CONTAINER], so = self[START_OFFSET], ec = self[END_CONTAINER], eo = self[END_OFFSET],
+ rsc = r.startContainer, rso = r.startOffset, rec = r.endContainer, reo = r.endOffset;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check START_TO_START
- if (h === 0) {
- return _compareBoundaryPoints(sc, so, rsc, rso);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check START_TO_START
+ if (h === 0) {
+ return _compareBoundaryPoints(sc, so, rsc, rso);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check START_TO_END
- if (h === 1) {
- return _compareBoundaryPoints(ec, eo, rsc, rso);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check START_TO_END
+ if (h === 1) {
+ return _compareBoundaryPoints(ec, eo, rsc, rso);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check END_TO_END
- if (h === 2) {
- return _compareBoundaryPoints(ec, eo, rec, reo);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check END_TO_END
+ if (h === 2) {
+ return _compareBoundaryPoints(ec, eo, rec, reo);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check END_TO_START
- if (h === 3) {
- return _compareBoundaryPoints(sc, so, rec, reo);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check END_TO_START
+ if (h === 3) {
+ return _compareBoundaryPoints(sc, so, rec, reo);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function deleteContents() {
- _traverse(DELETE);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function deleteContents() {
+ _traverse(DELETE);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function extractContents() {
- return _traverse(EXTRACT);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function extractContents() {
+ return _traverse(EXTRACT);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function cloneContents() {
- return _traverse(CLONE);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function cloneContents() {
+ return _traverse(CLONE);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function insertNode(n) {
- var startContainer = this[START_CONTAINER],
- startOffset = this[START_OFFSET], nn, o;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function insertNode(n) {
+ var startContainer = this[START_CONTAINER],
+ startOffset = this[START_OFFSET], nn, o;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Node is TEXT_NODE or CDATA
- if ((startContainer.nodeType === 3 || startContainer.nodeType === 4) && startContainer.nodeValue) {
- if (!startOffset) {
- // At the start of text
- startContainer.parentNode.insertBefore(n, startContainer);
- } else if (startOffset >= startContainer.nodeValue.length) {
- // At the end of text
- dom.insertAfter(n, startContainer);
- } else {
- // Middle, need to split
- nn = startContainer.splitText(startOffset);
- startContainer.parentNode.insertBefore(n, nn);
- }
- } else {
- // Insert element node
- if (startContainer.childNodes.length > 0) {
- o = startContainer.childNodes[startOffset];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Node is TEXT_NODE or CDATA
+ if ((startContainer.nodeType === 3 || startContainer.nodeType === 4) && startContainer.nodeValue) {
+ if (!startOffset) {
+ // At the start of text
+ startContainer.parentNode.insertBefore(n, startContainer);
+ } else if (startOffset >= startContainer.nodeValue.length) {
+ // At the end of text
+ dom.insertAfter(n, startContainer);
+ } else {
+ // Middle, need to split
+ nn = startContainer.splitText(startOffset);
+ startContainer.parentNode.insertBefore(n, nn);
+ }
+ } else {
+ // Insert element node
+ if (startContainer.childNodes.length > 0) {
+ o = startContainer.childNodes[startOffset];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (o) {
- startContainer.insertBefore(n, o);
- } else {
- if (startContainer.nodeType == 3) {
- dom.insertAfter(n, startContainer);
- } else {
- startContainer.appendChild(n);
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (o) {
+ startContainer.insertBefore(n, o);
+ } else {
+ if (startContainer.nodeType == 3) {
+ dom.insertAfter(n, startContainer);
+ } else {
+ startContainer.appendChild(n);
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function surroundContents(n) {
- var f = self.extractContents();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function surroundContents(n) {
+ var f = self.extractContents();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.insertNode(n);
- n.appendChild(f);
- self.selectNode(n);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.insertNode(n);
+ n.appendChild(f);
+ self.selectNode(n);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function cloneRange() {
- return extend(new Range(dom), {
- startContainer: self[START_CONTAINER],
- startOffset: self[START_OFFSET],
- endContainer: self[END_CONTAINER],
- endOffset: self[END_OFFSET],
- collapsed: self.collapsed,
- commonAncestorContainer: self.commonAncestorContainer
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function cloneRange() {
+ return extend(new Range(dom), {
+ startContainer: self[START_CONTAINER],
+ startOffset: self[START_OFFSET],
+ endContainer: self[END_CONTAINER],
+ endOffset: self[END_OFFSET],
+ collapsed: self.collapsed,
+ commonAncestorContainer: self.commonAncestorContainer
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Private methods
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Private methods
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function _getSelectedNode(container, offset) {
- var child;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function _getSelectedNode(container, offset) {
+ var child;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // TEXT_NODE
- if (container.nodeType == 3) {
- return container;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // TEXT_NODE
+ if (container.nodeType == 3) {
+ return container;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (offset < 0) {
- return container;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (offset < 0) {
+ return container;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- child = container.firstChild;
- while (child && offset > 0) {
- --offset;
- child = child.nextSibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ child = container.firstChild;
+ while (child && offset > 0) {
+ --offset;
+ child = child.nextSibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (child) {
- return child;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (child) {
+ return child;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return container;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return container;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function _isCollapsed() {
- return (self[START_CONTAINER] == self[END_CONTAINER] && self[START_OFFSET] == self[END_OFFSET]);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function _isCollapsed() {
+ return (self[START_CONTAINER] == self[END_CONTAINER] && self[START_OFFSET] == self[END_OFFSET]);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function _compareBoundaryPoints(containerA, offsetA, containerB, offsetB) {
- var c, offsetC, n, cmnRoot, childA, childB;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function _compareBoundaryPoints(containerA, offsetA, containerB, offsetB) {
+ var c, offsetC, n, cmnRoot, childA, childB;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // In the first case the boundary-points have the same container. A is before B
- // if its offset is less than the offset of B, A is equal to B if its offset is
- // equal to the offset of B, and A is after B if its offset is greater than the
- // offset of B.
- if (containerA == containerB) {
- if (offsetA == offsetB) {
- return 0; // equal
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // In the first case the boundary-points have the same container. A is before B
+ // if its offset is less than the offset of B, A is equal to B if its offset is
+ // equal to the offset of B, and A is after B if its offset is greater than the
+ // offset of B.
+ if (containerA == containerB) {
+ if (offsetA == offsetB) {
+ return 0; // equal
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (offsetA < offsetB) {
- return -1; // before
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (offsetA < offsetB) {
+ return -1; // before
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return 1; // after
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return 1; // after
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // In the second case a child node C of the container of A is an ancestor
- // container of B. In this case, A is before B if the offset of A is less than or
- // equal to the index of the child node C and A is after B otherwise.
- c = containerB;
- while (c && c.parentNode != containerA) {
- c = c.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // In the second case a child node C of the container of A is an ancestor
+ // container of B. In this case, A is before B if the offset of A is less than or
+ // equal to the index of the child node C and A is after B otherwise.
+ c = containerB;
+ while (c && c.parentNode != containerA) {
+ c = c.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (c) {
- offsetC = 0;
- n = containerA.firstChild;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (c) {
+ offsetC = 0;
+ n = containerA.firstChild;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (n != c && offsetC < offsetA) {
- offsetC++;
- n = n.nextSibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (n != c && offsetC < offsetA) {
+ offsetC++;
+ n = n.nextSibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (offsetA <= offsetC) {
- return -1; // before
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (offsetA <= offsetC) {
+ return -1; // before
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return 1; // after
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return 1; // after
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // In the third case a child node C of the container of B is an ancestor container
- // of A. In this case, A is before B if the index of the child node C is less than
- // the offset of B and A is after B otherwise.
- c = containerA;
- while (c && c.parentNode != containerB) {
- c = c.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // In the third case a child node C of the container of B is an ancestor container
+ // of A. In this case, A is before B if the index of the child node C is less than
+ // the offset of B and A is after B otherwise.
+ c = containerA;
+ while (c && c.parentNode != containerB) {
+ c = c.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (c) {
- offsetC = 0;
- n = containerB.firstChild;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (c) {
+ offsetC = 0;
+ n = containerB.firstChild;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (n != c && offsetC < offsetB) {
- offsetC++;
- n = n.nextSibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (n != c && offsetC < offsetB) {
+ offsetC++;
+ n = n.nextSibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (offsetC < offsetB) {
- return -1; // before
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (offsetC < offsetB) {
+ return -1; // before
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return 1; // after
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return 1; // after
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // In the fourth case, none of three other cases hold: the containers of A and B
- // are siblings or descendants of sibling nodes. In this case, A is before B if
- // the container of A is before the container of B in a pre-order traversal of the
- // Ranges' context tree and A is after B otherwise.
- cmnRoot = dom.findCommonAncestor(containerA, containerB);
- childA = containerA;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // In the fourth case, none of three other cases hold: the containers of A and B
+ // are siblings or descendants of sibling nodes. In this case, A is before B if
+ // the container of A is before the container of B in a pre-order traversal of the
+ // Ranges' context tree and A is after B otherwise.
+ cmnRoot = dom.findCommonAncestor(containerA, containerB);
+ childA = containerA;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (childA && childA.parentNode != cmnRoot) {
- childA = childA.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (childA && childA.parentNode != cmnRoot) {
+ childA = childA.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!childA) {
- childA = cmnRoot;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!childA) {
+ childA = cmnRoot;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- childB = containerB;
- while (childB && childB.parentNode != cmnRoot) {
- childB = childB.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ childB = containerB;
+ while (childB && childB.parentNode != cmnRoot) {
+ childB = childB.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!childB) {
- childB = cmnRoot;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!childB) {
+ childB = cmnRoot;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (childA == childB) {
- return 0; // equal
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (childA == childB) {
+ return 0; // equal
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- n = cmnRoot.firstChild;
- while (n) {
- if (n == childA) {
- return -1; // before
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ n = cmnRoot.firstChild;
+ while (n) {
+ if (n == childA) {
+ return -1; // before
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (n == childB) {
- return 1; // after
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (n == childB) {
+ return 1; // after
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- n = n.nextSibling;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ n = n.nextSibling;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function _setEndPoint(st, n, o) {
- var ec, sc;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function _setEndPoint(st, n, o) {
+ var ec, sc;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (st) {
- self[START_CONTAINER] = n;
- self[START_OFFSET] = o;
- } else {
- self[END_CONTAINER] = n;
- self[END_OFFSET] = o;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (st) {
+ self[START_CONTAINER] = n;
+ self[START_OFFSET] = o;
+ } else {
+ self[END_CONTAINER] = n;
+ self[END_OFFSET] = o;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If one boundary-point of a Range is set to have a root container
- // other than the current one for the Range, the Range is collapsed to
- // the new position. This enforces the restriction that both boundary-
- // points of a Range must have the same root container.
- ec = self[END_CONTAINER];
- while (ec.parentNode) {
- ec = ec.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If one boundary-point of a Range is set to have a root container
+ // other than the current one for the Range, the Range is collapsed to
+ // the new position. This enforces the restriction that both boundary-
+ // points of a Range must have the same root container.
+ ec = self[END_CONTAINER];
+ while (ec.parentNode) {
+ ec = ec.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- sc = self[START_CONTAINER];
- while (sc.parentNode) {
- sc = sc.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ sc = self[START_CONTAINER];
+ while (sc.parentNode) {
+ sc = sc.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (sc == ec) {
- // The start position of a Range is guaranteed to never be after the
- // end position. To enforce this restriction, if the start is set to
- // be at a position after the end, the Range is collapsed to that
- // position.
- if (_compareBoundaryPoints(self[START_CONTAINER], self[START_OFFSET], self[END_CONTAINER], self[END_OFFSET]) > 0) {
- self.collapse(st);
- }
- } else {
- self.collapse(st);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (sc == ec) {
+ // The start position of a Range is guaranteed to never be after the
+ // end position. To enforce this restriction, if the start is set to
+ // be at a position after the end, the Range is collapsed to that
+ // position.
+ if (_compareBoundaryPoints(self[START_CONTAINER], self[START_OFFSET], self[END_CONTAINER], self[END_OFFSET]) > 0) {
+ self.collapse(st);
+ }
+ } else {
+ self.collapse(st);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.collapsed = _isCollapsed();
- self.commonAncestorContainer = dom.findCommonAncestor(self[START_CONTAINER], self[END_CONTAINER]);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.collapsed = _isCollapsed();
+ self.commonAncestorContainer = dom.findCommonAncestor(self[START_CONTAINER], self[END_CONTAINER]);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function _traverse(how) {
- var c, endContainerDepth = 0, startContainerDepth = 0, p, depthDiff, startNode, endNode, sp, ep;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function _traverse(how) {
+ var c, endContainerDepth = 0, startContainerDepth = 0, p, depthDiff, startNode, endNode, sp, ep;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self[START_CONTAINER] == self[END_CONTAINER]) {
- return _traverseSameContainer(how);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self[START_CONTAINER] == self[END_CONTAINER]) {
+ return _traverseSameContainer(how);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (c = self[END_CONTAINER], p = c.parentNode; p; c = p, p = p.parentNode) {
- if (p == self[START_CONTAINER]) {
- return _traverseCommonStartContainer(c, how);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (c = self[END_CONTAINER], p = c.parentNode; p; c = p, p = p.parentNode) {
+ if (p == self[START_CONTAINER]) {
+ return _traverseCommonStartContainer(c, how);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ++endContainerDepth;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ++endContainerDepth;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (c = self[START_CONTAINER], p = c.parentNode; p; c = p, p = p.parentNode) {
- if (p == self[END_CONTAINER]) {
- return _traverseCommonEndContainer(c, how);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (c = self[START_CONTAINER], p = c.parentNode; p; c = p, p = p.parentNode) {
+ if (p == self[END_CONTAINER]) {
+ return _traverseCommonEndContainer(c, how);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ++startContainerDepth;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ++startContainerDepth;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- depthDiff = startContainerDepth - endContainerDepth;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ depthDiff = startContainerDepth - endContainerDepth;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- startNode = self[START_CONTAINER];
- while (depthDiff > 0) {
- startNode = startNode.parentNode;
- depthDiff--;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ startNode = self[START_CONTAINER];
+ while (depthDiff > 0) {
+ startNode = startNode.parentNode;
+ depthDiff--;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- endNode = self[END_CONTAINER];
- while (depthDiff < 0) {
- endNode = endNode.parentNode;
- depthDiff++;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ endNode = self[END_CONTAINER];
+ while (depthDiff < 0) {
+ endNode = endNode.parentNode;
+ depthDiff++;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // ascend the ancestor hierarchy until we have a common parent.
- for (sp = startNode.parentNode, ep = endNode.parentNode; sp != ep; sp = sp.parentNode, ep = ep.parentNode) {
- startNode = sp;
- endNode = ep;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // ascend the ancestor hierarchy until we have a common parent.
+ for (sp = startNode.parentNode, ep = endNode.parentNode; sp != ep; sp = sp.parentNode, ep = ep.parentNode) {
+ startNode = sp;
+ endNode = ep;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return _traverseCommonAncestors(startNode, endNode, how);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return _traverseCommonAncestors(startNode, endNode, how);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function _traverseSameContainer(how) {
- var frag, s, sub, n, cnt, sibling, xferNode, start, len;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function _traverseSameContainer(how) {
+ var frag, s, sub, n, cnt, sibling, xferNode, start, len;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (how != DELETE) {
- frag = createDocumentFragment();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (how != DELETE) {
+ frag = createDocumentFragment();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If selection is empty, just return the fragment
- if (self[START_OFFSET] == self[END_OFFSET]) {
- return frag;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If selection is empty, just return the fragment
+ if (self[START_OFFSET] == self[END_OFFSET]) {
+ return frag;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Text node needs special case handling
- if (self[START_CONTAINER].nodeType == 3) { // TEXT_NODE
- // get the substring
- s = self[START_CONTAINER].nodeValue;
- sub = s.substring(self[START_OFFSET], self[END_OFFSET]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Text node needs special case handling
+ if (self[START_CONTAINER].nodeType == 3) { // TEXT_NODE
+ // get the substring
+ s = self[START_CONTAINER].nodeValue;
+ sub = s.substring(self[START_OFFSET], self[END_OFFSET]);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // set the original text node to its new value
- if (how != CLONE) {
- n = self[START_CONTAINER];
- start = self[START_OFFSET];
- len = self[END_OFFSET] - self[START_OFFSET];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // set the original text node to its new value
+ if (how != CLONE) {
+ n = self[START_CONTAINER];
+ start = self[START_OFFSET];
+ len = self[END_OFFSET] - self[START_OFFSET];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (start === 0 && len >= n.nodeValue.length - 1) {
- n.parentNode.removeChild(n);
- } else {
- n.deleteData(start, len);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (start === 0 && len >= n.nodeValue.length - 1) {
+ n.parentNode.removeChild(n);
+ } else {
+ n.deleteData(start, len);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Nothing is partially selected, so collapse to start point
- self.collapse(TRUE);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Nothing is partially selected, so collapse to start point
+ self.collapse(TRUE);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (how == DELETE) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (how == DELETE) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (sub.length > 0) {
- frag.appendChild(doc.createTextNode(sub));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (sub.length > 0) {
+ frag.appendChild(doc.createTextNode(sub));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return frag;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return frag;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Copy nodes between the start/end offsets.
- n = _getSelectedNode(self[START_CONTAINER], self[START_OFFSET]);
- cnt = self[END_OFFSET] - self[START_OFFSET];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Copy nodes between the start/end offsets.
+ n = _getSelectedNode(self[START_CONTAINER], self[START_OFFSET]);
+ cnt = self[END_OFFSET] - self[START_OFFSET];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (n && cnt > 0) {
- sibling = n.nextSibling;
- xferNode = _traverseFullySelected(n, how);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (n && cnt > 0) {
+ sibling = n.nextSibling;
+ xferNode = _traverseFullySelected(n, how);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (frag) {
- frag.appendChild(xferNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (frag) {
+ frag.appendChild(xferNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- --cnt;
- n = sibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ --cnt;
+ n = sibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Nothing is partially selected, so collapse to start point
- if (how != CLONE) {
- self.collapse(TRUE);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Nothing is partially selected, so collapse to start point
+ if (how != CLONE) {
+ self.collapse(TRUE);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return frag;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return frag;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function _traverseCommonStartContainer(endAncestor, how) {
- var frag, n, endIdx, cnt, sibling, xferNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function _traverseCommonStartContainer(endAncestor, how) {
+ var frag, n, endIdx, cnt, sibling, xferNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (how != DELETE) {
- frag = createDocumentFragment();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (how != DELETE) {
+ frag = createDocumentFragment();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- n = _traverseRightBoundary(endAncestor, how);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ n = _traverseRightBoundary(endAncestor, how);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (frag) {
- frag.appendChild(n);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (frag) {
+ frag.appendChild(n);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- endIdx = nodeIndex(endAncestor);
- cnt = endIdx - self[START_OFFSET];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ endIdx = nodeIndex(endAncestor);
+ cnt = endIdx - self[START_OFFSET];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (cnt <= 0) {
- // Collapse to just before the endAncestor, which
- // is partially selected.
- if (how != CLONE) {
- self.setEndBefore(endAncestor);
- self.collapse(FALSE);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (cnt <= 0) {
+ // Collapse to just before the endAncestor, which
+ // is partially selected.
+ if (how != CLONE) {
+ self.setEndBefore(endAncestor);
+ self.collapse(FALSE);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return frag;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return frag;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- n = endAncestor.previousSibling;
- while (cnt > 0) {
- sibling = n.previousSibling;
- xferNode = _traverseFullySelected(n, how);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ n = endAncestor.previousSibling;
+ while (cnt > 0) {
+ sibling = n.previousSibling;
+ xferNode = _traverseFullySelected(n, how);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (frag) {
- frag.insertBefore(xferNode, frag.firstChild);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (frag) {
+ frag.insertBefore(xferNode, frag.firstChild);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- --cnt;
- n = sibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ --cnt;
+ n = sibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Collapse to just before the endAncestor, which
- // is partially selected.
- if (how != CLONE) {
- self.setEndBefore(endAncestor);
- self.collapse(FALSE);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Collapse to just before the endAncestor, which
+ // is partially selected.
+ if (how != CLONE) {
+ self.setEndBefore(endAncestor);
+ self.collapse(FALSE);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return frag;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return frag;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function _traverseCommonEndContainer(startAncestor, how) {
- var frag, startIdx, n, cnt, sibling, xferNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function _traverseCommonEndContainer(startAncestor, how) {
+ var frag, startIdx, n, cnt, sibling, xferNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (how != DELETE) {
- frag = createDocumentFragment();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (how != DELETE) {
+ frag = createDocumentFragment();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- n = _traverseLeftBoundary(startAncestor, how);
- if (frag) {
- frag.appendChild(n);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ n = _traverseLeftBoundary(startAncestor, how);
+ if (frag) {
+ frag.appendChild(n);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- startIdx = nodeIndex(startAncestor);
- ++startIdx; // Because we already traversed it
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ startIdx = nodeIndex(startAncestor);
+ ++startIdx; // Because we already traversed it
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- cnt = self[END_OFFSET] - startIdx;
- n = startAncestor.nextSibling;
- while (n && cnt > 0) {
- sibling = n.nextSibling;
- xferNode = _traverseFullySelected(n, how);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ cnt = self[END_OFFSET] - startIdx;
+ n = startAncestor.nextSibling;
+ while (n && cnt > 0) {
+ sibling = n.nextSibling;
+ xferNode = _traverseFullySelected(n, how);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (frag) {
- frag.appendChild(xferNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (frag) {
+ frag.appendChild(xferNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- --cnt;
- n = sibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ --cnt;
+ n = sibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (how != CLONE) {
- self.setStartAfter(startAncestor);
- self.collapse(TRUE);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (how != CLONE) {
+ self.setStartAfter(startAncestor);
+ self.collapse(TRUE);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return frag;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return frag;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function _traverseCommonAncestors(startAncestor, endAncestor, how) {
- var n, frag, startOffset, endOffset, cnt, sibling, nextSibling;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function _traverseCommonAncestors(startAncestor, endAncestor, how) {
+ var n, frag, startOffset, endOffset, cnt, sibling, nextSibling;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (how != DELETE) {
- frag = createDocumentFragment();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (how != DELETE) {
+ frag = createDocumentFragment();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- n = _traverseLeftBoundary(startAncestor, how);
- if (frag) {
- frag.appendChild(n);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ n = _traverseLeftBoundary(startAncestor, how);
+ if (frag) {
+ frag.appendChild(n);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- startOffset = nodeIndex(startAncestor);
- endOffset = nodeIndex(endAncestor);
- ++startOffset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ startOffset = nodeIndex(startAncestor);
+ endOffset = nodeIndex(endAncestor);
+ ++startOffset;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- cnt = endOffset - startOffset;
- sibling = startAncestor.nextSibling;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ cnt = endOffset - startOffset;
+ sibling = startAncestor.nextSibling;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (cnt > 0) {
- nextSibling = sibling.nextSibling;
- n = _traverseFullySelected(sibling, how);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (cnt > 0) {
+ nextSibling = sibling.nextSibling;
+ n = _traverseFullySelected(sibling, how);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (frag) {
- frag.appendChild(n);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (frag) {
+ frag.appendChild(n);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- sibling = nextSibling;
- --cnt;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ sibling = nextSibling;
+ --cnt;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- n = _traverseRightBoundary(endAncestor, how);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ n = _traverseRightBoundary(endAncestor, how);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (frag) {
- frag.appendChild(n);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (frag) {
+ frag.appendChild(n);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (how != CLONE) {
- self.setStartAfter(startAncestor);
- self.collapse(TRUE);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (how != CLONE) {
+ self.setStartAfter(startAncestor);
+ self.collapse(TRUE);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return frag;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return frag;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function _traverseRightBoundary(root, how) {
- var next = _getSelectedNode(self[END_CONTAINER], self[END_OFFSET] - 1), parent, clonedParent;
- var prevSibling, clonedChild, clonedGrandParent, isFullySelected = next != self[END_CONTAINER];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function _traverseRightBoundary(root, how) {
+ var next = _getSelectedNode(self[END_CONTAINER], self[END_OFFSET] - 1), parent, clonedParent;
+ var prevSibling, clonedChild, clonedGrandParent, isFullySelected = next != self[END_CONTAINER];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (next == root) {
- return _traverseNode(next, isFullySelected, FALSE, how);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (next == root) {
+ return _traverseNode(next, isFullySelected, FALSE, how);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parent = next.parentNode;
- clonedParent = _traverseNode(parent, FALSE, FALSE, how);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parent = next.parentNode;
+ clonedParent = _traverseNode(parent, FALSE, FALSE, how);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (parent) {
- while (next) {
- prevSibling = next.previousSibling;
- clonedChild = _traverseNode(next, isFullySelected, FALSE, how);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (parent) {
+ while (next) {
+ prevSibling = next.previousSibling;
+ clonedChild = _traverseNode(next, isFullySelected, FALSE, how);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (how != DELETE) {
- clonedParent.insertBefore(clonedChild, clonedParent.firstChild);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (how != DELETE) {
+ clonedParent.insertBefore(clonedChild, clonedParent.firstChild);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- isFullySelected = TRUE;
- next = prevSibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ isFullySelected = TRUE;
+ next = prevSibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (parent == root) {
- return clonedParent;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parent == root) {
+ return clonedParent;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- next = parent.previousSibling;
- parent = parent.parentNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ next = parent.previousSibling;
+ parent = parent.parentNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- clonedGrandParent = _traverseNode(parent, FALSE, FALSE, how);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ clonedGrandParent = _traverseNode(parent, FALSE, FALSE, how);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (how != DELETE) {
- clonedGrandParent.appendChild(clonedParent);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (how != DELETE) {
+ clonedGrandParent.appendChild(clonedParent);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- clonedParent = clonedGrandParent;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ clonedParent = clonedGrandParent;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function _traverseLeftBoundary(root, how) {
- var next = _getSelectedNode(self[START_CONTAINER], self[START_OFFSET]), isFullySelected = next != self[START_CONTAINER];
- var parent, clonedParent, nextSibling, clonedChild, clonedGrandParent;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function _traverseLeftBoundary(root, how) {
+ var next = _getSelectedNode(self[START_CONTAINER], self[START_OFFSET]), isFullySelected = next != self[START_CONTAINER];
+ var parent, clonedParent, nextSibling, clonedChild, clonedGrandParent;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (next == root) {
- return _traverseNode(next, isFullySelected, TRUE, how);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (next == root) {
+ return _traverseNode(next, isFullySelected, TRUE, how);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parent = next.parentNode;
- clonedParent = _traverseNode(parent, FALSE, TRUE, how);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parent = next.parentNode;
+ clonedParent = _traverseNode(parent, FALSE, TRUE, how);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (parent) {
- while (next) {
- nextSibling = next.nextSibling;
- clonedChild = _traverseNode(next, isFullySelected, TRUE, how);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (parent) {
+ while (next) {
+ nextSibling = next.nextSibling;
+ clonedChild = _traverseNode(next, isFullySelected, TRUE, how);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (how != DELETE) {
- clonedParent.appendChild(clonedChild);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (how != DELETE) {
+ clonedParent.appendChild(clonedChild);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- isFullySelected = TRUE;
- next = nextSibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ isFullySelected = TRUE;
+ next = nextSibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (parent == root) {
- return clonedParent;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parent == root) {
+ return clonedParent;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- next = parent.nextSibling;
- parent = parent.parentNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ next = parent.nextSibling;
+ parent = parent.parentNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- clonedGrandParent = _traverseNode(parent, FALSE, TRUE, how);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ clonedGrandParent = _traverseNode(parent, FALSE, TRUE, how);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (how != DELETE) {
- clonedGrandParent.appendChild(clonedParent);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (how != DELETE) {
+ clonedGrandParent.appendChild(clonedParent);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- clonedParent = clonedGrandParent;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ clonedParent = clonedGrandParent;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function _traverseNode(n, isFullySelected, isLeft, how) {
- var txtValue, newNodeValue, oldNodeValue, offset, newNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function _traverseNode(n, isFullySelected, isLeft, how) {
+ var txtValue, newNodeValue, oldNodeValue, offset, newNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isFullySelected) {
- return _traverseFullySelected(n, how);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isFullySelected) {
+ return _traverseFullySelected(n, how);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // TEXT_NODE
- if (n.nodeType == 3) {
- txtValue = n.nodeValue;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // TEXT_NODE
+ if (n.nodeType == 3) {
+ txtValue = n.nodeValue;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isLeft) {
- offset = self[START_OFFSET];
- newNodeValue = txtValue.substring(offset);
- oldNodeValue = txtValue.substring(0, offset);
- } else {
- offset = self[END_OFFSET];
- newNodeValue = txtValue.substring(0, offset);
- oldNodeValue = txtValue.substring(offset);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isLeft) {
+ offset = self[START_OFFSET];
+ newNodeValue = txtValue.substring(offset);
+ oldNodeValue = txtValue.substring(0, offset);
+ } else {
+ offset = self[END_OFFSET];
+ newNodeValue = txtValue.substring(0, offset);
+ oldNodeValue = txtValue.substring(offset);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (how != CLONE) {
- n.nodeValue = oldNodeValue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (how != CLONE) {
+ n.nodeValue = oldNodeValue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (how == DELETE) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (how == DELETE) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- newNode = dom.clone(n, FALSE);
- newNode.nodeValue = newNodeValue;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ newNode = dom.clone(n, FALSE);
+ newNode.nodeValue = newNodeValue;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return newNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return newNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (how == DELETE) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (how == DELETE) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return dom.clone(n, FALSE);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return dom.clone(n, FALSE);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function _traverseFullySelected(n, how) {
- if (how != DELETE) {
- return how == CLONE ? dom.clone(n, TRUE) : n;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function _traverseFullySelected(n, how) {
+ if (how != DELETE) {
+ return how == CLONE ? dom.clone(n, TRUE) : n;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- n.parentNode.removeChild(n);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ n.parentNode.removeChild(n);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function toStringIE() {
- return dom.create('body', null, cloneContents()).outerText;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function toStringIE() {
+ return dom.create('body', null, cloneContents()).outerText;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- extend(self, {
- // Initial states
- startContainer: doc,
- startOffset: 0,
- endContainer: doc,
- endOffset: 0,
- collapsed: TRUE,
- commonAncestorContainer: doc,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ extend(self, {
+ // Initial states
+ startContainer: doc,
+ startOffset: 0,
+ endContainer: doc,
+ endOffset: 0,
+ collapsed: TRUE,
+ commonAncestorContainer: doc,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Range constants
- START_TO_START: 0,
- START_TO_END: 1,
- END_TO_END: 2,
- END_TO_START: 3,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Range constants
+ START_TO_START: 0,
+ START_TO_END: 1,
+ END_TO_END: 2,
+ END_TO_START: 3,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Public methods
- setStart: setStart,
- setEnd: setEnd,
- setStartBefore: setStartBefore,
- setStartAfter: setStartAfter,
- setEndBefore: setEndBefore,
- setEndAfter: setEndAfter,
- collapse: collapse,
- selectNode: selectNode,
- selectNodeContents: selectNodeContents,
- compareBoundaryPoints: compareBoundaryPoints,
- deleteContents: deleteContents,
- extractContents: extractContents,
- cloneContents: cloneContents,
- insertNode: insertNode,
- surroundContents: surroundContents,
- cloneRange: cloneRange,
- toStringIE: toStringIE
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Public methods
+ setStart: setStart,
+ setEnd: setEnd,
+ setStartBefore: setStartBefore,
+ setStartAfter: setStartAfter,
+ setEndBefore: setEndBefore,
+ setEndAfter: setEndAfter,
+ collapse: collapse,
+ selectNode: selectNode,
+ selectNodeContents: selectNodeContents,
+ compareBoundaryPoints: compareBoundaryPoints,
+ deleteContents: deleteContents,
+ extractContents: extractContents,
+ cloneContents: cloneContents,
+ insertNode: insertNode,
+ surroundContents: surroundContents,
+ cloneRange: cloneRange,
+ toStringIE: toStringIE
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Older IE versions doesn't let you override toString by it's constructor so we have to stick it in the prototype
- Range.prototype.toString = function() {
- return this.toStringIE();
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Older IE versions doesn't let you override toString by it's constructor so we have to stick it in the prototype
+ Range.prototype.toString = function () {
+ return this.toStringIE();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Range;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Range;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/html/Entities.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+defineGlobal("global!Array", Array);
+defineGlobal("global!Error", Error);
+define(
+ 'ephox.katamari.api.Fun',
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ [
+ 'global!Array',
+ 'global!Error'
+ ],
+
+ function (Array, Error) {
+
+ var noop = function () { };
+
+ var compose = function (fa, fb) {
+ return function () {
+ return fa(fb.apply(null, arguments));
+ };
+ };
+
+ var constant = function (value) {
+ return function () {
+ return value;
+ };
+ };
+
+ var identity = function (x) {
+ return x;
+ };
+
+ var tripleEquals = function(a, b) {
+ return a === b;
+ };
+
+ // Don't use array slice(arguments), makes the whole function unoptimisable on Chrome
+ var curry = function (f) {
+ // equivalent to arguments.slice(1)
+ // starting at 1 because 0 is the f, makes things tricky.
+ // Pay attention to what variable is where, and the -1 magic.
+ // thankfully, we have tests for this.
+ var args = new Array(arguments.length - 1);
+ for (var i = 1; i < arguments.length; i++) args[i-1] = arguments[i];
+
+ return function () {
+ var newArgs = new Array(arguments.length);
+ for (var j = 0; j < newArgs.length; j++) newArgs[j] = arguments[j];
+
+ var all = args.concat(newArgs);
+ return f.apply(null, all);
+ };
+ };
+
+ var not = function (f) {
+ return function () {
+ return !f.apply(null, arguments);
+ };
+ };
+
+ var die = function (msg) {
+ return function () {
+ throw new Error(msg);
+ };
+ };
+
+ var apply = function (f) {
+ return f();
+ };
+
+ var call = function(f) {
+ f();
+ };
+
+ var never = constant(false);
+ var always = constant(true);
+
+
+ return {
+ noop: noop,
+ compose: compose,
+ constant: constant,
+ identity: identity,
+ tripleEquals: tripleEquals,
+ curry: curry,
+ not: not,
+ die: die,
+ apply: apply,
+ call: call,
+ never: never,
+ always: always
+ };
+ }
+);
+
+defineGlobal("global!Object", Object);
+define(
+ 'ephox.katamari.api.Option',
+
+ [
+ 'ephox.katamari.api.Fun',
+ 'global!Object'
+ ],
+
+ function (Fun, Object) {
+
+ var never = Fun.never;
+ var always = Fun.always;
+
+ /**
+ Option objects support the following methods:
+
+ fold :: this Option a -> ((() -> b, a -> b)) -> Option b
+
+ is :: this Option a -> a -> Boolean
+
+ isSome :: this Option a -> () -> Boolean
+
+ isNone :: this Option a -> () -> Boolean
+
+ getOr :: this Option a -> a -> a
+
+ getOrThunk :: this Option a -> (() -> a) -> a
+
+ getOrDie :: this Option a -> String -> a
+
+ or :: this Option a -> Option a -> Option a
+ - if some: return self
+ - if none: return opt
+
+ orThunk :: this Option a -> (() -> Option a) -> Option a
+ - Same as "or", but uses a thunk instead of a value
+
+ map :: this Option a -> (a -> b) -> Option b
+ - "fmap" operation on the Option Functor.
+ - same as 'each'
+
+ ap :: this Option a -> Option (a -> b) -> Option b
+ - "apply" operation on the Option Apply/Applicative.
+ - Equivalent to <*> in Haskell/PureScript.
+
+ each :: this Option a -> (a -> b) -> Option b
+ - same as 'map'
+
+ bind :: this Option a -> (a -> Option b) -> Option b
+ - "bind"/"flatMap" operation on the Option Bind/Monad.
+ - Equivalent to >>= in Haskell/PureScript; flatMap in Scala.
+
+ flatten :: {this Option (Option a))} -> () -> Option a
+ - "flatten"/"join" operation on the Option Monad.
+
+ exists :: this Option a -> (a -> Boolean) -> Boolean
+
+ forall :: this Option a -> (a -> Boolean) -> Boolean
+
+ filter :: this Option a -> (a -> Boolean) -> Option a
+
+ equals :: this Option a -> Option a -> Boolean
+
+ equals_ :: this Option a -> (Option a, a -> Boolean) -> Boolean
+
+ toArray :: this Option a -> () -> [a]
+
+ */
+
+ var none = function () { return NONE; };
+
+ var NONE = (function () {
+ var eq = function (o) {
+ return o.isNone();
+ };
+
+ // inlined from peanut, maybe a micro-optimisation?
+ var call = function (thunk) { return thunk(); };
+ var id = function (n) { return n; };
+ var noop = function () { };
+
+ var me = {
+ fold: function (n, s) { return n(); },
+ is: never,
+ isSome: never,
+ isNone: always,
+ getOr: id,
+ getOrThunk: call,
+ getOrDie: function (msg) {
+ throw new Error(msg || 'error: getOrDie called on none.');
+ },
+ or: id,
+ orThunk: call,
+ map: none,
+ ap: none,
+ each: noop,
+ bind: none,
+ flatten: none,
+ exists: never,
+ forall: always,
+ filter: none,
+ equals: eq,
+ equals_: eq,
+ toArray: function () { return []; },
+ toString: Fun.constant("none()")
+ };
+ if (Object.freeze) Object.freeze(me);
+ return me;
+ })();
+
+
+ /** some :: a -> Option a */
+ var some = function (a) {
+
+ // inlined from peanut, maybe a micro-optimisation?
+ var constant_a = function () { return a; };
+
+ var self = function () {
+ // can't Fun.constant this one
+ return me;
+ };
+
+ var map = function (f) {
+ return some(f(a));
+ };
+
+ var bind = function (f) {
+ return f(a);
+ };
+
+ var me = {
+ fold: function (n, s) { return s(a); },
+ is: function (v) { return a === v; },
+ isSome: always,
+ isNone: never,
+ getOr: constant_a,
+ getOrThunk: constant_a,
+ getOrDie: constant_a,
+ or: self,
+ orThunk: self,
+ map: map,
+ ap: function (optfab) {
+ return optfab.fold(none, function(fab) {
+ return some(fab(a));
+ });
+ },
+ each: function (f) {
+ f(a);
+ },
+ bind: bind,
+ flatten: constant_a,
+ exists: bind,
+ forall: bind,
+ filter: function (f) {
+ return f(a) ? me : NONE;
+ },
+ equals: function (o) {
+ return o.is(a);
+ },
+ equals_: function (o, elementEq) {
+ return o.fold(
+ never,
+ function (b) { return elementEq(a, b); }
+ );
+ },
+ toArray: function () {
+ return [a];
+ },
+ toString: function () {
+ return 'some(' + a + ')';
+ }
+ };
+ return me;
+ };
+
+ /** from :: undefined|null|a -> Option a */
+ var from = function (value) {
+ return value === null || value === undefined ? NONE : some(value);
+ };
+
+ return {
+ some: some,
+ none: none,
+ from: from
+ };
+ }
+);
+
+defineGlobal("global!String", String);
+define(
+ 'ephox.katamari.api.Arr',
+
+ [
+ 'ephox.katamari.api.Option',
+ 'global!Array',
+ 'global!Error',
+ 'global!String'
+ ],
+
+ function (Option, Array, Error, String) {
+ // Use the native Array.indexOf if it is available (IE9+) otherwise fall back to manual iteration
+ // https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
+ var rawIndexOf = (function () {
+ var pIndexOf = Array.prototype.indexOf;
+
+ var fastIndex = function (xs, x) { return pIndexOf.call(xs, x); };
+
+ var slowIndex = function(xs, x) { return slowIndexOf(xs, x); };
+
+ return pIndexOf === undefined ? slowIndex : fastIndex;
+ })();
+
+ var indexOf = function (xs, x) {
+ // The rawIndexOf method does not wrap up in an option. This is for performance reasons.
+ var r = rawIndexOf(xs, x);
+ return r === -1 ? Option.none() : Option.some(r);
+ };
+
+ var contains = function (xs, x) {
+ return rawIndexOf(xs, x) > -1;
+ };
+
+ // Using findIndex is likely less optimal in Chrome (dynamic return type instead of bool)
+ // but if we need that micro-optimisation we can inline it later.
+ var exists = function (xs, pred) {
+ return findIndex(xs, pred).isSome();
+ };
+
+ var range = function (num, f) {
+ var r = [];
+ for (var i = 0; i < num; i++) {
+ r.push(f(i));
+ }
+ return r;
+ };
+
+ // It's a total micro optimisation, but these do make some difference.
+ // Particularly for browsers other than Chrome.
+ // - length caching
+ // http://jsperf.com/browser-diet-jquery-each-vs-for-loop/69
+ // - not using push
+ // http://jsperf.com/array-direct-assignment-vs-push/2
+
+ var chunk = function (array, size) {
+ var r = [];
+ for (var i = 0; i < array.length; i += size) {
+ var s = array.slice(i, i + size);
+ r.push(s);
+ }
+ return r;
+ };
+
+ var map = function(xs, f) {
+ // pre-allocating array size when it's guaranteed to be known
+ // http://jsperf.com/push-allocated-vs-dynamic/22
+ var len = xs.length;
+ var r = new Array(len);
+ for (var i = 0; i < len; i++) {
+ var x = xs[i];
+ r[i] = f(x, i, xs);
+ }
+ return r;
+ };
+
+ // Unwound implementing other functions in terms of each.
+ // The code size is roughly the same, and it should allow for better optimisation.
+ var each = function(xs, f) {
+ for (var i = 0, len = xs.length; i < len; i++) {
+ var x = xs[i];
+ f(x, i, xs);
+ }
+ };
+
+ var eachr = function (xs, f) {
+ for (var i = xs.length - 1; i >= 0; i--) {
+ var x = xs[i];
+ f(x, i, xs);
+ }
+ };
+
+ var partition = function(xs, pred) {
+ var pass = [];
+ var fail = [];
+ for (var i = 0, len = xs.length; i < len; i++) {
+ var x = xs[i];
+ var arr = pred(x, i, xs) ? pass : fail;
+ arr.push(x);
+ }
+ return { pass: pass, fail: fail };
+ };
+
+ var filter = function(xs, pred) {
+ var r = [];
+ for (var i = 0, len = xs.length; i < len; i++) {
+ var x = xs[i];
+ if (pred(x, i, xs)) {
+ r.push(x);
+ }
+ }
+ return r;
+ };
+
+ /*
+ * Groups an array into contiguous arrays of like elements. Whether an element is like or not depends on f.
+ *
+ * f is a function that derives a value from an element - e.g. true or false, or a string.
+ * Elements are like if this function generates the same value for them (according to ===).
+ *
+ *
+ * Order of the elements is preserved. Arr.flatten() on the result will return the original list, as with Haskell groupBy function.
+ * For a good explanation, see the group function (which is a special case of groupBy)
+ * http://hackage.haskell.org/package/base-4.7.0.0/docs/Data-List.html#v:group
+ */
+ var groupBy = function (xs, f) {
+ if (xs.length === 0) {
+ return [];
+ } else {
+ var wasType = f(xs[0]); // initial case for matching
+ var r = [];
+ var group = [];
+
+ for (var i = 0, len = xs.length; i < len; i++) {
+ var x = xs[i];
+ var type = f(x);
+ if (type !== wasType) {
+ r.push(group);
+ group = [];
+ }
+ wasType = type;
+ group.push(x);
+ }
+ if (group.length !== 0) {
+ r.push(group);
+ }
+ return r;
+ }
+ };
+
+ var foldr = function (xs, f, acc) {
+ eachr(xs, function (x) {
+ acc = f(acc, x);
+ });
+ return acc;
+ };
+
+ var foldl = function (xs, f, acc) {
+ each(xs, function (x) {
+ acc = f(acc, x);
+ });
+ return acc;
+ };
+
+ var find = function (xs, pred) {
+ for (var i = 0, len = xs.length; i < len; i++) {
+ var x = xs[i];
+ if (pred(x, i, xs)) {
+ return Option.some(x);
+ }
+ }
+ return Option.none();
+ };
+
+ var findIndex = function (xs, pred) {
+ for (var i = 0, len = xs.length; i < len; i++) {
+ var x = xs[i];
+ if (pred(x, i, xs)) {
+ return Option.some(i);
+ }
+ }
+
+ return Option.none();
+ };
+
+ var slowIndexOf = function (xs, x) {
+ for (var i = 0, len = xs.length; i < len; ++i) {
+ if (xs[i] === x) {
+ return i;
+ }
+ }
+
+ return -1;
+ };
+
+ var push = Array.prototype.push;
+ var flatten = function (xs) {
+ // Note, this is possible because push supports multiple arguments:
+ // http://jsperf.com/concat-push/6
+ // Note that in the past, concat() would silently work (very slowly) for array-like objects.
+ // With this change it will throw an error.
+ var r = [];
+ for (var i = 0, len = xs.length; i < len; ++i) {
+ // Ensure that each value is an array itself
+ if (! Array.prototype.isPrototypeOf(xs[i])) throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
+ push.apply(r, xs[i]);
+ }
+ return r;
+ };
+
+ var bind = function (xs, f) {
+ var output = map(xs, f);
+ return flatten(output);
+ };
+
+ var forall = function (xs, pred) {
+ for (var i = 0, len = xs.length; i < len; ++i) {
+ var x = xs[i];
+ if (pred(x, i, xs) !== true) {
+ return false;
+ }
+ }
+ return true;
+ };
+
+ var equal = function (a1, a2) {
+ return a1.length === a2.length && forall(a1, function (x, i) {
+ return x === a2[i];
+ });
+ };
+
+ var slice = Array.prototype.slice;
+ var reverse = function (xs) {
+ var r = slice.call(xs, 0);
+ r.reverse();
+ return r;
+ };
+
+ var difference = function (a1, a2) {
+ return filter(a1, function (x) {
+ return !contains(a2, x);
+ });
+ };
+
+ var mapToObject = function(xs, f) {
+ var r = {};
+ for (var i = 0, len = xs.length; i < len; i++) {
+ var x = xs[i];
+ r[String(x)] = f(x, i);
+ }
+ return r;
+ };
+
+ var pure = function(x) {
+ return [x];
+ };
+
+ var sort = function (xs, comparator) {
+ var copy = slice.call(xs, 0);
+ copy.sort(comparator);
+ return copy;
+ };
+
+ return {
+ map: map,
+ each: each,
+ eachr: eachr,
+ partition: partition,
+ filter: filter,
+ groupBy: groupBy,
+ indexOf: indexOf,
+ foldr: foldr,
+ foldl: foldl,
+ find: find,
+ findIndex: findIndex,
+ flatten: flatten,
+ bind: bind,
+ forall: forall,
+ exists: exists,
+ contains: contains,
+ equal: equal,
+ reverse: reverse,
+ chunk: chunk,
+ difference: difference,
+ mapToObject: mapToObject,
+ pure: pure,
+ sort: sort,
+ range: range
+ };
+ }
+);
+defineGlobal("global!setTimeout", setTimeout);
+define(
+ 'ephox.katamari.api.LazyValue',
+
+ [
+ 'ephox.katamari.api.Arr',
+ 'ephox.katamari.api.Option',
+ 'global!setTimeout'
+ ],
+
+ function (Arr, Option, setTimeout) {
+ var nu = function (baseFn) {
+ var data = Option.none();
+ var callbacks = [];
+
+ /** map :: this LazyValue a -> (a -> b) -> LazyValue b */
+ var map = function (f) {
+ return nu(function (nCallback) {
+ get(function (data) {
+ nCallback(f(data));
+ });
+ });
+ };
+
+ var get = function (nCallback) {
+ if (isReady()) call(nCallback);
+ else callbacks.push(nCallback);
+ };
+
+ var set = function (x) {
+ data = Option.some(x);
+ run(callbacks);
+ callbacks = [];
+ };
+
+ var isReady = function () {
+ return data.isSome();
+ };
+
+ var run = function (cbs) {
+ Arr.each(cbs, call);
+ };
+
+ var call = function(cb) {
+ data.each(function(x) {
+ setTimeout(function() {
+ cb(x);
+ }, 0);
+ });
+ };
+
+ // Lazy values cache the value and kick off immediately
+ baseFn(set);
+
+ return {
+ get: get,
+ map: map,
+ isReady: isReady
+ };
+ };
+
+ var pure = function (a) {
+ return nu(function (callback) {
+ callback(a);
+ });
+ };
+
+ return {
+ nu: nu,
+ pure: pure
+ };
+ }
+);
+define(
+ 'ephox.katamari.async.Bounce',
+
+ [
+ 'global!Array',
+ 'global!setTimeout'
+ ],
+
+ function (Array, setTimeout) {
+
+ var bounce = function(f) {
+ return function() {
+ var args = Array.prototype.slice.call(arguments);
+ var me = this;
+ setTimeout(function() {
+ f.apply(me, args);
+ }, 0);
+ };
+ };
+
+ return {
+ bounce: bounce
+ };
+ }
+);
+
+define(
+ 'ephox.katamari.api.Future',
+
+ [
+ 'ephox.katamari.api.LazyValue',
+ 'ephox.katamari.async.Bounce'
+ ],
+
+ /** A future value that is evaluated on demand. The base function is re-evaluated each time 'get' is called. */
+ function (LazyValue, Bounce) {
+ var nu = function (baseFn) {
+ var get = function(callback) {
+ baseFn(Bounce.bounce(callback));
+ };
+
+ /** map :: this Future a -> (a -> b) -> Future b */
+ var map = function (fab) {
+ return nu(function (callback) {
+ get(function (a) {
+ var value = fab(a);
+ callback(value);
+ });
+ });
+ };
+
+ /** bind :: this Future a -> (a -> Future b) -> Future b */
+ var bind = function (aFutureB) {
+ return nu(function (callback) {
+ get(function (a) {
+ aFutureB(a).get(callback);
+ });
+ });
+ };
+
+ /** anonBind :: this Future a -> Future b -> Future b
+ * Returns a future, which evaluates the first future, ignores the result, then evaluates the second.
+ */
+ var anonBind = function (futureB) {
+ return nu(function (callback) {
+ get(function (a) {
+ futureB.get(callback);
+ });
+ });
+ };
+
+ var toLazy = function () {
+ return LazyValue.nu(get);
+ };
+
+ return {
+ map: map,
+ bind: bind,
+ anonBind: anonBind,
+ toLazy: toLazy,
+ get: get
+ };
+
+ };
+
+ /** a -> Future a */
+ var pure = function (a) {
+ return nu(function (callback) {
+ callback(a);
+ });
+ };
+
+ return {
+ nu: nu,
+ pure: pure
+ };
+ }
+);
+
+define(
+ 'ephox.katamari.async.AsyncValues',
+
+ [
+ 'ephox.katamari.api.Arr'
+ ],
+
+ function (Arr) {
+ /*
+ * NOTE: an `asyncValue` must have a `get` function which gets given a callback and calls
+ * that callback with a value once it is ready
+ *
+ * e.g
+ * {
+ * get: function (callback) { callback(10); }
+ * }
+ */
+ var par = function (asyncValues, nu) {
+ return nu(function(callback) {
+ var r = [];
+ var count = 0;
+
+ var cb = function(i) {
+ return function(value) {
+ r[i] = value;
+ count++;
+ if (count >= asyncValues.length) {
+ callback(r);
+ }
+ };
+ };
+
+ if (asyncValues.length === 0) {
+ callback([]);
+ } else {
+ Arr.each(asyncValues, function(asyncValue, i) {
+ asyncValue.get(cb(i));
+ });
+ }
+ });
+ };
+
+ return {
+ par: par
+ };
+ }
+);
+define(
+ 'ephox.katamari.api.Futures',
+
+ [
+ 'ephox.katamari.api.Arr',
+ 'ephox.katamari.api.Future',
+ 'ephox.katamari.async.AsyncValues'
+ ],
+
+ function (Arr, Future, AsyncValues) {
+ /** par :: [Future a] -> Future [a] */
+ var par = function(futures) {
+ return AsyncValues.par(futures, Future.nu);
+ };
+
+ /** mapM :: [a] -> (a -> Future b) -> Future [b] */
+ var mapM = function(array, fn) {
+ var futures = Arr.map(array, fn);
+ return par(futures);
+ };
+
+ /** Kleisli composition of two functions: a -> Future b.
+ * Note the order of arguments: g is invoked first, then the result passed to f.
+ * This is in line with f . g = \x -> f (g a)
+ *
+ * compose :: ((b -> Future c), (a -> Future b)) -> a -> Future c
+ */
+ var compose = function (f, g) {
+ return function (a) {
+ return g(a).bind(f);
+ };
+ };
+
+ return {
+ par: par,
+ mapM: mapM,
+ compose: compose
+ };
+ }
+);
+define(
+ 'ephox.katamari.api.Result',
+
+ [
+ 'ephox.katamari.api.Fun',
+ 'ephox.katamari.api.Option'
+ ],
+
+ function (Fun, Option) {
+ /* The type signatures for Result
+ * is :: this Result a -> a -> Bool
+ * or :: this Result a -> Result a -> Result a
+ * orThunk :: this Result a -> (_ -> Result a) -> Result a
+ * map :: this Result a -> (a -> b) -> Result b
+ * each :: this Result a -> (a -> _) -> _
+ * bind :: this Result a -> (a -> Result b) -> Result b
+ * fold :: this Result a -> (_ -> b, a -> b) -> b
+ * exists :: this Result a -> (a -> Bool) -> Bool
+ * forall :: this Result a -> (a -> Bool) -> Bool
+ * toOption :: this Result a -> Option a
+ * isValue :: this Result a -> Bool
+ * isError :: this Result a -> Bool
+ * getOr :: this Result a -> a -> a
+ * getOrThunk :: this Result a -> (_ -> a) -> a
+ * getOrDie :: this Result a -> a (or throws error)
+ */
+
+ var value = function (o) {
+ var is = function (v) {
+ return o === v;
+ };
+
+ var or = function (opt) {
+ return value(o);
+ };
+
+ var orThunk = function (f) {
+ return value(o);
+ };
+
+ var map = function (f) {
+ return value(f(o));
+ };
+
+ var each = function (f) {
+ f(o);
+ };
+
+ var bind = function (f) {
+ return f(o);
+ };
+
+ var fold = function (_, onValue) {
+ return onValue(o);
+ };
+
+ var exists = function (f) {
+ return f(o);
+ };
+
+ var forall = function (f) {
+ return f(o);
+ };
+
+ var toOption = function () {
+ return Option.some(o);
+ };
+
+ return {
+ is: is,
+ isValue: Fun.constant(true),
+ isError: Fun.constant(false),
+ getOr: Fun.constant(o),
+ getOrThunk: Fun.constant(o),
+ getOrDie: Fun.constant(o),
+ or: or,
+ orThunk: orThunk,
+ fold: fold,
+ map: map,
+ each: each,
+ bind: bind,
+ exists: exists,
+ forall: forall,
+ toOption: toOption
+ };
+ };
+
+ var error = function (message) {
+ var getOrThunk = function (f) {
+ return f();
+ };
+
+ var getOrDie = function () {
+ return Fun.die(message)();
+ };
+
+ var or = function (opt) {
+ return opt;
+ };
+
+ var orThunk = function (f) {
+ return f();
+ };
+
+ var map = function (f) {
+ return error(message);
+ };
+
+ var bind = function (f) {
+ return error(message);
+ };
+
+ var fold = function (onError, _) {
+ return onError(message);
+ };
+
+ return {
+ is: Fun.constant(false),
+ isValue: Fun.constant(false),
+ isError: Fun.constant(true),
+ getOr: Fun.identity,
+ getOrThunk: getOrThunk,
+ getOrDie: getOrDie,
+ or: or,
+ orThunk: orThunk,
+ fold: fold,
+ map: map,
+ each: Fun.noop,
+ bind: bind,
+ exists: Fun.constant(false),
+ forall: Fun.constant(true),
+ toOption: Option.none
+ };
+ };
+
+ return {
+ value: value,
+ error: error
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Entities.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * StyleSheetLoader.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/*jshint bitwise:false */
-/*eslint no-bitwise:0 */
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Entity encoder class.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * This class handles loading of external stylesheets and fires events when these are loaded.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @class tinymce.html.Entities
- * @static
- * @version 3.4
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @class tinymce.dom.StyleSheetLoader
+ * @private
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/html/Entities", [
- "tinymce/util/Tools"
-], function(Tools) {
- var makeMap = Tools.makeMap;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.StyleSheetLoader',
+ [
+ 'ephox.katamari.api.Arr',
+ 'ephox.katamari.api.Fun',
+ 'ephox.katamari.api.Future',
+ 'ephox.katamari.api.Futures',
+ 'ephox.katamari.api.Result',
+ 'tinymce.core.util.Delay',
+ 'tinymce.core.util.Tools'
+ ],
+ function (Arr, Fun, Future, Futures, Result, Delay, Tools) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var namedEntities, baseEntities, reverseEntities,
- attrsCharsRegExp = /[&<>\"\u0060\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
- textCharsRegExp = /[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
- rawCharsRegExp = /[<>&\"\']/g,
- entityRegExp = /&#([a-z0-9]+);?|&([a-z0-9]+);/gi,
- asciiMap = {
- 128: "\u20AC", 130: "\u201A", 131: "\u0192", 132: "\u201E", 133: "\u2026", 134: "\u2020",
- 135: "\u2021", 136: "\u02C6", 137: "\u2030", 138: "\u0160", 139: "\u2039", 140: "\u0152",
- 142: "\u017D", 145: "\u2018", 146: "\u2019", 147: "\u201C", 148: "\u201D", 149: "\u2022",
- 150: "\u2013", 151: "\u2014", 152: "\u02DC", 153: "\u2122", 154: "\u0161", 155: "\u203A",
- 156: "\u0153", 158: "\u017E", 159: "\u0178"
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function (document, settings) {
+ var idCount = 0, loadedStates = {}, maxLoadTime;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Raw entities
- baseEntities = {
- '\"': '"', // Needs to be escaped since the YUI compressor would otherwise break the code
- "'": ''',
- '<': '<',
- '>': '>',
- '&': '&',
- '\u0060': '`'
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ settings = settings || {};
+ maxLoadTime = settings.maxLoadTime || 5000;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Reverse lookup table for raw entities
- reverseEntities = {
- '<': '<',
- '>': '>',
- '&': '&',
- '"': '"',
- ''': "'"
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function appendToHead(node) {
+ document.getElementsByTagName('head')[0].appendChild(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Decodes text by using the browser
- function nativeDecode(text) {
- var elm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Loads the specified css style sheet file and call the loadedCallback once it's finished loading.
+ *
+ * @method load
+ * @param {String} url Url to be loaded.
+ * @param {Function} loadedCallback Callback to be executed when loaded.
+ * @param {Function} errorCallback Callback to be executed when failed loading.
+ */
+ function load(url, loadedCallback, errorCallback) {
+ var link, style, startTime, state;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elm = document.createElement("div");
- elm.innerHTML = text;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function passed() {
+ var callbacks = state.passed, i = callbacks.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return elm.textContent || elm.innerText || text;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ callbacks[i]();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Build a two way lookup table for the entities
- function buildEntitiesLookup(items, radix) {
- var i, chr, entity, lookup = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ state.status = 2;
+ state.passed = [];
+ state.failed = [];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (items) {
- items = items.split(',');
- radix = radix || 10;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function failed() {
+ var callbacks = state.failed, i = callbacks.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Build entities lookup table
- for (i = 0; i < items.length; i += 2) {
- chr = String.fromCharCode(parseInt(items[i], radix));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ callbacks[i]();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Only add non base entities
- if (!baseEntities[chr]) {
- entity = '&' + items[i + 1] + ';';
- lookup[chr] = entity;
- lookup[entity] = chr;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ state.status = 3;
+ state.passed = [];
+ state.failed = [];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return lookup;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Sniffs for older WebKit versions that have the link.onload but a broken one
+ function isOldWebKit() {
+ var webKitChunks = navigator.userAgent.match(/WebKit\/(\d*)/);
+ return !!(webKitChunks && webKitChunks[1] < 536);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Unpack entities lookup where the numbers are in radix 32 to reduce the size
- namedEntities = buildEntitiesLookup(
- '50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,' +
- '5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,' +
- '5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,' +
- '5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,' +
- '68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,' +
- '6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,' +
- '6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,' +
- '75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,' +
- '7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,' +
- '7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,' +
- 'sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,' +
- 'st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,' +
- 't9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,' +
- 'tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,' +
- 'u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,' +
- '81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,' +
- '8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,' +
- '8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,' +
- '8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,' +
- '8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,' +
- 'nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,' +
- 'rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,' +
- 'Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,' +
- '80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,' +
- '811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro', 32);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Calls the waitCallback until the test returns true or the timeout occurs
+ function wait(testCallback, waitCallback) {
+ if (!testCallback()) {
+ // Wait for timeout
+ if ((new Date().getTime()) - startTime < maxLoadTime) {
+ Delay.setTimeout(waitCallback);
+ } else {
+ failed();
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var Entities = {
- /**
- * Encodes the specified string using raw entities. This means only the required XML base entities will be encoded.
- *
- * @method encodeRaw
- * @param {String} text Text to encode.
- * @param {Boolean} attr Optional flag to specify if the text is attribute contents.
- * @return {String} Entity encoded text.
- */
- encodeRaw: function(text, attr) {
- return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) {
- return baseEntities[chr] || chr;
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Workaround for WebKit that doesn't properly support the onload event for link elements
+ // Or WebKit that fires the onload event before the StyleSheet is added to the document
+ function waitForWebKitLinkLoaded() {
+ wait(function () {
+ var styleSheets = document.styleSheets, styleSheet, i = styleSheets.length, owner;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Encoded the specified text with both the attributes and text entities. This function will produce larger text contents
- * since it doesn't know if the context is within a attribute or text node. This was added for compatibility
- * and is exposed as the DOMUtils.encode function.
- *
- * @method encodeAllRaw
- * @param {String} text Text to encode.
- * @return {String} Entity encoded text.
- */
- encodeAllRaw: function(text) {
- return ('' + text).replace(rawCharsRegExp, function(chr) {
- return baseEntities[chr] || chr;
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ styleSheet = styleSheets[i];
+ owner = styleSheet.ownerNode ? styleSheet.ownerNode : styleSheet.owningElement;
+ if (owner && owner.id === link.id) {
+ passed();
+ return true;
+ }
+ }
+ }, waitForWebKitLinkLoaded);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Encodes the specified string using numeric entities. The core entities will be
- * encoded as named ones but all non lower ascii characters will be encoded into numeric entities.
- *
- * @method encodeNumeric
- * @param {String} text Text to encode.
- * @param {Boolean} attr Optional flag to specify if the text is attribute contents.
- * @return {String} Entity encoded text.
- */
- encodeNumeric: function(text, attr) {
- return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) {
- // Multi byte sequence convert it to a single entity
- if (chr.length > 1) {
- return '&#' + (((chr.charCodeAt(0) - 0xD800) * 0x400) + (chr.charCodeAt(1) - 0xDC00) + 0x10000) + ';';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Workaround for older Geckos that doesn't have any onload event for StyleSheets
+ function waitForGeckoLinkLoaded() {
+ wait(function () {
+ try {
+ // Accessing the cssRules will throw an exception until the CSS file is loaded
+ var cssRules = style.sheet.cssRules;
+ passed();
+ return !!cssRules;
+ } catch (ex) {
+ // Ignore
+ }
+ }, waitForGeckoLinkLoaded);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return baseEntities[chr] || '&#' + chr.charCodeAt(0) + ';';
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ url = Tools._addCacheSuffix(url);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Encodes the specified string using named entities. The core entities will be encoded
- * as named ones but all non lower ascii characters will be encoded into named entities.
- *
- * @method encodeNamed
- * @param {String} text Text to encode.
- * @param {Boolean} attr Optional flag to specify if the text is attribute contents.
- * @param {Object} entities Optional parameter with entities to use.
- * @return {String} Entity encoded text.
- */
- encodeNamed: function(text, attr, entities) {
- entities = entities || namedEntities;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!loadedStates[url]) {
+ state = {
+ passed: [],
+ failed: []
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) {
- return baseEntities[chr] || entities[chr] || chr;
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ loadedStates[url] = state;
+ } else {
+ state = loadedStates[url];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns an encode function based on the name(s) and it's optional entities.
- *
- * @method getEncodeFunc
- * @param {String} name Comma separated list of encoders for example named,numeric.
- * @param {String} entities Optional parameter with entities to use instead of the built in set.
- * @return {function} Encode function to be used.
- */
- getEncodeFunc: function(name, entities) {
- entities = buildEntitiesLookup(entities) || namedEntities;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (loadedCallback) {
+ state.passed.push(loadedCallback);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function encodeNamedAndNumeric(text, attr) {
- return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) {
- return baseEntities[chr] || entities[chr] || '&#' + chr.charCodeAt(0) + ';' || chr;
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (errorCallback) {
+ state.failed.push(errorCallback);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function encodeCustomNamed(text, attr) {
- return Entities.encodeNamed(text, attr, entities);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Is loading wait for it to pass
+ if (state.status == 1) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Replace + with , to be compatible with previous TinyMCE versions
- name = makeMap(name.replace(/\+/g, ','));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Has finished loading and was success
+ if (state.status == 2) {
+ passed();
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Named and numeric encoder
- if (name.named && name.numeric) {
- return encodeNamedAndNumeric;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Has finished loading and was a failure
+ if (state.status == 3) {
+ failed();
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Named encoder
- if (name.named) {
- // Custom names
- if (entities) {
- return encodeCustomNamed;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Start loading
+ state.status = 1;
+ link = document.createElement('link');
+ link.rel = 'stylesheet';
+ link.type = 'text/css';
+ link.id = 'u' + (idCount++);
+ link.async = false;
+ link.defer = false;
+ startTime = new Date().getTime();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Entities.encodeNamed;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Feature detect onload on link element and sniff older webkits since it has an broken onload event
+ if ("onload" in link && !isOldWebKit()) {
+ link.onload = waitForWebKitLinkLoaded;
+ link.onerror = failed;
+ } else {
+ // Sniff for old Firefox that doesn't support the onload event on link elements
+ // TODO: Remove this in the future when everyone uses modern browsers
+ if (navigator.userAgent.indexOf("Firefox") > 0) {
+ style = document.createElement('style');
+ style.textContent = '@import "' + url + '"';
+ waitForGeckoLinkLoaded();
+ appendToHead(style);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Numeric
- if (name.numeric) {
- return Entities.encodeNumeric;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Use the id owner on older webkits
+ waitForWebKitLinkLoaded();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Raw encoder
- return Entities.encodeRaw;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ appendToHead(link);
+ link.href = url;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Decodes the specified string, this will replace entities with raw UTF characters.
- *
- * @method decode
- * @param {String} text Text to entity decode.
- * @return {String} Entity decoded string.
- */
- decode: function(text) {
- return text.replace(entityRegExp, function(all, numeric) {
- if (numeric) {
- if (numeric.charAt(0).toLowerCase() === 'x') {
- numeric = parseInt(numeric.substr(1), 16);
- } else {
- numeric = parseInt(numeric, 10);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var loadF = function (url) {
+ return Future.nu(function (resolve) {
+ load(
+ url,
+ Fun.compose(resolve, Fun.constant(Result.value(url))),
+ Fun.compose(resolve, Fun.constant(Result.error(url)))
+ );
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Support upper UTF
- if (numeric > 0xFFFF) {
- numeric -= 0x10000;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var unbox = function (result) {
+ return result.fold(Fun.identity, Fun.identity);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return String.fromCharCode(0xD800 + (numeric >> 10), 0xDC00 + (numeric & 0x3FF));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var loadAll = function (urls, success, failure) {
+ Futures.par(Arr.map(urls, loadF)).get(function (result) {
+ var parts = Arr.partition(result, function (r) {
+ return r.isValue();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return asciiMap[numeric] || String.fromCharCode(numeric);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parts.fail.length > 0) {
+ failure(parts.fail.map(unbox));
+ } else {
+ success(parts.pass.map(unbox));
+ }
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return reverseEntities[all] || namedEntities[all] || nativeDecode(all);
- });
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ load: load,
+ loadAll: loadAll
+ };
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Entities;
-});
-
-// Included from: js/tinymce/classes/dom/StyleSheetLoader.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * StyleSheetLoader.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Schema.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * This class handles loading of external stylesheets and fires events when these are loaded.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Schema validator class.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @class tinymce.dom.StyleSheetLoader
- * @private
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @class tinymce.html.Schema
+ * @example
+ * if (tinymce.activeEditor.schema.isValidChild('p', 'span'))
+ * alert('span is valid child of p.');
+ *
+ * if (tinymce.activeEditor.schema.getElementRule('p'))
+ * alert('P is a valid element.');
+ *
+ * @class tinymce.html.Schema
+ * @version 3.4
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/dom/StyleSheetLoader", [
- "tinymce/util/Tools",
- "tinymce/util/Delay"
-], function(Tools, Delay) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.html.Schema',
+ [
+ "tinymce.core.util.Tools"
+ ],
+ function (Tools) {
+ var mapCache = {}, dummyObj = {};
+ var makeMap = Tools.makeMap, each = Tools.each, extend = Tools.extend, explode = Tools.explode, inArray = Tools.inArray;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function(document, settings) {
- var idCount = 0, loadedStates = {}, maxLoadTime;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function split(items, delim) {
+ items = Tools.trim(items);
+ return items ? items.split(delim || ' ') : [];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- settings = settings || {};
- maxLoadTime = settings.maxLoadTime || 5000;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Builds a schema lookup table
+ *
+ * @private
+ * @param {String} type html4, html5 or html5-strict schema type.
+ * @return {Object} Schema lookup table.
+ */
+ function compileSchema(type) {
+ var schema = {}, globalAttributes, blockContent;
+ var phrasingContent, flowContent, html4BlockContent, html4PhrasingContent;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function appendToHead(node) {
- document.getElementsByTagName('head')[0].appendChild(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function add(name, attributes, children) {
+ var ni, attributesOrder, element;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Loads the specified css style sheet file and call the loadedCallback once it's finished loading.
- *
- * @method load
- * @param {String} url Url to be loaded.
- * @param {Function} loadedCallback Callback to be executed when loaded.
- * @param {Function} errorCallback Callback to be executed when failed loading.
- */
- function load(url, loadedCallback, errorCallback) {
- var link, style, startTime, state;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function arrayToMap(array, obj) {
+ var map = {}, i, l;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function passed() {
- var callbacks = state.passed, i = callbacks.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0, l = array.length; i < l; i++) {
+ map[array[i]] = obj || {};
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- callbacks[i]();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return map;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- state.status = 2;
- state.passed = [];
- state.failed = [];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ children = children || [];
+ attributes = attributes || "";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function failed() {
- var callbacks = state.failed, i = callbacks.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof children === "string") {
+ children = split(children);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- callbacks[i]();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ name = split(name);
+ ni = name.length;
+ while (ni--) {
+ attributesOrder = split([globalAttributes, attributes].join(' '));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- state.status = 3;
- state.passed = [];
- state.failed = [];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ element = {
+ attributes: arrayToMap(attributesOrder),
+ attributesOrder: attributesOrder,
+ children: arrayToMap(children, dummyObj)
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Sniffs for older WebKit versions that have the link.onload but a broken one
- function isOldWebKit() {
- var webKitChunks = navigator.userAgent.match(/WebKit\/(\d*)/);
- return !!(webKitChunks && webKitChunks[1] < 536);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ schema[name[ni]] = element;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Calls the waitCallback until the test returns true or the timeout occurs
- function wait(testCallback, waitCallback) {
- if (!testCallback()) {
- // Wait for timeout
- if ((new Date().getTime()) - startTime < maxLoadTime) {
- Delay.setTimeout(waitCallback);
- } else {
- failed();
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function addAttrs(name, attributes) {
+ var ni, schemaItem, i, l;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Workaround for WebKit that doesn't properly support the onload event for link elements
- // Or WebKit that fires the onload event before the StyleSheet is added to the document
- function waitForWebKitLinkLoaded() {
- wait(function() {
- var styleSheets = document.styleSheets, styleSheet, i = styleSheets.length, owner;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ name = split(name);
+ ni = name.length;
+ attributes = split(attributes);
+ while (ni--) {
+ schemaItem = schema[name[ni]];
+ for (i = 0, l = attributes.length; i < l; i++) {
+ schemaItem.attributes[attributes[i]] = {};
+ schemaItem.attributesOrder.push(attributes[i]);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- styleSheet = styleSheets[i];
- owner = styleSheet.ownerNode ? styleSheet.ownerNode : styleSheet.owningElement;
- if (owner && owner.id === link.id) {
- passed();
- return true;
- }
- }
- }, waitForWebKitLinkLoaded);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Use cached schema
+ if (mapCache[type]) {
+ return mapCache[type];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Workaround for older Geckos that doesn't have any onload event for StyleSheets
- function waitForGeckoLinkLoaded() {
- wait(function() {
- try {
- // Accessing the cssRules will throw an exception until the CSS file is loaded
- var cssRules = style.sheet.cssRules;
- passed();
- return !!cssRules;
- } catch (ex) {
- // Ignore
- }
- }, waitForGeckoLinkLoaded);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Attributes present on all elements
+ globalAttributes = "id accesskey class dir lang style tabindex title role";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- url = Tools._addCacheSuffix(url);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Event attributes can be opt-in/opt-out
+ /*eventAttributes = split("onabort onblur oncancel oncanplay oncanplaythrough onchange onclick onclose oncontextmenu oncuechange " +
+ "ondblclick ondrag ondragend ondragenter ondragleave ondragover ondragstart ondrop ondurationchange onemptied onended " +
+ "onerror onfocus oninput oninvalid onkeydown onkeypress onkeyup onload onloadeddata onloadedmetadata onloadstart " +
+ "onmousedown onmousemove onmouseout onmouseover onmouseup onmousewheel onpause onplay onplaying onprogress onratechange " +
+ "onreset onscroll onseeked onseeking onseeking onselect onshow onstalled onsubmit onsuspend ontimeupdate onvolumechange " +
+ "onwaiting"
+ );*/
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!loadedStates[url]) {
- state = {
- passed: [],
- failed: []
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Block content elements
+ blockContent =
+ "address blockquote div dl fieldset form h1 h2 h3 h4 h5 h6 hr menu ol p pre table ul";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- loadedStates[url] = state;
- } else {
- state = loadedStates[url];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Phrasing content elements from the HTML5 spec (inline)
+ phrasingContent =
+ "a abbr b bdo br button cite code del dfn em embed i iframe img input ins kbd " +
+ "label map noscript object q s samp script select small span strong sub sup " +
+ "textarea u var #text #comment"
+ ;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (loadedCallback) {
- state.passed.push(loadedCallback);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add HTML5 items to globalAttributes, blockContent, phrasingContent
+ if (type != "html4") {
+ globalAttributes += " contenteditable contextmenu draggable dropzone " +
+ "hidden spellcheck translate";
+ blockContent += " article aside details dialog figure header footer hgroup section nav";
+ phrasingContent += " audio canvas command datalist mark meter output picture " +
+ "progress time wbr video ruby bdi keygen";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (errorCallback) {
- state.failed.push(errorCallback);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add HTML4 elements unless it's html5-strict
+ if (type != "html5-strict") {
+ globalAttributes += " xml:lang";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Is loading wait for it to pass
- if (state.status == 1) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ html4PhrasingContent = "acronym applet basefont big font strike tt";
+ phrasingContent = [phrasingContent, html4PhrasingContent].join(' ');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Has finished loading and was success
- if (state.status == 2) {
- passed();
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(split(html4PhrasingContent), function (name) {
+ add(name, "", phrasingContent);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Has finished loading and was a failure
- if (state.status == 3) {
- failed();
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ html4BlockContent = "center dir isindex noframes";
+ blockContent = [blockContent, html4BlockContent].join(' ');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Start loading
- state.status = 1;
- link = document.createElement('link');
- link.rel = 'stylesheet';
- link.type = 'text/css';
- link.id = 'u' + (idCount++);
- link.async = false;
- link.defer = false;
- startTime = new Date().getTime();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Flow content elements from the HTML5 spec (block+inline)
+ flowContent = [blockContent, phrasingContent].join(' ');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Feature detect onload on link element and sniff older webkits since it has an broken onload event
- if ("onload" in link && !isOldWebKit()) {
- link.onload = waitForWebKitLinkLoaded;
- link.onerror = failed;
- } else {
- // Sniff for old Firefox that doesn't support the onload event on link elements
- // TODO: Remove this in the future when everyone uses modern browsers
- if (navigator.userAgent.indexOf("Firefox") > 0) {
- style = document.createElement('style');
- style.textContent = '@import "' + url + '"';
- waitForGeckoLinkLoaded();
- appendToHead(style);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(split(html4BlockContent), function (name) {
+ add(name, "", flowContent);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Use the id owner on older webkits
- waitForWebKitLinkLoaded();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Flow content elements from the HTML5 spec (block+inline)
+ flowContent = flowContent || [blockContent, phrasingContent].join(" ");
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- appendToHead(link);
- link.href = url;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // HTML4 base schema TODO: Move HTML5 specific attributes to HTML5 specific if statement
+ // Schema items <element name>, <specific attributes>, <children ..>
+ add("html", "manifest", "head body");
+ add("head", "", "base command link meta noscript script style title");
+ add("title hr noscript br");
+ add("base", "href target");
+ add("link", "href rel media hreflang type sizes hreflang");
+ add("meta", "name http-equiv content charset");
+ add("style", "media type scoped");
+ add("script", "src async defer type charset");
+ add("body", "onafterprint onbeforeprint onbeforeunload onblur onerror onfocus " +
+ "onhashchange onload onmessage onoffline ononline onpagehide onpageshow " +
+ "onpopstate onresize onscroll onstorage onunload", flowContent);
+ add("address dt dd div caption", "", flowContent);
+ add("h1 h2 h3 h4 h5 h6 pre p abbr code var samp kbd sub sup i b u bdo span legend em strong small s cite dfn", "", phrasingContent);
+ add("blockquote", "cite", flowContent);
+ add("ol", "reversed start type", "li");
+ add("ul", "", "li");
+ add("li", "value", flowContent);
+ add("dl", "", "dt dd");
+ add("a", "href target rel media hreflang type", phrasingContent);
+ add("q", "cite", phrasingContent);
+ add("ins del", "cite datetime", flowContent);
+ add("img", "src sizes srcset alt usemap ismap width height");
+ add("iframe", "src name width height", flowContent);
+ add("embed", "src type width height");
+ add("object", "data type typemustmatch name usemap form width height", [flowContent, "param"].join(' '));
+ add("param", "name value");
+ add("map", "name", [flowContent, "area"].join(' '));
+ add("area", "alt coords shape href target rel media hreflang type");
+ add("table", "border", "caption colgroup thead tfoot tbody tr" + (type == "html4" ? " col" : ""));
+ add("colgroup", "span", "col");
+ add("col", "span");
+ add("tbody thead tfoot", "", "tr");
+ add("tr", "", "td th");
+ add("td", "colspan rowspan headers", flowContent);
+ add("th", "colspan rowspan headers scope abbr", flowContent);
+ add("form", "accept-charset action autocomplete enctype method name novalidate target", flowContent);
+ add("fieldset", "disabled form name", [flowContent, "legend"].join(' '));
+ add("label", "form for", phrasingContent);
+ add("input", "accept alt autocomplete checked dirname disabled form formaction formenctype formmethod formnovalidate " +
+ "formtarget height list max maxlength min multiple name pattern readonly required size src step type value width"
+ );
+ add("button", "disabled form formaction formenctype formmethod formnovalidate formtarget name type value",
+ type == "html4" ? flowContent : phrasingContent);
+ add("select", "disabled form multiple name required size", "option optgroup");
+ add("optgroup", "disabled label", "option");
+ add("option", "disabled label selected value");
+ add("textarea", "cols dirname disabled form maxlength name readonly required rows wrap");
+ add("menu", "type label", [flowContent, "li"].join(' '));
+ add("noscript", "", flowContent);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.load = load;
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Extend with HTML5 elements
+ if (type != "html4") {
+ add("wbr");
+ add("ruby", "", [phrasingContent, "rt rp"].join(' '));
+ add("figcaption", "", flowContent);
+ add("mark rt rp summary bdi", "", phrasingContent);
+ add("canvas", "width height", flowContent);
+ add("video", "src crossorigin poster preload autoplay mediagroup loop " +
+ "muted controls width height buffered", [flowContent, "track source"].join(' '));
+ add("audio", "src crossorigin preload autoplay mediagroup loop muted controls " +
+ "buffered volume", [flowContent, "track source"].join(' '));
+ add("picture", "", "img source");
+ add("source", "src srcset type media sizes");
+ add("track", "kind src srclang label default");
+ add("datalist", "", [phrasingContent, "option"].join(' '));
+ add("article section nav aside header footer", "", flowContent);
+ add("hgroup", "", "h1 h2 h3 h4 h5 h6");
+ add("figure", "", [flowContent, "figcaption"].join(' '));
+ add("time", "datetime", phrasingContent);
+ add("dialog", "open", flowContent);
+ add("command", "type label icon disabled checked radiogroup command");
+ add("output", "for form name", phrasingContent);
+ add("progress", "value max", phrasingContent);
+ add("meter", "value min max low high optimum", phrasingContent);
+ add("details", "open", [flowContent, "summary"].join(' '));
+ add("keygen", "autofocus challenge disabled form keytype name");
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/dom/DOMUtils.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Extend with HTML4 attributes unless it's html5-strict
+ if (type != "html5-strict") {
+ addAttrs("script", "language xml:space");
+ addAttrs("style", "xml:space");
+ addAttrs("object", "declare classid code codebase codetype archive standby align border hspace vspace");
+ addAttrs("embed", "align name hspace vspace");
+ addAttrs("param", "valuetype type");
+ addAttrs("a", "charset name rev shape coords");
+ addAttrs("br", "clear");
+ addAttrs("applet", "codebase archive code object alt name width height align hspace vspace");
+ addAttrs("img", "name longdesc align border hspace vspace");
+ addAttrs("iframe", "longdesc frameborder marginwidth marginheight scrolling align");
+ addAttrs("font basefont", "size color face");
+ addAttrs("input", "usemap align");
+ addAttrs("select", "onchange");
+ addAttrs("textarea");
+ addAttrs("h1 h2 h3 h4 h5 h6 div p legend caption", "align");
+ addAttrs("ul", "type compact");
+ addAttrs("li", "type");
+ addAttrs("ol dl menu dir", "compact");
+ addAttrs("pre", "width xml:space");
+ addAttrs("hr", "align noshade size width");
+ addAttrs("isindex", "prompt");
+ addAttrs("table", "summary width frame rules cellspacing cellpadding align bgcolor");
+ addAttrs("col", "width align char charoff valign");
+ addAttrs("colgroup", "width align char charoff valign");
+ addAttrs("thead", "align char charoff valign");
+ addAttrs("tr", "align char charoff valign bgcolor");
+ addAttrs("th", "axis align char charoff valign nowrap bgcolor width height");
+ addAttrs("form", "accept");
+ addAttrs("td", "abbr axis scope align char charoff valign nowrap bgcolor width height");
+ addAttrs("tfoot", "align char charoff valign");
+ addAttrs("tbody", "align char charoff valign");
+ addAttrs("area", "nohref");
+ addAttrs("body", "background bgcolor text link vlink alink");
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Extend with HTML5 attributes unless it's html4
+ if (type != "html4") {
+ addAttrs("input button select textarea", "autofocus");
+ addAttrs("input textarea", "placeholder");
+ addAttrs("a", "download");
+ addAttrs("link script img", "crossorigin");
+ addAttrs("iframe", "sandbox seamless allowfullscreen"); // Excluded: srcdoc
+ }
+
+ // Special: iframe, ruby, video, audio, label
+
+ // Delete children of the same name from it's parent
+ // For example: form can't have a child of the name form
+ each(split('a form meter progress dfn'), function (name) {
+ if (schema[name]) {
+ delete schema[name].children[name];
+ }
+ });
+
+ // Delete header, footer, sectioning and heading content descendants
+ /*each('dt th address', function(name) {
+ delete schema[name].children[name];
+ });*/
+
+ // Caption can't have tables
+ delete schema.caption.children.table;
+
+ // Delete scripts by default due to possible XSS
+ delete schema.script;
+
+ // TODO: LI:s can only have value if parent is OL
+
+ // TODO: Handle transparent elements
+ // a ins del canvas map
+
+ mapCache[type] = schema;
+
+ return schema;
+ }
+
+ function compileElementMap(value, mode) {
+ var styles;
+
+ if (value) {
+ styles = {};
+
+ if (typeof value == 'string') {
+ value = {
+ '*': value
+ };
+ }
+
+ // Convert styles into a rule list
+ each(value, function (value, key) {
+ styles[key] = styles[key.toUpperCase()] = mode == 'map' ? makeMap(value, /[, ]/) : explode(value, /[, ]/);
+ });
+ }
+
+ return styles;
+ }
+
+ /**
+ * Constructs a new Schema instance.
+ *
+ * @constructor
+ * @method Schema
+ * @param {Object} settings Name/value settings object.
+ */
+ return function (settings) {
+ var self = this, elements = {}, children = {}, patternElements = [], validStyles, invalidStyles, schemaItems;
+ var whiteSpaceElementsMap, selfClosingElementsMap, shortEndedElementsMap, boolAttrMap, validClasses;
+ var blockElementsMap, nonEmptyElementsMap, moveCaretBeforeOnEnterElementsMap, textBlockElementsMap, textInlineElementsMap;
+ var customElementsMap = {}, specialElements = {};
+
+ // Creates an lookup table map object for the specified option or the default value
+ function createLookupTable(option, defaultValue, extendWith) {
+ var value = settings[option];
+
+ if (!value) {
+ // Get cached default map or make it if needed
+ value = mapCache[option];
+
+ if (!value) {
+ value = makeMap(defaultValue, ' ', makeMap(defaultValue.toUpperCase(), ' '));
+ value = extend(value, extendWith);
+
+ mapCache[option] = value;
+ }
+ } else {
+ // Create custom map
+ value = makeMap(value, /[, ]/, makeMap(value.toUpperCase(), /[, ]/));
+ }
+
+ return value;
+ }
+
+ settings = settings || {};
+ schemaItems = compileSchema(settings.schema);
+
+ // Allow all elements and attributes if verify_html is set to false
+ if (settings.verify_html === false) {
+ settings.valid_elements = '*[*]';
+ }
+
+ validStyles = compileElementMap(settings.valid_styles);
+ invalidStyles = compileElementMap(settings.invalid_styles, 'map');
+ validClasses = compileElementMap(settings.valid_classes, 'map');
+
+ // Setup map objects
+ whiteSpaceElementsMap = createLookupTable(
+ 'whitespace_elements',
+ 'pre script noscript style textarea video audio iframe object code'
+ );
+ selfClosingElementsMap = createLookupTable('self_closing_elements', 'colgroup dd dt li option p td tfoot th thead tr');
+ shortEndedElementsMap = createLookupTable('short_ended_elements', 'area base basefont br col frame hr img input isindex link ' +
+ 'meta param embed source wbr track');
+ boolAttrMap = createLookupTable('boolean_attributes', 'checked compact declare defer disabled ismap multiple nohref noresize ' +
+ 'noshade nowrap readonly selected autoplay loop controls');
+ nonEmptyElementsMap = createLookupTable('non_empty_elements', 'td th iframe video audio object ' +
+ 'script pre code', shortEndedElementsMap);
+ moveCaretBeforeOnEnterElementsMap = createLookupTable('move_caret_before_on_enter_elements', 'table', nonEmptyElementsMap);
+ textBlockElementsMap = createLookupTable('text_block_elements', 'h1 h2 h3 h4 h5 h6 p div address pre form ' +
+ 'blockquote center dir fieldset header footer article section hgroup aside nav figure');
+ blockElementsMap = createLookupTable('block_elements', 'hr table tbody thead tfoot ' +
+ 'th tr td li ol ul caption dl dt dd noscript menu isindex option ' +
+ 'datalist select optgroup figcaption', textBlockElementsMap);
+ textInlineElementsMap = createLookupTable('text_inline_elements', 'span strong b em i font strike u var cite ' +
+ 'dfn code mark q sup sub samp');
+
+ each((settings.special || 'script noscript style textarea').split(' '), function (name) {
+ specialElements[name] = new RegExp('<\/' + name + '[^>]*>', 'gi');
+ });
+
+ // Converts a wildcard expression string to a regexp for example *a will become /.*a/.
+ function patternToRegExp(str) {
+ return new RegExp('^' + str.replace(/([?+*])/g, '.$1') + '$');
+ }
+
+ // Parses the specified valid_elements string and adds to the current rules
+ // This function is a bit hard to read since it's heavily optimized for speed
+ function addValidElements(validElements) {
+ var ei, el, ai, al, matches, element, attr, attrData, elementName, attrName, attrType, attributes, attributesOrder,
+ prefix, outputName, globalAttributes, globalAttributesOrder, key, value,
+ elementRuleRegExp = /^([#+\-])?([^\[!\/]+)(?:\/([^\[!]+))?(?:(!?)\[([^\]]+)\])?$/,
+ attrRuleRegExp = /^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/,
+ hasPatternsRegExp = /[*?+]/;
+
+ if (validElements) {
+ // Split valid elements into an array with rules
+ validElements = split(validElements, ',');
+
+ if (elements['@']) {
+ globalAttributes = elements['@'].attributes;
+ globalAttributesOrder = elements['@'].attributesOrder;
+ }
+
+ // Loop all rules
+ for (ei = 0, el = validElements.length; ei < el; ei++) {
+ // Parse element rule
+ matches = elementRuleRegExp.exec(validElements[ei]);
+ if (matches) {
+ // Setup local names for matches
+ prefix = matches[1];
+ elementName = matches[2];
+ outputName = matches[3];
+ attrData = matches[5];
+
+ // Create new attributes and attributesOrder
+ attributes = {};
+ attributesOrder = [];
+
+ // Create the new element
+ element = {
+ attributes: attributes,
+ attributesOrder: attributesOrder
+ };
+
+ // Padd empty elements prefix
+ if (prefix === '#') {
+ element.paddEmpty = true;
+ }
+
+ // Remove empty elements prefix
+ if (prefix === '-') {
+ element.removeEmpty = true;
+ }
+
+ if (matches[4] === '!') {
+ element.removeEmptyAttrs = true;
+ }
+
+ // Copy attributes from global rule into current rule
+ if (globalAttributes) {
+ for (key in globalAttributes) {
+ attributes[key] = globalAttributes[key];
+ }
+
+ attributesOrder.push.apply(attributesOrder, globalAttributesOrder);
+ }
+
+ // Attributes defined
+ if (attrData) {
+ attrData = split(attrData, '|');
+ for (ai = 0, al = attrData.length; ai < al; ai++) {
+ matches = attrRuleRegExp.exec(attrData[ai]);
+ if (matches) {
+ attr = {};
+ attrType = matches[1];
+ attrName = matches[2].replace(/::/g, ':');
+ prefix = matches[3];
+ value = matches[4];
+
+ // Required
+ if (attrType === '!') {
+ element.attributesRequired = element.attributesRequired || [];
+ element.attributesRequired.push(attrName);
+ attr.required = true;
+ }
+
+ // Denied from global
+ if (attrType === '-') {
+ delete attributes[attrName];
+ attributesOrder.splice(inArray(attributesOrder, attrName), 1);
+ continue;
+ }
+
+ // Default value
+ if (prefix) {
+ // Default value
+ if (prefix === '=') {
+ element.attributesDefault = element.attributesDefault || [];
+ element.attributesDefault.push({ name: attrName, value: value });
+ attr.defaultValue = value;
+ }
+
+ // Forced value
+ if (prefix === ':') {
+ element.attributesForced = element.attributesForced || [];
+ element.attributesForced.push({ name: attrName, value: value });
+ attr.forcedValue = value;
+ }
+
+ // Required values
+ if (prefix === '<') {
+ attr.validValues = makeMap(value, '?');
+ }
+ }
+
+ // Check for attribute patterns
+ if (hasPatternsRegExp.test(attrName)) {
+ element.attributePatterns = element.attributePatterns || [];
+ attr.pattern = patternToRegExp(attrName);
+ element.attributePatterns.push(attr);
+ } else {
+ // Add attribute to order list if it doesn't already exist
+ if (!attributes[attrName]) {
+ attributesOrder.push(attrName);
+ }
+
+ attributes[attrName] = attr;
+ }
+ }
+ }
+ }
+
+ // Global rule, store away these for later usage
+ if (!globalAttributes && elementName == '@') {
+ globalAttributes = attributes;
+ globalAttributesOrder = attributesOrder;
+ }
+
+ // Handle substitute elements such as b/strong
+ if (outputName) {
+ element.outputName = elementName;
+ elements[outputName] = element;
+ }
+
+ // Add pattern or exact element
+ if (hasPatternsRegExp.test(elementName)) {
+ element.pattern = patternToRegExp(elementName);
+ patternElements.push(element);
+ } else {
+ elements[elementName] = element;
+ }
+ }
+ }
+ }
+ }
+
+ function setValidElements(validElements) {
+ elements = {};
+ patternElements = [];
+
+ addValidElements(validElements);
+
+ each(schemaItems, function (element, name) {
+ children[name] = element.children;
+ });
+ }
+
+ // Adds custom non HTML elements to the schema
+ function addCustomElements(customElements) {
+ var customElementRegExp = /^(~)?(.+)$/;
+
+ if (customElements) {
+ // Flush cached items since we are altering the default maps
+ mapCache.text_block_elements = mapCache.block_elements = null;
+
+ each(split(customElements, ','), function (rule) {
+ var matches = customElementRegExp.exec(rule),
+ inline = matches[1] === '~',
+ cloneName = inline ? 'span' : 'div',
+ name = matches[2];
+
+ children[name] = children[cloneName];
+ customElementsMap[name] = cloneName;
+
+ // If it's not marked as inline then add it to valid block elements
+ if (!inline) {
+ blockElementsMap[name.toUpperCase()] = {};
+ blockElementsMap[name] = {};
+ }
+
+ // Add elements clone if needed
+ if (!elements[name]) {
+ var customRule = elements[cloneName];
+
+ customRule = extend({}, customRule);
+ delete customRule.removeEmptyAttrs;
+ delete customRule.removeEmpty;
+
+ elements[name] = customRule;
+ }
+
+ // Add custom elements at span/div positions
+ each(children, function (element, elmName) {
+ if (element[cloneName]) {
+ children[elmName] = element = extend({}, children[elmName]);
+ element[name] = element[cloneName];
+ }
+ });
+ });
+ }
+ }
+
+ // Adds valid children to the schema object
+ function addValidChildren(validChildren) {
+ var childRuleRegExp = /^([+\-]?)(\w+)\[([^\]]+)\]$/;
+
+ // Invalidate the schema cache if the schema is mutated
+ mapCache[settings.schema] = null;
+
+ if (validChildren) {
+ each(split(validChildren, ','), function (rule) {
+ var matches = childRuleRegExp.exec(rule), parent, prefix;
+
+ if (matches) {
+ prefix = matches[1];
+
+ // Add/remove items from default
+ if (prefix) {
+ parent = children[matches[2]];
+ } else {
+ parent = children[matches[2]] = { '#comment': {} };
+ }
+
+ parent = children[matches[2]];
+
+ each(split(matches[3], '|'), function (child) {
+ if (prefix === '-') {
+ delete parent[child];
+ } else {
+ parent[child] = {};
+ }
+ });
+ }
+ });
+ }
+ }
+
+ function getElementRule(name) {
+ var element = elements[name], i;
+
+ // Exact match found
+ if (element) {
+ return element;
+ }
+
+ // No exact match then try the patterns
+ i = patternElements.length;
+ while (i--) {
+ element = patternElements[i];
+
+ if (element.pattern.test(name)) {
+ return element;
+ }
+ }
+ }
+
+ if (!settings.valid_elements) {
+ // No valid elements defined then clone the elements from the schema spec
+ each(schemaItems, function (element, name) {
+ elements[name] = {
+ attributes: element.attributes,
+ attributesOrder: element.attributesOrder
+ };
+
+ children[name] = element.children;
+ });
+
+ // Switch these on HTML4
+ if (settings.schema != "html5") {
+ each(split('strong/b em/i'), function (item) {
+ item = split(item, '/');
+ elements[item[1]].outputName = item[0];
+ });
+ }
+
+ // Add default alt attribute for images, removed since alt="" is treated as presentational.
+ // elements.img.attributesDefault = [{name: 'alt', value: ''}];
+
+ // Remove these if they are empty by default
+ each(split('ol ul sub sup blockquote span font a table tbody tr strong em b i'), function (name) {
+ if (elements[name]) {
+ elements[name].removeEmpty = true;
+ }
+ });
+
+ // Padd these by default
+ each(split('p h1 h2 h3 h4 h5 h6 th td pre div address caption'), function (name) {
+ elements[name].paddEmpty = true;
+ });
+
+ // Remove these if they have no attributes
+ each(split('span'), function (name) {
+ elements[name].removeEmptyAttrs = true;
+ });
+
+ // Remove these by default
+ // TODO: Reenable in 4.1
+ /*each(split('script style'), function(name) {
+ delete elements[name];
+ });*/
+ } else {
+ setValidElements(settings.valid_elements);
+ }
+
+ addCustomElements(settings.custom_elements);
+ addValidChildren(settings.valid_children);
+ addValidElements(settings.extended_valid_elements);
+
+ // Todo: Remove this when we fix list handling to be valid
+ addValidChildren('+ol[ul|ol],+ul[ul|ol]');
+
+
+ // Some elements are not valid by themselves - require parents
+ each({
+ dd: 'dl',
+ dt: 'dl',
+ li: 'ul ol',
+ td: 'tr',
+ th: 'tr',
+ tr: 'tbody thead tfoot',
+ tbody: 'table',
+ thead: 'table',
+ tfoot: 'table',
+ legend: 'fieldset',
+ area: 'map',
+ param: 'video audio object'
+ }, function (parents, item) {
+ if (elements[item]) {
+ elements[item].parentsRequired = split(parents);
+ }
+ });
+
+
+ // Delete invalid elements
+ if (settings.invalid_elements) {
+ each(explode(settings.invalid_elements), function (item) {
+ if (elements[item]) {
+ delete elements[item];
+ }
+ });
+ }
+
+ // If the user didn't allow span only allow internal spans
+ if (!getElementRule('span')) {
+ addValidElements('span[!data-mce-type|*]');
+ }
+
+ /**
+ * Name/value map object with valid parents and children to those parents.
+ *
+ * @example
+ * children = {
+ * div:{p:{}, h1:{}}
+ * };
+ * @field children
+ * @type Object
+ */
+ self.children = children;
+
+ /**
+ * Name/value map object with valid styles for each element.
+ *
+ * @method getValidStyles
+ * @type Object
+ */
+ self.getValidStyles = function () {
+ return validStyles;
+ };
+
+ /**
+ * Name/value map object with valid styles for each element.
+ *
+ * @method getInvalidStyles
+ * @type Object
+ */
+ self.getInvalidStyles = function () {
+ return invalidStyles;
+ };
+
+ /**
+ * Name/value map object with valid classes for each element.
+ *
+ * @method getValidClasses
+ * @type Object
+ */
+ self.getValidClasses = function () {
+ return validClasses;
+ };
+
+ /**
+ * Returns a map with boolean attributes.
+ *
+ * @method getBoolAttrs
+ * @return {Object} Name/value lookup map for boolean attributes.
+ */
+ self.getBoolAttrs = function () {
+ return boolAttrMap;
+ };
+
+ /**
+ * Returns a map with block elements.
+ *
+ * @method getBlockElements
+ * @return {Object} Name/value lookup map for block elements.
+ */
+ self.getBlockElements = function () {
+ return blockElementsMap;
+ };
+
+ /**
+ * Returns a map with text block elements. Such as: p,h1-h6,div,address
+ *
+ * @method getTextBlockElements
+ * @return {Object} Name/value lookup map for block elements.
+ */
+ self.getTextBlockElements = function () {
+ return textBlockElementsMap;
+ };
+
+ /**
+ * Returns a map of inline text format nodes for example strong/span or ins.
+ *
+ * @method getTextInlineElements
+ * @return {Object} Name/value lookup map for text format elements.
+ */
+ self.getTextInlineElements = function () {
+ return textInlineElementsMap;
+ };
+
+ /**
+ * Returns a map with short ended elements such as BR or IMG.
+ *
+ * @method getShortEndedElements
+ * @return {Object} Name/value lookup map for short ended elements.
+ */
+ self.getShortEndedElements = function () {
+ return shortEndedElementsMap;
+ };
+
+ /**
+ * Returns a map with self closing tags such as <li>.
+ *
+ * @method getSelfClosingElements
+ * @return {Object} Name/value lookup map for self closing tags elements.
+ */
+ self.getSelfClosingElements = function () {
+ return selfClosingElementsMap;
+ };
+
+ /**
+ * Returns a map with elements that should be treated as contents regardless if it has text
+ * content in them or not such as TD, VIDEO or IMG.
+ *
+ * @method getNonEmptyElements
+ * @return {Object} Name/value lookup map for non empty elements.
+ */
+ self.getNonEmptyElements = function () {
+ return nonEmptyElementsMap;
+ };
+
+ /**
+ * Returns a map with elements that the caret should be moved in front of after enter is
+ * pressed
+ *
+ * @method getMoveCaretBeforeOnEnterElements
+ * @return {Object} Name/value lookup map for elements to place the caret in front of.
+ */
+ self.getMoveCaretBeforeOnEnterElements = function () {
+ return moveCaretBeforeOnEnterElementsMap;
+ };
+
+ /**
+ * Returns a map with elements where white space is to be preserved like PRE or SCRIPT.
+ *
+ * @method getWhiteSpaceElements
+ * @return {Object} Name/value lookup map for white space elements.
+ */
+ self.getWhiteSpaceElements = function () {
+ return whiteSpaceElementsMap;
+ };
+
+ /**
+ * Returns a map with special elements. These are elements that needs to be parsed
+ * in a special way such as script, style, textarea etc. The map object values
+ * are regexps used to find the end of the element.
+ *
+ * @method getSpecialElements
+ * @return {Object} Name/value lookup map for special elements.
+ */
+ self.getSpecialElements = function () {
+ return specialElements;
+ };
+
+ /**
+ * Returns true/false if the specified element and it's child is valid or not
+ * according to the schema.
+ *
+ * @method isValidChild
+ * @param {String} name Element name to check for.
+ * @param {String} child Element child to verify.
+ * @return {Boolean} True/false if the element is a valid child of the specified parent.
+ */
+ self.isValidChild = function (name, child) {
+ var parent = children[name.toLowerCase()];
+
+ return !!(parent && parent[child.toLowerCase()]);
+ };
+
+ /**
+ * Returns true/false if the specified element name and optional attribute is
+ * valid according to the schema.
+ *
+ * @method isValid
+ * @param {String} name Name of element to check.
+ * @param {String} attr Optional attribute name to check for.
+ * @return {Boolean} True/false if the element and attribute is valid.
+ */
+ self.isValid = function (name, attr) {
+ var attrPatterns, i, rule = getElementRule(name);
+
+ // Check if it's a valid element
+ if (rule) {
+ if (attr) {
+ // Check if attribute name exists
+ if (rule.attributes[attr]) {
+ return true;
+ }
+
+ // Check if attribute matches a regexp pattern
+ attrPatterns = rule.attributePatterns;
+ if (attrPatterns) {
+ i = attrPatterns.length;
+ while (i--) {
+ if (attrPatterns[i].pattern.test(name)) {
+ return true;
+ }
+ }
+ }
+ } else {
+ return true;
+ }
+ }
+
+ // No match
+ return false;
+ };
+
+ /**
+ * Returns true/false if the specified element is valid or not
+ * according to the schema.
+ *
+ * @method getElementRule
+ * @param {String} name Element name to check for.
+ * @return {Object} Element object or undefined if the element isn't valid.
+ */
+ self.getElementRule = getElementRule;
+
+ /**
+ * Returns an map object of all custom elements.
+ *
+ * @method getCustomElements
+ * @return {Object} Name/value map object of all custom elements.
+ */
+ self.getCustomElements = function () {
+ return customElementsMap;
+ };
+
+ /**
+ * Parses a valid elements string and adds it to the schema. The valid elements
+ * format is for example "element[attr=default|otherattr]".
+ * Existing rules will be replaced with the ones specified, so this extends the schema.
+ *
+ * @method addValidElements
+ * @param {String} valid_elements String in the valid elements format to be parsed.
+ */
+ self.addValidElements = addValidElements;
+
+ /**
+ * Parses a valid elements string and sets it to the schema. The valid elements
+ * format is for example "element[attr=default|otherattr]".
+ * Existing rules will be replaced with the ones specified, so this extends the schema.
+ *
+ * @method setValidElements
+ * @param {String} valid_elements String in the valid elements format to be parsed.
+ */
+ self.setValidElements = setValidElements;
+
+ /**
+ * Adds custom non HTML elements to the schema.
+ *
+ * @method addCustomElements
+ * @param {String} custom_elements Comma separated list of custom elements to add.
+ */
+ self.addCustomElements = addCustomElements;
+
+ /**
+ * Parses a valid children string and adds them to the schema structure. The valid children
+ * format is for example: "element[child1|child2]".
+ *
+ * @method addValidChildren
+ * @param {String} valid_children Valid children elements string to parse
+ */
+ self.addValidChildren = addValidChildren;
+
+ self.elements = elements;
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * DOMUtils.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -7541,1857 +9603,1864 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * // Add a class to an element by id inside the editor
</span><span class="cx" style="display: block; padding: 0 10px"> * tinymce.activeEditor.dom.addClass('someid', 'someclass');
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/dom/DOMUtils", [
- "tinymce/dom/Sizzle",
- "tinymce/dom/DomQuery",
- "tinymce/html/Styles",
- "tinymce/dom/EventUtils",
- "tinymce/dom/TreeWalker",
- "tinymce/dom/Range",
- "tinymce/html/Entities",
- "tinymce/Env",
- "tinymce/util/Tools",
- "tinymce/dom/StyleSheetLoader"
-], function(Sizzle, $, Styles, EventUtils, TreeWalker, Range, Entities, Env, Tools, StyleSheetLoader) {
- // Shorten names
- var each = Tools.each, is = Tools.is, grep = Tools.grep, trim = Tools.trim;
- var isIE = Env.ie;
- var simpleSelectorRe = /^([a-z0-9],?)+$/i;
- var whiteSpaceRegExp = /^[ \t\r\n]*$/;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.DOMUtils',
+ [
+ 'tinymce.core.dom.DomQuery',
+ 'tinymce.core.dom.EventUtils',
+ 'tinymce.core.dom.Range',
+ 'tinymce.core.dom.Sizzle',
+ 'tinymce.core.dom.StyleSheetLoader',
+ 'tinymce.core.dom.TreeWalker',
+ 'tinymce.core.Env',
+ 'tinymce.core.html.Entities',
+ 'tinymce.core.html.Schema',
+ 'tinymce.core.html.Styles',
+ 'tinymce.core.util.Tools'
+ ],
+ function (DomQuery, EventUtils, Range, Sizzle, StyleSheetLoader, TreeWalker, Env, Entities, Schema, Styles, Tools) {
+ // Shorten names
+ var each = Tools.each, is = Tools.is, grep = Tools.grep, trim = Tools.trim;
+ var isIE = Env.ie;
+ var simpleSelectorRe = /^([a-z0-9],?)+$/i;
+ var whiteSpaceRegExp = /^[ \t\r\n]*$/;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setupAttrHooks(domUtils, settings) {
- var attrHooks = {}, keepValues = settings.keep_values, keepUrlHook;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setupAttrHooks(domUtils, settings) {
+ var attrHooks = {}, keepValues = settings.keep_values, keepUrlHook;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- keepUrlHook = {
- set: function($elm, value, name) {
- if (settings.url_converter) {
- value = settings.url_converter.call(settings.url_converter_scope || domUtils, value, name, $elm[0]);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ keepUrlHook = {
+ set: function ($elm, value, name) {
+ if (settings.url_converter) {
+ value = settings.url_converter.call(settings.url_converter_scope || domUtils, value, name, $elm[0]);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $elm.attr('data-mce-' + name, value).attr(name, value);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $elm.attr('data-mce-' + name, value).attr(name, value);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- get: function($elm, name) {
- return $elm.attr('data-mce-' + name) || $elm.attr(name);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ get: function ($elm, name) {
+ return $elm.attr('data-mce-' + name) || $elm.attr(name);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- attrHooks = {
- style: {
- set: function($elm, value) {
- if (value !== null && typeof value === 'object') {
- $elm.css(value);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ attrHooks = {
+ style: {
+ set: function ($elm, value) {
+ if (value !== null && typeof value === 'object') {
+ $elm.css(value);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (keepValues) {
- $elm.attr('data-mce-style', value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (keepValues) {
+ $elm.attr('data-mce-style', value);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $elm.attr('style', value);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $elm.attr('style', value);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- get: function($elm) {
- var value = $elm.attr('data-mce-style') || $elm.attr('style');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ get: function ($elm) {
+ var value = $elm.attr('data-mce-style') || $elm.attr('style');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- value = domUtils.serializeStyle(domUtils.parseStyle(value), $elm[0].nodeName);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ value = domUtils.serializeStyle(domUtils.parseStyle(value), $elm[0].nodeName);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return value;
- }
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return value;
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (keepValues) {
- attrHooks.href = attrHooks.src = keepUrlHook;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (keepValues) {
+ attrHooks.href = attrHooks.src = keepUrlHook;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return attrHooks;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return attrHooks;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function updateInternalStyleAttr(domUtils, $elm) {
- var value = $elm.attr('style');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function updateInternalStyleAttr(domUtils, $elm) {
+ var value = $elm.attr('style');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- value = domUtils.serializeStyle(domUtils.parseStyle(value), $elm[0].nodeName);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ value = domUtils.serializeStyle(domUtils.parseStyle(value), $elm[0].nodeName);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!value) {
- value = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!value) {
+ value = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $elm.attr('data-mce-style', value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $elm.attr('data-mce-style', value);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function nodeIndex(node, normalized) {
- var idx = 0, lastNodeType, nodeType;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function nodeIndex(node, normalized) {
+ var idx = 0, lastNodeType, nodeType;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node) {
- for (lastNodeType = node.nodeType, node = node.previousSibling; node; node = node.previousSibling) {
- nodeType = node.nodeType;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node) {
+ for (lastNodeType = node.nodeType, node = node.previousSibling; node; node = node.previousSibling) {
+ nodeType = node.nodeType;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Normalize text nodes
- if (normalized && nodeType == 3) {
- if (nodeType == lastNodeType || !node.nodeValue.length) {
- continue;
- }
- }
- idx++;
- lastNodeType = nodeType;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Normalize text nodes
+ if (normalized && nodeType == 3) {
+ if (nodeType == lastNodeType || !node.nodeValue.length) {
+ continue;
+ }
+ }
+ idx++;
+ lastNodeType = nodeType;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return idx;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return idx;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a new DOMUtils instance. Consult the Wiki for more details on settings etc for this class.
- *
- * @constructor
- * @method DOMUtils
- * @param {Document} doc Document reference to bind the utility class to.
- * @param {settings} settings Optional settings collection.
- */
- function DOMUtils(doc, settings) {
- var self = this, blockElementsMap;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a new DOMUtils instance. Consult the Wiki for more details on settings etc for this class.
+ *
+ * @constructor
+ * @method DOMUtils
+ * @param {Document} doc Document reference to bind the utility class to.
+ * @param {settings} settings Optional settings collection.
+ */
+ function DOMUtils(doc, settings) {
+ var self = this, blockElementsMap;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.doc = doc;
- self.win = window;
- self.files = {};
- self.counter = 0;
- self.stdMode = !isIE || doc.documentMode >= 8;
- self.boxModel = !isIE || doc.compatMode == "CSS1Compat" || self.stdMode;
- self.styleSheetLoader = new StyleSheetLoader(doc);
- self.boundEvents = [];
- self.settings = settings = settings || {};
- self.schema = settings.schema;
- self.styles = new Styles({
- url_converter: settings.url_converter,
- url_converter_scope: settings.url_converter_scope
- }, settings.schema);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.doc = doc;
+ self.win = window;
+ self.files = {};
+ self.counter = 0;
+ self.stdMode = !isIE || doc.documentMode >= 8;
+ self.boxModel = !isIE || doc.compatMode == "CSS1Compat" || self.stdMode;
+ self.styleSheetLoader = new StyleSheetLoader(doc);
+ self.boundEvents = [];
+ self.settings = settings = settings || {};
+ self.schema = settings.schema ? settings.schema : new Schema({});
+ self.styles = new Styles({
+ url_converter: settings.url_converter,
+ url_converter_scope: settings.url_converter_scope
+ }, settings.schema);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.fixDoc(doc);
- self.events = settings.ownEvents ? new EventUtils(settings.proxy) : EventUtils.Event;
- self.attrHooks = setupAttrHooks(self, settings);
- blockElementsMap = settings.schema ? settings.schema.getBlockElements() : {};
- self.$ = $.overrideDefaults(function() {
- return {
- context: doc,
- element: self.getRoot()
- };
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.fixDoc(doc);
+ self.events = settings.ownEvents ? new EventUtils(settings.proxy) : EventUtils.Event;
+ self.attrHooks = setupAttrHooks(self, settings);
+ blockElementsMap = settings.schema ? settings.schema.getBlockElements() : {};
+ self.$ = DomQuery.overrideDefaults(function () {
+ return {
+ context: doc,
+ element: self.getRoot()
+ };
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the specified element is a block element or not.
- *
- * @method isBlock
- * @param {Node/String} node Element/Node to check.
- * @return {Boolean} True/False state if the node is a block element or not.
- */
- self.isBlock = function(node) {
- // Fix for #5446
- if (!node) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the specified element is a block element or not.
+ *
+ * @method isBlock
+ * @param {Node/String} node Element/Node to check.
+ * @return {Boolean} True/False state if the node is a block element or not.
+ */
+ self.isBlock = function (node) {
+ // Fix for #5446
+ if (!node) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // This function is called in module pattern style since it might be executed with the wrong this scope
- var type = node.nodeType;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // This function is called in module pattern style since it might be executed with the wrong this scope
+ var type = node.nodeType;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If it's a node then check the type and use the nodeName
- if (type) {
- return !!(type === 1 && blockElementsMap[node.nodeName]);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If it's a node then check the type and use the nodeName
+ if (type) {
+ return !!(type === 1 && blockElementsMap[node.nodeName]);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return !!blockElementsMap[node];
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return !!blockElementsMap[node];
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DOMUtils.prototype = {
- $$: function(elm) {
- if (typeof elm == 'string') {
- elm = this.get(elm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOMUtils.prototype = {
+ $$: function (elm) {
+ if (typeof elm == 'string') {
+ elm = this.get(elm);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this.$(elm);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this.$(elm);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- root: null,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ root: null,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- fixDoc: function(doc) {
- var settings = this.settings, name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ fixDoc: function (doc) {
+ var settings = this.settings, name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isIE && settings.schema) {
- // Add missing HTML 4/5 elements to IE
- ('abbr article aside audio canvas ' +
- 'details figcaption figure footer ' +
- 'header hgroup mark menu meter nav ' +
- 'output progress section summary ' +
- 'time video').replace(/\w+/g, function(name) {
- doc.createElement(name);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isIE && settings.schema) {
+ // Add missing HTML 4/5 elements to IE
+ ('abbr article aside audio canvas ' +
+ 'details figcaption figure footer ' +
+ 'header hgroup mark menu meter nav ' +
+ 'output progress section summary ' +
+ 'time video').replace(/\w+/g, function (name) {
+ doc.createElement(name);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Create all custom elements
- for (name in settings.schema.getCustomElements()) {
- doc.createElement(name);
- }
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Create all custom elements
+ for (name in settings.schema.getCustomElements()) {
+ doc.createElement(name);
+ }
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- clone: function(node, deep) {
- var self = this, clone, doc;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ clone: function (node, deep) {
+ var self = this, clone, doc;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // TODO: Add feature detection here in the future
- if (!isIE || node.nodeType !== 1 || deep) {
- return node.cloneNode(deep);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // TODO: Add feature detection here in the future
+ if (!isIE || node.nodeType !== 1 || deep) {
+ return node.cloneNode(deep);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- doc = self.doc;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ doc = self.doc;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Make a HTML5 safe shallow copy
- if (!deep) {
- clone = doc.createElement(node.nodeName);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Make a HTML5 safe shallow copy
+ if (!deep) {
+ clone = doc.createElement(node.nodeName);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Copy attribs
- each(self.getAttribs(node), function(attr) {
- self.setAttrib(clone, attr.nodeName, self.getAttrib(node, attr.nodeName));
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Copy attribs
+ each(self.getAttribs(node), function (attr) {
+ self.setAttrib(clone, attr.nodeName, self.getAttrib(node, attr.nodeName));
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return clone;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return clone;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return clone.firstChild;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return clone.firstChild;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the root node of the document. This is normally the body but might be a DIV. Parents like getParent will not
- * go above the point of this root node.
- *
- * @method getRoot
- * @return {Element} Root element for the utility class.
- */
- getRoot: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the root node of the document. This is normally the body but might be a DIV. Parents like getParent will not
+ * go above the point of this root node.
+ *
+ * @method getRoot
+ * @return {Element} Root element for the utility class.
+ */
+ getRoot: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self.settings.root_element || self.doc.body;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self.settings.root_element || self.doc.body;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the viewport of the window.
- *
- * @method getViewPort
- * @param {Window} win Optional window to get viewport of.
- * @return {Object} Viewport object with fields x, y, w and h.
- */
- getViewPort: function(win) {
- var doc, rootElm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the viewport of the window.
+ *
+ * @method getViewPort
+ * @param {Window} win Optional window to get viewport of.
+ * @return {Object} Viewport object with fields x, y, w and h.
+ */
+ getViewPort: function (win) {
+ var doc, rootElm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- win = !win ? this.win : win;
- doc = win.document;
- rootElm = this.boxModel ? doc.documentElement : doc.body;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ win = !win ? this.win : win;
+ doc = win.document;
+ rootElm = this.boxModel ? doc.documentElement : doc.body;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Returns viewport size excluding scrollbars
- return {
- x: win.pageXOffset || rootElm.scrollLeft,
- y: win.pageYOffset || rootElm.scrollTop,
- w: win.innerWidth || rootElm.clientWidth,
- h: win.innerHeight || rootElm.clientHeight
- };
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Returns viewport size excluding scrollbars
+ return {
+ x: win.pageXOffset || rootElm.scrollLeft,
+ y: win.pageYOffset || rootElm.scrollTop,
+ w: win.innerWidth || rootElm.clientWidth,
+ h: win.innerHeight || rootElm.clientHeight
+ };
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the rectangle for a specific element.
- *
- * @method getRect
- * @param {Element/String} elm Element object or element ID to get rectangle from.
- * @return {object} Rectangle for specified element object with x, y, w, h fields.
- */
- getRect: function(elm) {
- var self = this, pos, size;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the rectangle for a specific element.
+ *
+ * @method getRect
+ * @param {Element/String} elm Element object or element ID to get rectangle from.
+ * @return {object} Rectangle for specified element object with x, y, w, h fields.
+ */
+ getRect: function (elm) {
+ var self = this, pos, size;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elm = self.get(elm);
- pos = self.getPos(elm);
- size = self.getSize(elm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elm = self.get(elm);
+ pos = self.getPos(elm);
+ size = self.getSize(elm);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- x: pos.x, y: pos.y,
- w: size.w, h: size.h
- };
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ x: pos.x, y: pos.y,
+ w: size.w, h: size.h
+ };
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the size dimensions of the specified element.
- *
- * @method getSize
- * @param {Element/String} elm Element object or element ID to get rectangle from.
- * @return {object} Rectangle for specified element object with w, h fields.
- */
- getSize: function(elm) {
- var self = this, w, h;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the size dimensions of the specified element.
+ *
+ * @method getSize
+ * @param {Element/String} elm Element object or element ID to get rectangle from.
+ * @return {object} Rectangle for specified element object with w, h fields.
+ */
+ getSize: function (elm) {
+ var self = this, w, h;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elm = self.get(elm);
- w = self.getStyle(elm, 'width');
- h = self.getStyle(elm, 'height');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elm = self.get(elm);
+ w = self.getStyle(elm, 'width');
+ h = self.getStyle(elm, 'height');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Non pixel value, then force offset/clientWidth
- if (w.indexOf('px') === -1) {
- w = 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Non pixel value, then force offset/clientWidth
+ if (w.indexOf('px') === -1) {
+ w = 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Non pixel value, then force offset/clientWidth
- if (h.indexOf('px') === -1) {
- h = 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Non pixel value, then force offset/clientWidth
+ if (h.indexOf('px') === -1) {
+ h = 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- w: parseInt(w, 10) || elm.offsetWidth || elm.clientWidth,
- h: parseInt(h, 10) || elm.offsetHeight || elm.clientHeight
- };
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ w: parseInt(w, 10) || elm.offsetWidth || elm.clientWidth,
+ h: parseInt(h, 10) || elm.offsetHeight || elm.clientHeight
+ };
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a node by the specified selector function. This function will
- * loop through all parent nodes and call the specified function for each node.
- * If the function then returns true indicating that it has found what it was looking for, the loop execution will then end
- * and the node it found will be returned.
- *
- * @method getParent
- * @param {Node/String} node DOM node to search parents on or ID string.
- * @param {function} selector Selection function or CSS selector to execute on each node.
- * @param {Node} root Optional root element, never go beyond this point.
- * @return {Node} DOM Node or null if it wasn't found.
- */
- getParent: function(node, selector, root) {
- return this.getParents(node, selector, root, false);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a node by the specified selector function. This function will
+ * loop through all parent nodes and call the specified function for each node.
+ * If the function then returns true indicating that it has found what it was looking for, the loop execution will then end
+ * and the node it found will be returned.
+ *
+ * @method getParent
+ * @param {Node/String} node DOM node to search parents on or ID string.
+ * @param {function} selector Selection function or CSS selector to execute on each node.
+ * @param {Node} root Optional root element, never go beyond this point.
+ * @return {Node} DOM Node or null if it wasn't found.
+ */
+ getParent: function (node, selector, root) {
+ return this.getParents(node, selector, root, false);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a node list of all parents matching the specified selector function or pattern.
- * If the function then returns true indicating that it has found what it was looking for and that node will be collected.
- *
- * @method getParents
- * @param {Node/String} node DOM node to search parents on or ID string.
- * @param {function} selector Selection function to execute on each node or CSS pattern.
- * @param {Node} root Optional root element, never go beyond this point.
- * @return {Array} Array of nodes or null if it wasn't found.
- */
- getParents: function(node, selector, root, collect) {
- var self = this, selectorVal, result = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a node list of all parents matching the specified selector function or pattern.
+ * If the function then returns true indicating that it has found what it was looking for and that node will be collected.
+ *
+ * @method getParents
+ * @param {Node/String} node DOM node to search parents on or ID string.
+ * @param {function} selector Selection function to execute on each node or CSS pattern.
+ * @param {Node} root Optional root element, never go beyond this point.
+ * @return {Array} Array of nodes or null if it wasn't found.
+ */
+ getParents: function (node, selector, root, collect) {
+ var self = this, selectorVal, result = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = self.get(node);
- collect = collect === undefined;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = self.get(node);
+ collect = collect === undefined;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Default root on inline mode
- root = root || (self.getRoot().nodeName != 'BODY' ? self.getRoot().parentNode : null);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Default root on inline mode
+ root = root || (self.getRoot().nodeName != 'BODY' ? self.getRoot().parentNode : null);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Wrap node name as func
- if (is(selector, 'string')) {
- selectorVal = selector;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Wrap node name as func
+ if (is(selector, 'string')) {
+ selectorVal = selector;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (selector === '*') {
- selector = function(node) {
- return node.nodeType == 1;
- };
- } else {
- selector = function(node) {
- return self.is(node, selectorVal);
- };
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (selector === '*') {
+ selector = function (node) {
+ return node.nodeType == 1;
+ };
+ } else {
+ selector = function (node) {
+ return self.is(node, selectorVal);
+ };
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (node) {
- if (node == root || !node.nodeType || node.nodeType === 9) {
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (node) {
+ if (node == root || !node.nodeType || node.nodeType === 9) {
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!selector || selector(node)) {
- if (collect) {
- result.push(node);
- } else {
- return node;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!selector || selector(node)) {
+ if (collect) {
+ result.push(node);
+ } else {
+ return node;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return collect ? result : null;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return collect ? result : null;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the specified element by ID or the input element if it isn't a string.
- *
- * @method get
- * @param {String/Element} n Element id to look for or element to just pass though.
- * @return {Element} Element matching the specified id or null if it wasn't found.
- */
- get: function(elm) {
- var name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the specified element by ID or the input element if it isn't a string.
+ *
+ * @method get
+ * @param {String/Element} n Element id to look for or element to just pass though.
+ * @return {Element} Element matching the specified id or null if it wasn't found.
+ */
+ get: function (elm) {
+ var name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elm && this.doc && typeof elm == 'string') {
- name = elm;
- elm = this.doc.getElementById(elm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (elm && this.doc && typeof elm == 'string') {
+ name = elm;
+ elm = this.doc.getElementById(elm);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // IE and Opera returns meta elements when they match the specified input ID, but getElementsByName seems to do the trick
- if (elm && elm.id !== name) {
- return this.doc.getElementsByName(name)[1];
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // IE and Opera returns meta elements when they match the specified input ID, but getElementsByName seems to do the trick
+ if (elm && elm.id !== name) {
+ return this.doc.getElementsByName(name)[1];
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return elm;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return elm;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the next node that matches selector or function
- *
- * @method getNext
- * @param {Node} node Node to find siblings from.
- * @param {String/function} selector Selector CSS expression or function.
- * @return {Node} Next node item matching the selector or null if it wasn't found.
- */
- getNext: function(node, selector) {
- return this._findSib(node, selector, 'nextSibling');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the next node that matches selector or function
+ *
+ * @method getNext
+ * @param {Node} node Node to find siblings from.
+ * @param {String/function} selector Selector CSS expression or function.
+ * @return {Node} Next node item matching the selector or null if it wasn't found.
+ */
+ getNext: function (node, selector) {
+ return this._findSib(node, selector, 'nextSibling');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the previous node that matches selector or function
- *
- * @method getPrev
- * @param {Node} node Node to find siblings from.
- * @param {String/function} selector Selector CSS expression or function.
- * @return {Node} Previous node item matching the selector or null if it wasn't found.
- */
- getPrev: function(node, selector) {
- return this._findSib(node, selector, 'previousSibling');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the previous node that matches selector or function
+ *
+ * @method getPrev
+ * @param {Node} node Node to find siblings from.
+ * @param {String/function} selector Selector CSS expression or function.
+ * @return {Node} Previous node item matching the selector or null if it wasn't found.
+ */
+ getPrev: function (node, selector) {
+ return this._findSib(node, selector, 'previousSibling');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // #ifndef jquery
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // #ifndef jquery
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Selects specific elements by a CSS level 3 pattern. For example "div#a1 p.test".
- * This function is optimized for the most common patterns needed in TinyMCE but it also performs well enough
- * on more complex patterns.
- *
- * @method select
- * @param {String} selector CSS level 3 pattern to select/find elements by.
- * @param {Object} scope Optional root element/scope element to search in.
- * @return {Array} Array with all matched elements.
- * @example
- * // Adds a class to all paragraphs in the currently active editor
- * tinymce.activeEditor.dom.addClass(tinymce.activeEditor.dom.select('p'), 'someclass');
- *
- * // Adds a class to all spans that have the test class in the currently active editor
- * tinymce.activeEditor.dom.addClass(tinymce.activeEditor.dom.select('span.test'), 'someclass')
- */
- select: function(selector, scope) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Selects specific elements by a CSS level 3 pattern. For example "div#a1 p.test".
+ * This function is optimized for the most common patterns needed in TinyMCE but it also performs well enough
+ * on more complex patterns.
+ *
+ * @method select
+ * @param {String} selector CSS level 3 pattern to select/find elements by.
+ * @param {Object} scope Optional root element/scope element to search in.
+ * @return {Array} Array with all matched elements.
+ * @example
+ * // Adds a class to all paragraphs in the currently active editor
+ * tinymce.activeEditor.dom.addClass(tinymce.activeEditor.dom.select('p'), 'someclass');
+ *
+ * // Adds a class to all spans that have the test class in the currently active editor
+ * tinymce.activeEditor.dom.addClass(tinymce.activeEditor.dom.select('span.test'), 'someclass')
+ */
+ select: function (selector, scope) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /*eslint new-cap:0 */
- return Sizzle(selector, self.get(scope) || self.settings.root_element || self.doc, []);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /*eslint new-cap:0 */
+ return Sizzle(selector, self.get(scope) || self.settings.root_element || self.doc, []);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the specified element matches the specified css pattern.
- *
- * @method is
- * @param {Node/NodeList} elm DOM node to match or an array of nodes to match.
- * @param {String} selector CSS pattern to match the element against.
- */
- is: function(elm, selector) {
- var i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the specified element matches the specified css pattern.
+ *
+ * @method is
+ * @param {Node/NodeList} elm DOM node to match or an array of nodes to match.
+ * @param {String} selector CSS pattern to match the element against.
+ */
+ is: function (elm, selector) {
+ var i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If it isn't an array then try to do some simple selectors instead of Sizzle for to boost performance
- if (elm.length === undefined) {
- // Simple all selector
- if (selector === '*') {
- return elm.nodeType == 1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!elm) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Simple selector just elements
- if (simpleSelectorRe.test(selector)) {
- selector = selector.toLowerCase().split(/,/);
- elm = elm.nodeName.toLowerCase();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If it isn't an array then try to do some simple selectors instead of Sizzle for to boost performance
+ if (elm.length === undefined) {
+ // Simple all selector
+ if (selector === '*') {
+ return elm.nodeType == 1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = selector.length - 1; i >= 0; i--) {
- if (selector[i] == elm) {
- return true;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Simple selector just elements
+ if (simpleSelectorRe.test(selector)) {
+ selector = selector.toLowerCase().split(/,/);
+ elm = elm.nodeName.toLowerCase();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = selector.length - 1; i >= 0; i--) {
+ if (selector[i] == elm) {
+ return true;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Is non element
- if (elm.nodeType && elm.nodeType != 1) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var elms = elm.nodeType ? [elm] : elm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Is non element
+ if (elm.nodeType && elm.nodeType != 1) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /*eslint new-cap:0 */
- return Sizzle(selector, elms[0].ownerDocument || elms[0], null, elms).length > 0;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var elms = elm.nodeType ? [elm] : elm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // #endif
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /*eslint new-cap:0 */
+ return Sizzle(selector, elms[0].ownerDocument || elms[0], null, elms).length > 0;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds the specified element to another element or elements.
- *
- * @method add
- * @param {String/Element/Array} parentElm Element id string, DOM node element or array of ids or elements to add to.
- * @param {String/Element} name Name of new element to add or existing element to add.
- * @param {Object} attrs Optional object collection with arguments to add to the new element(s).
- * @param {String} html Optional inner HTML contents to add for each element.
- * @param {Boolean} create Optional flag if the element should be created or added.
- * @return {Element/Array} Element that got created, or an array of created elements if multiple input elements
- * were passed in.
- * @example
- * // Adds a new paragraph to the end of the active editor
- * tinymce.activeEditor.dom.add(tinymce.activeEditor.getBody(), 'p', {title: 'my title'}, 'Some content');
- */
- add: function(parentElm, name, attrs, html, create) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // #endif
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this.run(parentElm, function(parentElm) {
- var newElm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds the specified element to another element or elements.
+ *
+ * @method add
+ * @param {String/Element/Array} parentElm Element id string, DOM node element or array of ids or elements to add to.
+ * @param {String/Element} name Name of new element to add or existing element to add.
+ * @param {Object} attrs Optional object collection with arguments to add to the new element(s).
+ * @param {String} html Optional inner HTML contents to add for each element.
+ * @param {Boolean} create Optional flag if the element should be created or added.
+ * @return {Element/Array} Element that got created, or an array of created elements if multiple input elements
+ * were passed in.
+ * @example
+ * // Adds a new paragraph to the end of the active editor
+ * tinymce.activeEditor.dom.add(tinymce.activeEditor.getBody(), 'p', {title: 'my title'}, 'Some content');
+ */
+ add: function (parentElm, name, attrs, html, create) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- newElm = is(name, 'string') ? self.doc.createElement(name) : name;
- self.setAttribs(newElm, attrs);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this.run(parentElm, function (parentElm) {
+ var newElm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (html) {
- if (html.nodeType) {
- newElm.appendChild(html);
- } else {
- self.setHTML(newElm, html);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ newElm = is(name, 'string') ? self.doc.createElement(name) : name;
+ self.setAttribs(newElm, attrs);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return !create ? parentElm.appendChild(newElm) : newElm;
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (html) {
+ if (html.nodeType) {
+ newElm.appendChild(html);
+ } else {
+ self.setHTML(newElm, html);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates a new element.
- *
- * @method create
- * @param {String} name Name of new element.
- * @param {Object} attrs Optional object name/value collection with element attributes.
- * @param {String} html Optional HTML string to set as inner HTML of the element.
- * @return {Element} HTML DOM node element that got created.
- * @example
- * // Adds an element where the caret/selection is in the active editor
- * var el = tinymce.activeEditor.dom.create('div', {id: 'test', 'class': 'myclass'}, 'some content');
- * tinymce.activeEditor.selection.setNode(el);
- */
- create: function(name, attrs, html) {
- return this.add(this.doc.createElement(name), name, attrs, html, 1);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return !create ? parentElm.appendChild(newElm) : newElm;
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates HTML string for element. The element will be closed unless an empty inner HTML string is passed in.
- *
- * @method createHTML
- * @param {String} name Name of new element.
- * @param {Object} attrs Optional object name/value collection with element attributes.
- * @param {String} html Optional HTML string to set as inner HTML of the element.
- * @return {String} String with new HTML element, for example: <a href="#">test</a>.
- * @example
- * // Creates a html chunk and inserts it at the current selection/caret location
- * tinymce.activeEditor.selection.setContent(tinymce.activeEditor.dom.createHTML('a', {href: 'test.html'}, 'some line'));
- */
- createHTML: function(name, attrs, html) {
- var outHtml = '', key;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates a new element.
+ *
+ * @method create
+ * @param {String} name Name of new element.
+ * @param {Object} attrs Optional object name/value collection with element attributes.
+ * @param {String} html Optional HTML string to set as inner HTML of the element.
+ * @return {Element} HTML DOM node element that got created.
+ * @example
+ * // Adds an element where the caret/selection is in the active editor
+ * var el = tinymce.activeEditor.dom.create('div', {id: 'test', 'class': 'myclass'}, 'some content');
+ * tinymce.activeEditor.selection.setNode(el);
+ */
+ create: function (name, attrs, html) {
+ return this.add(this.doc.createElement(name), name, attrs, html, 1);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- outHtml += '<' + name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates HTML string for element. The element will be closed unless an empty inner HTML string is passed in.
+ *
+ * @method createHTML
+ * @param {String} name Name of new element.
+ * @param {Object} attrs Optional object name/value collection with element attributes.
+ * @param {String} html Optional HTML string to set as inner HTML of the element.
+ * @return {String} String with new HTML element, for example: <a href="#">test</a>.
+ * @example
+ * // Creates a html chunk and inserts it at the current selection/caret location
+ * tinymce.activeEditor.selection.setContent(tinymce.activeEditor.dom.createHTML('a', {href: 'test.html'}, 'some line'));
+ */
+ createHTML: function (name, attrs, html) {
+ var outHtml = '', key;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (key in attrs) {
- if (attrs.hasOwnProperty(key) && attrs[key] !== null && typeof attrs[key] != 'undefined') {
- outHtml += ' ' + key + '="' + this.encode(attrs[key]) + '"';
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ outHtml += '<' + name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // A call to tinymce.is doesn't work for some odd reason on IE9 possible bug inside their JS runtime
- if (typeof html != "undefined") {
- return outHtml + '>' + html + '</' + name + '>';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (key in attrs) {
+ if (attrs.hasOwnProperty(key) && attrs[key] !== null && typeof attrs[key] != 'undefined') {
+ outHtml += ' ' + key + '="' + this.encode(attrs[key]) + '"';
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return outHtml + ' />';
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // A call to tinymce.is doesn't work for some odd reason on IE9 possible bug inside their JS runtime
+ if (typeof html != "undefined") {
+ return outHtml + '>' + html + '</' + name + '>';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates a document fragment out of the specified HTML string.
- *
- * @method createFragment
- * @param {String} html Html string to create fragment from.
- * @return {DocumentFragment} Document fragment node.
- */
- createFragment: function(html) {
- var frag, node, doc = this.doc, container;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return outHtml + ' />';
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = doc.createElement("div");
- frag = doc.createDocumentFragment();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates a document fragment out of the specified HTML string.
+ *
+ * @method createFragment
+ * @param {String} html Html string to create fragment from.
+ * @return {DocumentFragment} Document fragment node.
+ */
+ createFragment: function (html) {
+ var frag, node, doc = this.doc, container;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (html) {
- container.innerHTML = html;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = doc.createElement("div");
+ frag = doc.createDocumentFragment();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while ((node = container.firstChild)) {
- frag.appendChild(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (html) {
+ container.innerHTML = html;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return frag;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while ((node = container.firstChild)) {
+ frag.appendChild(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes/deletes the specified element(s) from the DOM.
- *
- * @method remove
- * @param {String/Element/Array} node ID of element or DOM element object or array containing multiple elements/ids.
- * @param {Boolean} keepChildren Optional state to keep children or not. If set to true all children will be
- * placed at the location of the removed element.
- * @return {Element/Array} HTML DOM element that got removed, or an array of removed elements if multiple input elements
- * were passed in.
- * @example
- * // Removes all paragraphs in the active editor
- * tinymce.activeEditor.dom.remove(tinymce.activeEditor.dom.select('p'));
- *
- * // Removes an element by id in the document
- * tinymce.DOM.remove('mydiv');
- */
- remove: function(node, keepChildren) {
- node = this.$$(node);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return frag;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (keepChildren) {
- node.each(function() {
- var child;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes/deletes the specified element(s) from the DOM.
+ *
+ * @method remove
+ * @param {String/Element/Array} node ID of element or DOM element object or array containing multiple elements/ids.
+ * @param {Boolean} keepChildren Optional state to keep children or not. If set to true all children will be
+ * placed at the location of the removed element.
+ * @return {Element/Array} HTML DOM element that got removed, or an array of removed elements if multiple input elements
+ * were passed in.
+ * @example
+ * // Removes all paragraphs in the active editor
+ * tinymce.activeEditor.dom.remove(tinymce.activeEditor.dom.select('p'));
+ *
+ * // Removes an element by id in the document
+ * tinymce.DOM.remove('mydiv');
+ */
+ remove: function (node, keepChildren) {
+ node = this.$$(node);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while ((child = this.firstChild)) {
- if (child.nodeType == 3 && child.data.length === 0) {
- this.removeChild(child);
- } else {
- this.parentNode.insertBefore(child, this);
- }
- }
- }).remove();
- } else {
- node.remove();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (keepChildren) {
+ node.each(function () {
+ var child;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return node.length > 1 ? node.toArray() : node[0];
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while ((child = this.firstChild)) {
+ if (child.nodeType == 3 && child.data.length === 0) {
+ this.removeChild(child);
+ } else {
+ this.parentNode.insertBefore(child, this);
+ }
+ }
+ }).remove();
+ } else {
+ node.remove();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets the CSS style value on a HTML element. The name can be a camelcase string
- * or the CSS style name like background-color.
- *
- * @method setStyle
- * @param {String/Element/Array} elm HTML element/Array of elements to set CSS style value on.
- * @param {String} name Name of the style value to set.
- * @param {String} value Value to set on the style.
- * @example
- * // Sets a style value on all paragraphs in the currently active editor
- * tinymce.activeEditor.dom.setStyle(tinymce.activeEditor.dom.select('p'), 'background-color', 'red');
- *
- * // Sets a style value to an element by id in the current document
- * tinymce.DOM.setStyle('mydiv', 'background-color', 'red');
- */
- setStyle: function(elm, name, value) {
- elm = this.$$(elm).css(name, value);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return node.length > 1 ? node.toArray() : node[0];
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.settings.update_styles) {
- updateInternalStyleAttr(this, elm);
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets the CSS style value on a HTML element. The name can be a camelcase string
+ * or the CSS style name like background-color.
+ *
+ * @method setStyle
+ * @param {String/Element/Array} elm HTML element/Array of elements to set CSS style value on.
+ * @param {String} name Name of the style value to set.
+ * @param {String} value Value to set on the style.
+ * @example
+ * // Sets a style value on all paragraphs in the currently active editor
+ * tinymce.activeEditor.dom.setStyle(tinymce.activeEditor.dom.select('p'), 'background-color', 'red');
+ *
+ * // Sets a style value to an element by id in the current document
+ * tinymce.DOM.setStyle('mydiv', 'background-color', 'red');
+ */
+ setStyle: function (elm, name, value) {
+ elm = this.$$(elm).css(name, value);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the current style or runtime/computed value of an element.
- *
- * @method getStyle
- * @param {String/Element} elm HTML element or element id string to get style from.
- * @param {String} name Style name to return.
- * @param {Boolean} computed Computed style.
- * @return {String} Current style or computed style value of an element.
- */
- getStyle: function(elm, name, computed) {
- elm = this.$$(elm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.settings.update_styles) {
+ updateInternalStyleAttr(this, elm);
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (computed) {
- return elm.css(name);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the current style or runtime/computed value of an element.
+ *
+ * @method getStyle
+ * @param {String/Element} elm HTML element or element id string to get style from.
+ * @param {String} name Style name to return.
+ * @param {Boolean} computed Computed style.
+ * @return {String} Current style or computed style value of an element.
+ */
+ getStyle: function (elm, name, computed) {
+ elm = this.$$(elm);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Camelcase it, if needed
- name = name.replace(/-(\D)/g, function(a, b) {
- return b.toUpperCase();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (computed) {
+ return elm.css(name);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name == 'float') {
- name = Env.ie && Env.ie < 12 ? 'styleFloat' : 'cssFloat';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Camelcase it, if needed
+ name = name.replace(/-(\D)/g, function (a, b) {
+ return b.toUpperCase();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return elm[0] && elm[0].style ? elm[0].style[name] : undefined;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name == 'float') {
+ name = Env.ie && Env.ie < 12 ? 'styleFloat' : 'cssFloat';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets multiple styles on the specified element(s).
- *
- * @method setStyles
- * @param {Element/String/Array} elm DOM element, element id string or array of elements/ids to set styles on.
- * @param {Object} styles Name/Value collection of style items to add to the element(s).
- * @example
- * // Sets styles on all paragraphs in the currently active editor
- * tinymce.activeEditor.dom.setStyles(tinymce.activeEditor.dom.select('p'), {'background-color': 'red', 'color': 'green'});
- *
- * // Sets styles to an element by id in the current document
- * tinymce.DOM.setStyles('mydiv', {'background-color': 'red', 'color': 'green'});
- */
- setStyles: function(elm, styles) {
- elm = this.$$(elm).css(styles);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return elm[0] && elm[0].style ? elm[0].style[name] : undefined;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.settings.update_styles) {
- updateInternalStyleAttr(this, elm);
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets multiple styles on the specified element(s).
+ *
+ * @method setStyles
+ * @param {Element/String/Array} elm DOM element, element id string or array of elements/ids to set styles on.
+ * @param {Object} styles Name/Value collection of style items to add to the element(s).
+ * @example
+ * // Sets styles on all paragraphs in the currently active editor
+ * tinymce.activeEditor.dom.setStyles(tinymce.activeEditor.dom.select('p'), {'background-color': 'red', 'color': 'green'});
+ *
+ * // Sets styles to an element by id in the current document
+ * tinymce.DOM.setStyles('mydiv', {'background-color': 'red', 'color': 'green'});
+ */
+ setStyles: function (elm, styles) {
+ elm = this.$$(elm).css(styles);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes all attributes from an element or elements.
- *
- * @method removeAllAttribs
- * @param {Element/String/Array} e DOM element, element id string or array of elements/ids to remove attributes from.
- */
- removeAllAttribs: function(e) {
- return this.run(e, function(e) {
- var i, attrs = e.attributes;
- for (i = attrs.length - 1; i >= 0; i--) {
- e.removeAttributeNode(attrs.item(i));
- }
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.settings.update_styles) {
+ updateInternalStyleAttr(this, elm);
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets the specified attribute of an element or elements.
- *
- * @method setAttrib
- * @param {Element/String/Array} elm DOM element, element id string or array of elements/ids to set attribute on.
- * @param {String} name Name of attribute to set.
- * @param {String} value Value to set on the attribute - if this value is falsy like null, 0 or '' it will remove
- * the attribute instead.
- * @example
- * // Sets class attribute on all paragraphs in the active editor
- * tinymce.activeEditor.dom.setAttrib(tinymce.activeEditor.dom.select('p'), 'class', 'myclass');
- *
- * // Sets class attribute on a specific element in the current page
- * tinymce.dom.setAttrib('mydiv', 'class', 'myclass');
- */
- setAttrib: function(elm, name, value) {
- var self = this, originalValue, hook, settings = self.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes all attributes from an element or elements.
+ *
+ * @method removeAllAttribs
+ * @param {Element/String/Array} e DOM element, element id string or array of elements/ids to remove attributes from.
+ */
+ removeAllAttribs: function (e) {
+ return this.run(e, function (e) {
+ var i, attrs = e.attributes;
+ for (i = attrs.length - 1; i >= 0; i--) {
+ e.removeAttributeNode(attrs.item(i));
+ }
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value === '') {
- value = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets the specified attribute of an element or elements.
+ *
+ * @method setAttrib
+ * @param {Element/String/Array} elm DOM element, element id string or array of elements/ids to set attribute on.
+ * @param {String} name Name of attribute to set.
+ * @param {String} value Value to set on the attribute - if this value is falsy like null, 0 or '' it will remove
+ * the attribute instead.
+ * @example
+ * // Sets class attribute on all paragraphs in the active editor
+ * tinymce.activeEditor.dom.setAttrib(tinymce.activeEditor.dom.select('p'), 'class', 'myclass');
+ *
+ * // Sets class attribute on a specific element in the current page
+ * tinymce.dom.setAttrib('mydiv', 'class', 'myclass');
+ */
+ setAttrib: function (elm, name, value) {
+ var self = this, originalValue, hook, settings = self.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elm = self.$$(elm);
- originalValue = elm.attr(name);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value === '') {
+ value = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!elm.length) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elm = self.$$(elm);
+ originalValue = elm.attr(name);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- hook = self.attrHooks[name];
- if (hook && hook.set) {
- hook.set(elm, value, name);
- } else {
- elm.attr(name, value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!elm.length) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (originalValue != value && settings.onSetAttrib) {
- settings.onSetAttrib({
- attrElm: elm,
- attrName: name,
- attrValue: value
- });
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ hook = self.attrHooks[name];
+ if (hook && hook.set) {
+ hook.set(elm, value, name);
+ } else {
+ elm.attr(name, value);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets two or more specified attributes of an element or elements.
- *
- * @method setAttribs
- * @param {Element/String/Array} elm DOM element, element id string or array of elements/ids to set attributes on.
- * @param {Object} attrs Name/Value collection of attribute items to add to the element(s).
- * @example
- * // Sets class and title attributes on all paragraphs in the active editor
- * tinymce.activeEditor.dom.setAttribs(tinymce.activeEditor.dom.select('p'), {'class': 'myclass', title: 'some title'});
- *
- * // Sets class and title attributes on a specific element in the current page
- * tinymce.DOM.setAttribs('mydiv', {'class': 'myclass', title: 'some title'});
- */
- setAttribs: function(elm, attrs) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (originalValue != value && settings.onSetAttrib) {
+ settings.onSetAttrib({
+ attrElm: elm,
+ attrName: name,
+ attrValue: value
+ });
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.$$(elm).each(function(i, node) {
- each(attrs, function(value, name) {
- self.setAttrib(node, name, value);
- });
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets two or more specified attributes of an element or elements.
+ *
+ * @method setAttribs
+ * @param {Element/String/Array} elm DOM element, element id string or array of elements/ids to set attributes on.
+ * @param {Object} attrs Name/Value collection of attribute items to add to the element(s).
+ * @example
+ * // Sets class and title attributes on all paragraphs in the active editor
+ * tinymce.activeEditor.dom.setAttribs(tinymce.activeEditor.dom.select('p'), {'class': 'myclass', title: 'some title'});
+ *
+ * // Sets class and title attributes on a specific element in the current page
+ * tinymce.DOM.setAttribs('mydiv', {'class': 'myclass', title: 'some title'});
+ */
+ setAttribs: function (elm, attrs) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the specified attribute by name.
- *
- * @method getAttrib
- * @param {String/Element} elm Element string id or DOM element to get attribute from.
- * @param {String} name Name of attribute to get.
- * @param {String} defaultVal Optional default value to return if the attribute didn't exist.
- * @return {String} Attribute value string, default value or null if the attribute wasn't found.
- */
- getAttrib: function(elm, name, defaultVal) {
- var self = this, hook, value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.$$(elm).each(function (i, node) {
+ each(attrs, function (value, name) {
+ self.setAttrib(node, name, value);
+ });
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elm = self.$$(elm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the specified attribute by name.
+ *
+ * @method getAttrib
+ * @param {String/Element} elm Element string id or DOM element to get attribute from.
+ * @param {String} name Name of attribute to get.
+ * @param {String} defaultVal Optional default value to return if the attribute didn't exist.
+ * @return {String} Attribute value string, default value or null if the attribute wasn't found.
+ */
+ getAttrib: function (elm, name, defaultVal) {
+ var self = this, hook, value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elm.length) {
- hook = self.attrHooks[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elm = self.$$(elm);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (hook && hook.get) {
- value = hook.get(elm, name);
- } else {
- value = elm.attr(name);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (elm.length) {
+ hook = self.attrHooks[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof value == 'undefined') {
- value = defaultVal || '';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (hook && hook.get) {
+ value = hook.get(elm, name);
+ } else {
+ value = elm.attr(name);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return value;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof value == 'undefined') {
+ value = defaultVal || '';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the absolute x, y position of a node. The position will be returned in an object with x, y fields.
- *
- * @method getPos
- * @param {Element/String} elm HTML element or element id to get x, y position from.
- * @param {Element} rootElm Optional root element to stop calculations at.
- * @return {object} Absolute position of the specified element object with x, y fields.
- */
- getPos: function(elm, rootElm) {
- var self = this, x = 0, y = 0, offsetParent, doc = self.doc, body = doc.body, pos;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return value;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elm = self.get(elm);
- rootElm = rootElm || body;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the absolute x, y position of a node. The position will be returned in an object with x, y fields.
+ *
+ * @method getPos
+ * @param {Element/String} elm HTML element or element id to get x, y position from.
+ * @param {Element} rootElm Optional root element to stop calculations at.
+ * @return {object} Absolute position of the specified element object with x, y fields.
+ */
+ getPos: function (elm, rootElm) {
+ var self = this, x = 0, y = 0, offsetParent, doc = self.doc, body = doc.body, pos;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elm) {
- // Use getBoundingClientRect if it exists since it's faster than looping offset nodes
- // Fallback to offsetParent calculations if the body isn't static better since it stops at the body root
- if (rootElm === body && elm.getBoundingClientRect && $(body).css('position') === 'static') {
- pos = elm.getBoundingClientRect();
- rootElm = self.boxModel ? doc.documentElement : body;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elm = self.get(elm);
+ rootElm = rootElm || body;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add scroll offsets from documentElement or body since IE with the wrong box model will use d.body and so do WebKit
- // Also remove the body/documentelement clientTop/clientLeft on IE 6, 7 since they offset the position
- x = pos.left + (doc.documentElement.scrollLeft || body.scrollLeft) - rootElm.clientLeft;
- y = pos.top + (doc.documentElement.scrollTop || body.scrollTop) - rootElm.clientTop;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (elm) {
+ // Use getBoundingClientRect if it exists since it's faster than looping offset nodes
+ // Fallback to offsetParent calculations if the body isn't static better since it stops at the body root
+ if (rootElm === body && elm.getBoundingClientRect && DomQuery(body).css('position') === 'static') {
+ pos = elm.getBoundingClientRect();
+ rootElm = self.boxModel ? doc.documentElement : body;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {x: x, y: y};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add scroll offsets from documentElement or body since IE with the wrong box model will use d.body and so do WebKit
+ // Also remove the body/documentelement clientTop/clientLeft on IE 6, 7 since they offset the position
+ x = pos.left + (doc.documentElement.scrollLeft || body.scrollLeft) - rootElm.clientLeft;
+ y = pos.top + (doc.documentElement.scrollTop || body.scrollTop) - rootElm.clientTop;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- offsetParent = elm;
- while (offsetParent && offsetParent != rootElm && offsetParent.nodeType) {
- x += offsetParent.offsetLeft || 0;
- y += offsetParent.offsetTop || 0;
- offsetParent = offsetParent.offsetParent;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return { x: x, y: y };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- offsetParent = elm.parentNode;
- while (offsetParent && offsetParent != rootElm && offsetParent.nodeType) {
- x -= offsetParent.scrollLeft || 0;
- y -= offsetParent.scrollTop || 0;
- offsetParent = offsetParent.parentNode;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ offsetParent = elm;
+ while (offsetParent && offsetParent != rootElm && offsetParent.nodeType) {
+ x += offsetParent.offsetLeft || 0;
+ y += offsetParent.offsetTop || 0;
+ offsetParent = offsetParent.offsetParent;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {x: x, y: y};
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ offsetParent = elm.parentNode;
+ while (offsetParent && offsetParent != rootElm && offsetParent.nodeType) {
+ x -= offsetParent.scrollLeft || 0;
+ y -= offsetParent.scrollTop || 0;
+ offsetParent = offsetParent.parentNode;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Parses the specified style value into an object collection. This parser will also
- * merge and remove any redundant items that browsers might have added. It will also convert non-hex
- * colors to hex values. Urls inside the styles will also be converted to absolute/relative based on settings.
- *
- * @method parseStyle
- * @param {String} cssText Style value to parse, for example: border:1px solid red;.
- * @return {Object} Object representation of that style, for example: {border: '1px solid red'}
- */
- parseStyle: function(cssText) {
- return this.styles.parse(cssText);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return { x: x, y: y };
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Serializes the specified style object into a string.
- *
- * @method serializeStyle
- * @param {Object} styles Object to serialize as string, for example: {border: '1px solid red'}
- * @param {String} name Optional element name.
- * @return {String} String representation of the style object, for example: border: 1px solid red.
- */
- serializeStyle: function(styles, name) {
- return this.styles.serialize(styles, name);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Parses the specified style value into an object collection. This parser will also
+ * merge and remove any redundant items that browsers might have added. It will also convert non-hex
+ * colors to hex values. Urls inside the styles will also be converted to absolute/relative based on settings.
+ *
+ * @method parseStyle
+ * @param {String} cssText Style value to parse, for example: border:1px solid red;.
+ * @return {Object} Object representation of that style, for example: {border: '1px solid red'}
+ */
+ parseStyle: function (cssText) {
+ return this.styles.parse(cssText);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds a style element at the top of the document with the specified cssText content.
- *
- * @method addStyle
- * @param {String} cssText CSS Text style to add to top of head of document.
- */
- addStyle: function(cssText) {
- var self = this, doc = self.doc, head, styleElm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Serializes the specified style object into a string.
+ *
+ * @method serializeStyle
+ * @param {Object} styles Object to serialize as string, for example: {border: '1px solid red'}
+ * @param {String} name Optional element name.
+ * @return {String} String representation of the style object, for example: border: 1px solid red.
+ */
+ serializeStyle: function (styles, name) {
+ return this.styles.serialize(styles, name);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Prevent inline from loading the same styles twice
- if (self !== DOMUtils.DOM && doc === document) {
- var addedStyles = DOMUtils.DOM.addedStyles;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds a style element at the top of the document with the specified cssText content.
+ *
+ * @method addStyle
+ * @param {String} cssText CSS Text style to add to top of head of document.
+ */
+ addStyle: function (cssText) {
+ var self = this, doc = self.doc, head, styleElm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- addedStyles = addedStyles || [];
- if (addedStyles[cssText]) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Prevent inline from loading the same styles twice
+ if (self !== DOMUtils.DOM && doc === document) {
+ var addedStyles = DOMUtils.DOM.addedStyles;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- addedStyles[cssText] = true;
- DOMUtils.DOM.addedStyles = addedStyles;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ addedStyles = addedStyles || [];
+ if (addedStyles[cssText]) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Create style element if needed
- styleElm = doc.getElementById('mceDefaultStyles');
- if (!styleElm) {
- styleElm = doc.createElement('style');
- styleElm.id = 'mceDefaultStyles';
- styleElm.type = 'text/css';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ addedStyles[cssText] = true;
+ DOMUtils.DOM.addedStyles = addedStyles;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- head = doc.getElementsByTagName('head')[0];
- if (head.firstChild) {
- head.insertBefore(styleElm, head.firstChild);
- } else {
- head.appendChild(styleElm);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Create style element if needed
+ styleElm = doc.getElementById('mceDefaultStyles');
+ if (!styleElm) {
+ styleElm = doc.createElement('style');
+ styleElm.id = 'mceDefaultStyles';
+ styleElm.type = 'text/css';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Append style data to old or new style element
- if (styleElm.styleSheet) {
- styleElm.styleSheet.cssText += cssText;
- } else {
- styleElm.appendChild(doc.createTextNode(cssText));
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ head = doc.getElementsByTagName('head')[0];
+ if (head.firstChild) {
+ head.insertBefore(styleElm, head.firstChild);
+ } else {
+ head.appendChild(styleElm);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Imports/loads the specified CSS file into the document bound to the class.
- *
- * @method loadCSS
- * @param {String} url URL to CSS file to load.
- * @example
- * // Loads a CSS file dynamically into the current document
- * tinymce.DOM.loadCSS('somepath/some.css');
- *
- * // Loads a CSS file into the currently active editor instance
- * tinymce.activeEditor.dom.loadCSS('somepath/some.css');
- *
- * // Loads a CSS file into an editor instance by id
- * tinymce.get('someid').dom.loadCSS('somepath/some.css');
- *
- * // Loads multiple CSS files into the current document
- * tinymce.DOM.loadCSS('somepath/some.css,somepath/someother.css');
- */
- loadCSS: function(url) {
- var self = this, doc = self.doc, head;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Append style data to old or new style element
+ if (styleElm.styleSheet) {
+ styleElm.styleSheet.cssText += cssText;
+ } else {
+ styleElm.appendChild(doc.createTextNode(cssText));
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Prevent inline from loading the same CSS file twice
- if (self !== DOMUtils.DOM && doc === document) {
- DOMUtils.DOM.loadCSS(url);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Imports/loads the specified CSS file into the document bound to the class.
+ *
+ * @method loadCSS
+ * @param {String} url URL to CSS file to load.
+ * @example
+ * // Loads a CSS file dynamically into the current document
+ * tinymce.DOM.loadCSS('somepath/some.css');
+ *
+ * // Loads a CSS file into the currently active editor instance
+ * tinymce.activeEditor.dom.loadCSS('somepath/some.css');
+ *
+ * // Loads a CSS file into an editor instance by id
+ * tinymce.get('someid').dom.loadCSS('somepath/some.css');
+ *
+ * // Loads multiple CSS files into the current document
+ * tinymce.DOM.loadCSS('somepath/some.css,somepath/someother.css');
+ */
+ loadCSS: function (url) {
+ var self = this, doc = self.doc, head;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!url) {
- url = '';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Prevent inline from loading the same CSS file twice
+ if (self !== DOMUtils.DOM && doc === document) {
+ DOMUtils.DOM.loadCSS(url);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- head = doc.getElementsByTagName('head')[0];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!url) {
+ url = '';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(url.split(','), function(url) {
- var link;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ head = doc.getElementsByTagName('head')[0];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- url = Tools._addCacheSuffix(url);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(url.split(','), function (url) {
+ var link;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.files[url]) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ url = Tools._addCacheSuffix(url);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.files[url] = true;
- link = self.create('link', {rel: 'stylesheet', href: url});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.files[url]) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // IE 8 has a bug where dynamically loading stylesheets would produce a 1 item remaining bug
- // This fix seems to resolve that issue by recalcing the document once a stylesheet finishes loading
- // It's ugly but it seems to work fine.
- if (isIE && doc.documentMode && doc.recalc) {
- link.onload = function() {
- if (doc.recalc) {
- doc.recalc();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.files[url] = true;
+ link = self.create('link', { rel: 'stylesheet', href: url });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- link.onload = null;
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // IE 8 has a bug where dynamically loading stylesheets would produce a 1 item remaining bug
+ // This fix seems to resolve that issue by recalcing the document once a stylesheet finishes loading
+ // It's ugly but it seems to work fine.
+ if (isIE && doc.documentMode && doc.recalc) {
+ link.onload = function () {
+ if (doc.recalc) {
+ doc.recalc();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- head.appendChild(link);
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ link.onload = null;
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds a class to the specified element or elements.
- *
- * @method addClass
- * @param {String/Element/Array} elm Element ID string or DOM element or array with elements or IDs.
- * @param {String} cls Class name to add to each element.
- * @return {String/Array} String with new class value or array with new class values for all elements.
- * @example
- * // Adds a class to all paragraphs in the active editor
- * tinymce.activeEditor.dom.addClass(tinymce.activeEditor.dom.select('p'), 'myclass');
- *
- * // Adds a class to a specific element in the current page
- * tinymce.DOM.addClass('mydiv', 'myclass');
- */
- addClass: function(elm, cls) {
- this.$$(elm).addClass(cls);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ head.appendChild(link);
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes a class from the specified element or elements.
- *
- * @method removeClass
- * @param {String/Element/Array} elm Element ID string or DOM element or array with elements or IDs.
- * @param {String} cls Class name to remove from each element.
- * @return {String/Array} String of remaining class name(s), or an array of strings if multiple input elements
- * were passed in.
- * @example
- * // Removes a class from all paragraphs in the active editor
- * tinymce.activeEditor.dom.removeClass(tinymce.activeEditor.dom.select('p'), 'myclass');
- *
- * // Removes a class from a specific element in the current page
- * tinymce.DOM.removeClass('mydiv', 'myclass');
- */
- removeClass: function(elm, cls) {
- this.toggleClass(elm, cls, false);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds a class to the specified element or elements.
+ *
+ * @method addClass
+ * @param {String/Element/Array} elm Element ID string or DOM element or array with elements or IDs.
+ * @param {String} cls Class name to add to each element.
+ * @return {String/Array} String with new class value or array with new class values for all elements.
+ * @example
+ * // Adds a class to all paragraphs in the active editor
+ * tinymce.activeEditor.dom.addClass(tinymce.activeEditor.dom.select('p'), 'myclass');
+ *
+ * // Adds a class to a specific element in the current page
+ * tinymce.DOM.addClass('mydiv', 'myclass');
+ */
+ addClass: function (elm, cls) {
+ this.$$(elm).addClass(cls);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true if the specified element has the specified class.
- *
- * @method hasClass
- * @param {String/Element} elm HTML element or element id string to check CSS class on.
- * @param {String} cls CSS class to check for.
- * @return {Boolean} true/false if the specified element has the specified class.
- */
- hasClass: function(elm, cls) {
- return this.$$(elm).hasClass(cls);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes a class from the specified element or elements.
+ *
+ * @method removeClass
+ * @param {String/Element/Array} elm Element ID string or DOM element or array with elements or IDs.
+ * @param {String} cls Class name to remove from each element.
+ * @return {String/Array} String of remaining class name(s), or an array of strings if multiple input elements
+ * were passed in.
+ * @example
+ * // Removes a class from all paragraphs in the active editor
+ * tinymce.activeEditor.dom.removeClass(tinymce.activeEditor.dom.select('p'), 'myclass');
+ *
+ * // Removes a class from a specific element in the current page
+ * tinymce.DOM.removeClass('mydiv', 'myclass');
+ */
+ removeClass: function (elm, cls) {
+ this.toggleClass(elm, cls, false);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Toggles the specified class on/off.
- *
- * @method toggleClass
- * @param {Element} elm Element to toggle class on.
- * @param {[type]} cls Class to toggle on/off.
- * @param {[type]} state Optional state to set.
- */
- toggleClass: function(elm, cls, state) {
- this.$$(elm).toggleClass(cls, state).each(function() {
- if (this.className === '') {
- $(this).attr('class', null);
- }
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true if the specified element has the specified class.
+ *
+ * @method hasClass
+ * @param {String/Element} elm HTML element or element id string to check CSS class on.
+ * @param {String} cls CSS class to check for.
+ * @return {Boolean} true/false if the specified element has the specified class.
+ */
+ hasClass: function (elm, cls) {
+ return this.$$(elm).hasClass(cls);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Shows the specified element(s) by ID by setting the "display" style.
- *
- * @method show
- * @param {String/Element/Array} elm ID of DOM element or DOM element or array with elements or IDs to show.
- */
- show: function(elm) {
- this.$$(elm).show();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Toggles the specified class on/off.
+ *
+ * @method toggleClass
+ * @param {Element} elm Element to toggle class on.
+ * @param {[type]} cls Class to toggle on/off.
+ * @param {[type]} state Optional state to set.
+ */
+ toggleClass: function (elm, cls, state) {
+ this.$$(elm).toggleClass(cls, state).each(function () {
+ if (this.className === '') {
+ DomQuery(this).attr('class', null);
+ }
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Hides the specified element(s) by ID by setting the "display" style.
- *
- * @method hide
- * @param {String/Element/Array} elm ID of DOM element or DOM element or array with elements or IDs to hide.
- * @example
- * // Hides an element by id in the document
- * tinymce.DOM.hide('myid');
- */
- hide: function(elm) {
- this.$$(elm).hide();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Shows the specified element(s) by ID by setting the "display" style.
+ *
+ * @method show
+ * @param {String/Element/Array} elm ID of DOM element or DOM element or array with elements or IDs to show.
+ */
+ show: function (elm) {
+ this.$$(elm).show();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the element is hidden or not by checking the "display" style.
- *
- * @method isHidden
- * @param {String/Element} elm Id or element to check display state on.
- * @return {Boolean} true/false if the element is hidden or not.
- */
- isHidden: function(elm) {
- return this.$$(elm).css('display') == 'none';
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Hides the specified element(s) by ID by setting the "display" style.
+ *
+ * @method hide
+ * @param {String/Element/Array} elm ID of DOM element or DOM element or array with elements or IDs to hide.
+ * @example
+ * // Hides an element by id in the document
+ * tinymce.DOM.hide('myid');
+ */
+ hide: function (elm) {
+ this.$$(elm).hide();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a unique id. This can be useful when generating elements on the fly.
- * This method will not check if the element already exists.
- *
- * @method uniqueId
- * @param {String} prefix Optional prefix to add in front of all ids - defaults to "mce_".
- * @return {String} Unique id.
- */
- uniqueId: function(prefix) {
- return (!prefix ? 'mce_' : prefix) + (this.counter++);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the element is hidden or not by checking the "display" style.
+ *
+ * @method isHidden
+ * @param {String/Element} elm Id or element to check display state on.
+ * @return {Boolean} true/false if the element is hidden or not.
+ */
+ isHidden: function (elm) {
+ return this.$$(elm).css('display') == 'none';
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets the specified HTML content inside the element or elements. The HTML will first be processed. This means
- * URLs will get converted, hex color values fixed etc. Check processHTML for details.
- *
- * @method setHTML
- * @param {Element/String/Array} elm DOM element, element id string or array of elements/ids to set HTML inside of.
- * @param {String} html HTML content to set as inner HTML of the element.
- * @example
- * // Sets the inner HTML of all paragraphs in the active editor
- * tinymce.activeEditor.dom.setHTML(tinymce.activeEditor.dom.select('p'), 'some inner html');
- *
- * // Sets the inner HTML of an element by id in the document
- * tinymce.DOM.setHTML('mydiv', 'some inner html');
- */
- setHTML: function(elm, html) {
- elm = this.$$(elm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a unique id. This can be useful when generating elements on the fly.
+ * This method will not check if the element already exists.
+ *
+ * @method uniqueId
+ * @param {String} prefix Optional prefix to add in front of all ids - defaults to "mce_".
+ * @return {String} Unique id.
+ */
+ uniqueId: function (prefix) {
+ return (!prefix ? 'mce_' : prefix) + (this.counter++);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isIE) {
- elm.each(function(i, target) {
- if (target.canHaveHTML === false) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets the specified HTML content inside the element or elements. The HTML will first be processed. This means
+ * URLs will get converted, hex color values fixed etc. Check processHTML for details.
+ *
+ * @method setHTML
+ * @param {Element/String/Array} elm DOM element, element id string or array of elements/ids to set HTML inside of.
+ * @param {String} html HTML content to set as inner HTML of the element.
+ * @example
+ * // Sets the inner HTML of all paragraphs in the active editor
+ * tinymce.activeEditor.dom.setHTML(tinymce.activeEditor.dom.select('p'), 'some inner html');
+ *
+ * // Sets the inner HTML of an element by id in the document
+ * tinymce.DOM.setHTML('mydiv', 'some inner html');
+ */
+ setHTML: function (elm, html) {
+ elm = this.$$(elm);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove all child nodes, IE keeps empty text nodes in DOM
- while (target.firstChild) {
- target.removeChild(target.firstChild);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isIE) {
+ elm.each(function (i, target) {
+ if (target.canHaveHTML === false) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- try {
- // IE will remove comments from the beginning
- // unless you padd the contents with something
- target.innerHTML = '<br>' + html;
- target.removeChild(target.firstChild);
- } catch (ex) {
- // IE sometimes produces an unknown runtime error on innerHTML if it's a div inside a p
- $('<div></div>').html('<br>' + html).contents().slice(1).appendTo(target);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove all child nodes, IE keeps empty text nodes in DOM
+ while (target.firstChild) {
+ target.removeChild(target.firstChild);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return html;
- });
- } else {
- elm.html(html);
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ try {
+ // IE will remove comments from the beginning
+ // unless you padd the contents with something
+ target.innerHTML = '<br>' + html;
+ target.removeChild(target.firstChild);
+ } catch (ex) {
+ // IE sometimes produces an unknown runtime error on innerHTML if it's a div inside a p
+ DomQuery('<div></div>').html('<br>' + html).contents().slice(1).appendTo(target);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the outer HTML of an element.
- *
- * @method getOuterHTML
- * @param {String/Element} elm Element ID or element object to get outer HTML from.
- * @return {String} Outer HTML string.
- * @example
- * tinymce.DOM.getOuterHTML(editorElement);
- * tinymce.activeEditor.getOuterHTML(tinymce.activeEditor.getBody());
- */
- getOuterHTML: function(elm) {
- elm = this.get(elm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return html;
+ });
+ } else {
+ elm.html(html);
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Older FF doesn't have outerHTML 3.6 is still used by some orgaizations
- return elm.nodeType == 1 && "outerHTML" in elm ? elm.outerHTML : $('<div></div>').append($(elm).clone()).html();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the outer HTML of an element.
+ *
+ * @method getOuterHTML
+ * @param {String/Element} elm Element ID or element object to get outer HTML from.
+ * @return {String} Outer HTML string.
+ * @example
+ * tinymce.DOM.getOuterHTML(editorElement);
+ * tinymce.activeEditor.getOuterHTML(tinymce.activeEditor.getBody());
+ */
+ getOuterHTML: function (elm) {
+ elm = this.get(elm);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets the specified outer HTML on an element or elements.
- *
- * @method setOuterHTML
- * @param {Element/String/Array} elm DOM element, element id string or array of elements/ids to set outer HTML on.
- * @param {Object} html HTML code to set as outer value for the element.
- * @example
- * // Sets the outer HTML of all paragraphs in the active editor
- * tinymce.activeEditor.dom.setOuterHTML(tinymce.activeEditor.dom.select('p'), '<div>some html</div>');
- *
- * // Sets the outer HTML of an element by id in the document
- * tinymce.DOM.setOuterHTML('mydiv', '<div>some html</div>');
- */
- setOuterHTML: function(elm, html) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Older FF doesn't have outerHTML 3.6 is still used by some orgaizations
+ return elm.nodeType == 1 && "outerHTML" in elm ? elm.outerHTML : DomQuery('<div></div>').append(DomQuery(elm).clone()).html();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.$$(elm).each(function() {
- try {
- // Older FF doesn't have outerHTML 3.6 is still used by some organizations
- if ("outerHTML" in this) {
- this.outerHTML = html;
- return;
- }
- } catch (ex) {
- // Ignore
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets the specified outer HTML on an element or elements.
+ *
+ * @method setOuterHTML
+ * @param {Element/String/Array} elm DOM element, element id string or array of elements/ids to set outer HTML on.
+ * @param {Object} html HTML code to set as outer value for the element.
+ * @example
+ * // Sets the outer HTML of all paragraphs in the active editor
+ * tinymce.activeEditor.dom.setOuterHTML(tinymce.activeEditor.dom.select('p'), '<div>some html</div>');
+ *
+ * // Sets the outer HTML of an element by id in the document
+ * tinymce.DOM.setOuterHTML('mydiv', '<div>some html</div>');
+ */
+ setOuterHTML: function (elm, html) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // OuterHTML for IE it sometimes produces an "unknown runtime error"
- self.remove($(this).html(html), true);
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.$$(elm).each(function () {
+ try {
+ // Older FF doesn't have outerHTML 3.6 is still used by some organizations
+ if ("outerHTML" in this) {
+ this.outerHTML = html;
+ return;
+ }
+ } catch (ex) {
+ // Ignore
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Entity decodes a string. This method decodes any HTML entities, such as å.
- *
- * @method decode
- * @param {String} s String to decode entities on.
- * @return {String} Entity decoded string.
- */
- decode: Entities.decode,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // OuterHTML for IE it sometimes produces an "unknown runtime error"
+ self.remove(DomQuery(this).html(html), true);
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Entity encodes a string. This method encodes the most common entities, such as <>"&.
- *
- * @method encode
- * @param {String} text String to encode with entities.
- * @return {String} Entity encoded string.
- */
- encode: Entities.encodeAllRaw,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Entity decodes a string. This method decodes any HTML entities, such as å.
+ *
+ * @method decode
+ * @param {String} s String to decode entities on.
+ * @return {String} Entity decoded string.
+ */
+ decode: Entities.decode,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Inserts an element after the reference element.
- *
- * @method insertAfter
- * @param {Element} node Element to insert after the reference.
- * @param {Element/String/Array} referenceNode Reference element, element id or array of elements to insert after.
- * @return {Element/Array} Element that got added or an array with elements.
- */
- insertAfter: function(node, referenceNode) {
- referenceNode = this.get(referenceNode);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Entity encodes a string. This method encodes the most common entities, such as <>"&.
+ *
+ * @method encode
+ * @param {String} text String to encode with entities.
+ * @return {String} Entity encoded string.
+ */
+ encode: Entities.encodeAllRaw,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this.run(node, function(node) {
- var parent, nextSibling;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Inserts an element after the reference element.
+ *
+ * @method insertAfter
+ * @param {Element} node Element to insert after the reference.
+ * @param {Element/String/Array} referenceNode Reference element, element id or array of elements to insert after.
+ * @return {Element/Array} Element that got added or an array with elements.
+ */
+ insertAfter: function (node, referenceNode) {
+ referenceNode = this.get(referenceNode);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parent = referenceNode.parentNode;
- nextSibling = referenceNode.nextSibling;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this.run(node, function (node) {
+ var parent, nextSibling;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (nextSibling) {
- parent.insertBefore(node, nextSibling);
- } else {
- parent.appendChild(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parent = referenceNode.parentNode;
+ nextSibling = referenceNode.nextSibling;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return node;
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (nextSibling) {
+ parent.insertBefore(node, nextSibling);
+ } else {
+ parent.appendChild(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Replaces the specified element or elements with the new element specified. The new element will
- * be cloned if multiple input elements are passed in.
- *
- * @method replace
- * @param {Element} newElm New element to replace old ones with.
- * @param {Element/String/Array} oldElm Element DOM node, element id or array of elements or ids to replace.
- * @param {Boolean} keepChildren Optional keep children state, if set to true child nodes from the old object will be added
- * to new ones.
- */
- replace: function(newElm, oldElm, keepChildren) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return node;
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self.run(oldElm, function(oldElm) {
- if (is(oldElm, 'array')) {
- newElm = newElm.cloneNode(true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Replaces the specified element or elements with the new element specified. The new element will
+ * be cloned if multiple input elements are passed in.
+ *
+ * @method replace
+ * @param {Element} newElm New element to replace old ones with.
+ * @param {Element/String/Array} oldElm Element DOM node, element id or array of elements or ids to replace.
+ * @param {Boolean} keepChildren Optional keep children state, if set to true child nodes from the old object will be added
+ * to new ones.
+ */
+ replace: function (newElm, oldElm, keepChildren) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (keepChildren) {
- each(grep(oldElm.childNodes), function(node) {
- newElm.appendChild(node);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self.run(oldElm, function (oldElm) {
+ if (is(oldElm, 'array')) {
+ newElm = newElm.cloneNode(true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return oldElm.parentNode.replaceChild(newElm, oldElm);
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (keepChildren) {
+ each(grep(oldElm.childNodes), function (node) {
+ newElm.appendChild(node);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renames the specified element and keeps its attributes and children.
- *
- * @method rename
- * @param {Element} elm Element to rename.
- * @param {String} name Name of the new element.
- * @return {Element} New element or the old element if it needed renaming.
- */
- rename: function(elm, name) {
- var self = this, newElm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return oldElm.parentNode.replaceChild(newElm, oldElm);
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elm.nodeName != name.toUpperCase()) {
- // Rename block element
- newElm = self.create(name);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renames the specified element and keeps its attributes and children.
+ *
+ * @method rename
+ * @param {Element} elm Element to rename.
+ * @param {String} name Name of the new element.
+ * @return {Element} New element or the old element if it needed renaming.
+ */
+ rename: function (elm, name) {
+ var self = this, newElm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Copy attribs to new block
- each(self.getAttribs(elm), function(attrNode) {
- self.setAttrib(newElm, attrNode.nodeName, self.getAttrib(elm, attrNode.nodeName));
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (elm.nodeName != name.toUpperCase()) {
+ // Rename block element
+ newElm = self.create(name);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Replace block
- self.replace(newElm, elm, 1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Copy attribs to new block
+ each(self.getAttribs(elm), function (attrNode) {
+ self.setAttrib(newElm, attrNode.nodeName, self.getAttrib(elm, attrNode.nodeName));
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return newElm || elm;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Replace block
+ self.replace(newElm, elm, 1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Find the common ancestor of two elements. This is a shorter method than using the DOM Range logic.
- *
- * @method findCommonAncestor
- * @param {Element} a Element to find common ancestor of.
- * @param {Element} b Element to find common ancestor of.
- * @return {Element} Common ancestor element of the two input elements.
- */
- findCommonAncestor: function(a, b) {
- var ps = a, pe;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return newElm || elm;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (ps) {
- pe = b;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Find the common ancestor of two elements. This is a shorter method than using the DOM Range logic.
+ *
+ * @method findCommonAncestor
+ * @param {Element} a Element to find common ancestor of.
+ * @param {Element} b Element to find common ancestor of.
+ * @return {Element} Common ancestor element of the two input elements.
+ */
+ findCommonAncestor: function (a, b) {
+ var ps = a, pe;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (pe && ps != pe) {
- pe = pe.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (ps) {
+ pe = b;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (ps == pe) {
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (pe && ps != pe) {
+ pe = pe.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ps = ps.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (ps == pe) {
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!ps && a.ownerDocument) {
- return a.ownerDocument.documentElement;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ps = ps.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return ps;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!ps && a.ownerDocument) {
+ return a.ownerDocument.documentElement;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Parses the specified RGB color value and returns a hex version of that color.
- *
- * @method toHex
- * @param {String} rgbVal RGB string value like rgb(1,2,3)
- * @return {String} Hex version of that RGB value like #FF00FF.
- */
- toHex: function(rgbVal) {
- return this.styles.toHex(Tools.trim(rgbVal));
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return ps;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Executes the specified function on the element by id or dom element node or array of elements/id.
- *
- * @method run
- * @param {String/Element/Array} elm ID or DOM element object or array with ids or elements.
- * @param {function} func Function to execute for each item.
- * @param {Object} scope Optional scope to execute the function in.
- * @return {Object/Array} Single object, or an array of objects if multiple input elements were passed in.
- */
- run: function(elm, func, scope) {
- var self = this, result;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Parses the specified RGB color value and returns a hex version of that color.
+ *
+ * @method toHex
+ * @param {String} rgbVal RGB string value like rgb(1,2,3)
+ * @return {String} Hex version of that RGB value like #FF00FF.
+ */
+ toHex: function (rgbVal) {
+ return this.styles.toHex(Tools.trim(rgbVal));
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof elm === 'string') {
- elm = self.get(elm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Executes the specified function on the element by id or dom element node or array of elements/id.
+ *
+ * @method run
+ * @param {String/Element/Array} elm ID or DOM element object or array with ids or elements.
+ * @param {function} func Function to execute for each item.
+ * @param {Object} scope Optional scope to execute the function in.
+ * @return {Object/Array} Single object, or an array of objects if multiple input elements were passed in.
+ */
+ run: function (elm, func, scope) {
+ var self = this, result;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!elm) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof elm === 'string') {
+ elm = self.get(elm);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- scope = scope || this;
- if (!elm.nodeType && (elm.length || elm.length === 0)) {
- result = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!elm) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(elm, function(elm, i) {
- if (elm) {
- if (typeof elm == 'string') {
- elm = self.get(elm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ scope = scope || this;
+ if (!elm.nodeType && (elm.length || elm.length === 0)) {
+ result = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- result.push(func.call(scope, elm, i));
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(elm, function (elm, i) {
+ if (elm) {
+ if (typeof elm == 'string') {
+ elm = self.get(elm);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return result;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ result.push(func.call(scope, elm, i));
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return func.call(scope, elm);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return result;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a NodeList with attributes for the element.
- *
- * @method getAttribs
- * @param {HTMLElement/string} elm Element node or string id to get attributes from.
- * @return {NodeList} NodeList with attributes.
- */
- getAttribs: function(elm) {
- var attrs;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return func.call(scope, elm);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elm = this.get(elm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a NodeList with attributes for the element.
+ *
+ * @method getAttribs
+ * @param {HTMLElement/string} elm Element node or string id to get attributes from.
+ * @return {NodeList} NodeList with attributes.
+ */
+ getAttribs: function (elm) {
+ var attrs;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!elm) {
- return [];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elm = this.get(elm);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isIE) {
- attrs = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!elm) {
+ return [];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Object will throw exception in IE
- if (elm.nodeName == 'OBJECT') {
- return elm.attributes;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isIE) {
+ attrs = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // IE doesn't keep the selected attribute if you clone option elements
- if (elm.nodeName === 'OPTION' && this.getAttrib(elm, 'selected')) {
- attrs.push({specified: 1, nodeName: 'selected'});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Object will throw exception in IE
+ if (elm.nodeName == 'OBJECT') {
+ return elm.attributes;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // It's crazy that this is faster in IE but it's because it returns all attributes all the time
- var attrRegExp = /<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi;
- elm.cloneNode(false).outerHTML.replace(attrRegExp, '').replace(/[\w:\-]+/gi, function(a) {
- attrs.push({specified: 1, nodeName: a});
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // IE doesn't keep the selected attribute if you clone option elements
+ if (elm.nodeName === 'OPTION' && this.getAttrib(elm, 'selected')) {
+ attrs.push({ specified: 1, nodeName: 'selected' });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return attrs;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // It's crazy that this is faster in IE but it's because it returns all attributes all the time
+ var attrRegExp = /<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi;
+ elm.cloneNode(false).outerHTML.replace(attrRegExp, '').replace(/[\w:\-]+/gi, function (a) {
+ attrs.push({ specified: 1, nodeName: a });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return elm.attributes;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return attrs;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the specified node is to be considered empty or not.
- *
- * @example
- * tinymce.DOM.isEmpty(node, {img: true});
- * @method isEmpty
- * @param {Object} elements Optional name/value object with elements that are automatically treated as non-empty elements.
- * @return {Boolean} true/false if the node is empty or not.
- */
- isEmpty: function(node, elements) {
- var self = this, i, attributes, type, whitespace, walker, name, brCount = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return elm.attributes;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.firstChild;
- if (node) {
- walker = new TreeWalker(node, node.parentNode);
- elements = elements || (self.schema ? self.schema.getNonEmptyElements() : null);
- whitespace = self.schema ? self.schema.getWhiteSpaceElements() : {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the specified node is to be considered empty or not.
+ *
+ * @example
+ * tinymce.DOM.isEmpty(node, {img: true});
+ * @method isEmpty
+ * @param {Object} elements Optional name/value object with elements that are automatically treated as non-empty elements.
+ * @return {Boolean} true/false if the node is empty or not.
+ */
+ isEmpty: function (node, elements) {
+ var self = this, i, attributes, type, whitespace, walker, name, brCount = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- do {
- type = node.nodeType;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node.firstChild;
+ if (node) {
+ walker = new TreeWalker(node, node.parentNode);
+ elements = elements || (self.schema ? self.schema.getNonEmptyElements() : null);
+ whitespace = self.schema ? self.schema.getWhiteSpaceElements() : {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (type === 1) {
- // Ignore bogus elements
- var bogusVal = node.getAttribute('data-mce-bogus');
- if (bogusVal) {
- node = walker.next(bogusVal === 'all');
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ do {
+ type = node.nodeType;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Keep empty elements like <img />
- name = node.nodeName.toLowerCase();
- if (elements && elements[name]) {
- // Ignore single BR elements in blocks like <p><br /></p> or <p><span><br /></span></p>
- if (name === 'br') {
- brCount++;
- node = walker.next();
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (type === 1) {
+ // Ignore bogus elements
+ var bogusVal = node.getAttribute('data-mce-bogus');
+ if (bogusVal) {
+ node = walker.next(bogusVal === 'all');
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Keep empty elements like <img />
+ name = node.nodeName.toLowerCase();
+ if (elements && elements[name]) {
+ // Ignore single BR elements in blocks like <p><br /></p> or <p><span><br /></span></p>
+ if (name === 'br') {
+ brCount++;
+ node = walker.next();
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Keep elements with data-bookmark attributes or name attribute like <a name="1"></a>
- attributes = self.getAttribs(node);
- i = attributes.length;
- while (i--) {
- name = attributes[i].nodeName;
- if (name === "name" || name === 'data-mce-bookmark') {
- return false;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Keep comment nodes
- if (type == 8) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Keep elements with data-bookmark attributes or name attribute like <a name="1"></a>
+ attributes = self.getAttribs(node);
+ i = attributes.length;
+ while (i--) {
+ name = attributes[i].nodeName;
+ if (name === "name" || name === 'data-mce-bookmark') {
+ return false;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Keep non whitespace text nodes
- if (type === 3 && !whiteSpaceRegExp.test(node.nodeValue)) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Keep comment nodes
+ if (type == 8) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Keep whitespace preserve elements
- if (type === 3 && node.parentNode && whitespace[node.parentNode.nodeName] && whiteSpaceRegExp.test(node.nodeValue)) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Keep non whitespace text nodes
+ if (type === 3 && !whiteSpaceRegExp.test(node.nodeValue)) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = walker.next();
- } while (node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Keep whitespace preserve elements
+ if (type === 3 && node.parentNode && whitespace[node.parentNode.nodeName] && whiteSpaceRegExp.test(node.nodeValue)) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return brCount <= 1;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = walker.next();
+ } while (node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates a new DOM Range object. This will use the native DOM Range API if it's
- * available. If it's not, it will fall back to the custom TinyMCE implementation.
- *
- * @method createRng
- * @return {DOMRange} DOM Range object.
- * @example
- * var rng = tinymce.DOM.createRng();
- * alert(rng.startContainer + "," + rng.startOffset);
- */
- createRng: function() {
- var doc = this.doc;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return brCount <= 1;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return doc.createRange ? doc.createRange() : new Range(this);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates a new DOM Range object. This will use the native DOM Range API if it's
+ * available. If it's not, it will fall back to the custom TinyMCE implementation.
+ *
+ * @method createRng
+ * @return {DOMRange} DOM Range object.
+ * @example
+ * var rng = tinymce.DOM.createRng();
+ * alert(rng.startContainer + "," + rng.startOffset);
+ */
+ createRng: function () {
+ var doc = this.doc;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the index of the specified node within its parent.
- *
- * @method nodeIndex
- * @param {Node} node Node to look for.
- * @param {boolean} normalized Optional true/false state if the index is what it would be after a normalization.
- * @return {Number} Index of the specified node.
- */
- nodeIndex: nodeIndex,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return doc.createRange ? doc.createRange() : new Range(this);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Splits an element into two new elements and places the specified split
- * element or elements between the new ones. For example splitting the paragraph at the bold element in
- * this example <p>abc<b>abc</b>123</p> would produce <p>abc</p><b>abc</b><p>123</p>.
- *
- * @method split
- * @param {Element} parentElm Parent element to split.
- * @param {Element} splitElm Element to split at.
- * @param {Element} replacementElm Optional replacement element to replace the split element with.
- * @return {Element} Returns the split element or the replacement element if that is specified.
- */
- split: function(parentElm, splitElm, replacementElm) {
- var self = this, r = self.createRng(), bef, aft, pa;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the index of the specified node within its parent.
+ *
+ * @method nodeIndex
+ * @param {Node} node Node to look for.
+ * @param {boolean} normalized Optional true/false state if the index is what it would be after a normalization.
+ * @return {Number} Index of the specified node.
+ */
+ nodeIndex: nodeIndex,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // W3C valid browsers tend to leave empty nodes to the left/right side of the contents - this makes sense
- // but we don't want that in our code since it serves no purpose for the end user
- // For example splitting this html at the bold element:
- // <p>text 1<span><b>CHOP</b></span>text 2</p>
- // would produce:
- // <p>text 1<span></span></p><b>CHOP</b><p><span></span>text 2</p>
- // this function will then trim off empty edges and produce:
- // <p>text 1</p><b>CHOP</b><p>text 2</p>
- function trimNode(node) {
- var i, children = node.childNodes, type = node.nodeType;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Splits an element into two new elements and places the specified split
+ * element or elements between the new ones. For example splitting the paragraph at the bold element in
+ * this example <p>abc<b>abc</b>123</p> would produce <p>abc</p><b>abc</b><p>123</p>.
+ *
+ * @method split
+ * @param {Element} parentElm Parent element to split.
+ * @param {Element} splitElm Element to split at.
+ * @param {Element} replacementElm Optional replacement element to replace the split element with.
+ * @return {Element} Returns the split element or the replacement element if that is specified.
+ */
+ split: function (parentElm, splitElm, replacementElm) {
+ var self = this, r = self.createRng(), bef, aft, pa;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function surroundedBySpans(node) {
- var previousIsSpan = node.previousSibling && node.previousSibling.nodeName == 'SPAN';
- var nextIsSpan = node.nextSibling && node.nextSibling.nodeName == 'SPAN';
- return previousIsSpan && nextIsSpan;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // W3C valid browsers tend to leave empty nodes to the left/right side of the contents - this makes sense
+ // but we don't want that in our code since it serves no purpose for the end user
+ // For example splitting this html at the bold element:
+ // <p>text 1<span><b>CHOP</b></span>text 2</p>
+ // would produce:
+ // <p>text 1<span></span></p><b>CHOP</b><p><span></span>text 2</p>
+ // this function will then trim off empty edges and produce:
+ // <p>text 1</p><b>CHOP</b><p>text 2</p>
+ function trimNode(node) {
+ var i, children = node.childNodes, type = node.nodeType;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (type == 1 && node.getAttribute('data-mce-type') == 'bookmark') {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function surroundedBySpans(node) {
+ var previousIsSpan = node.previousSibling && node.previousSibling.nodeName == 'SPAN';
+ var nextIsSpan = node.nextSibling && node.nextSibling.nodeName == 'SPAN';
+ return previousIsSpan && nextIsSpan;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = children.length - 1; i >= 0; i--) {
- trimNode(children[i]);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (type == 1 && node.getAttribute('data-mce-type') == 'bookmark') {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (type != 9) {
- // Keep non whitespace text nodes
- if (type == 3 && node.nodeValue.length > 0) {
- // If parent element isn't a block or there isn't any useful contents for example "<p> </p>"
- // Also keep text nodes with only spaces if surrounded by spans.
- // eg. "<p><span>a</span> <span>b</span></p>" should keep space between a and b
- var trimmedLength = trim(node.nodeValue).length;
- if (!self.isBlock(node.parentNode) || trimmedLength > 0 || trimmedLength === 0 && surroundedBySpans(node)) {
- return;
- }
- } else if (type == 1) {
- // If the only child is a bookmark then move it up
- children = node.childNodes;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = children.length - 1; i >= 0; i--) {
+ trimNode(children[i]);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // TODO fix this complex if
- if (children.length == 1 && children[0] && children[0].nodeType == 1 &&
- children[0].getAttribute('data-mce-type') == 'bookmark') {
- node.parentNode.insertBefore(children[0], node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (type != 9) {
+ // Keep non whitespace text nodes
+ if (type == 3 && node.nodeValue.length > 0) {
+ // If parent element isn't a block or there isn't any useful contents for example "<p> </p>"
+ // Also keep text nodes with only spaces if surrounded by spans.
+ // eg. "<p><span>a</span> <span>b</span></p>" should keep space between a and b
+ var trimmedLength = trim(node.nodeValue).length;
+ if (!self.isBlock(node.parentNode) || trimmedLength > 0 || trimmedLength === 0 && surroundedBySpans(node)) {
+ return;
+ }
+ } else if (type == 1) {
+ // If the only child is a bookmark then move it up
+ children = node.childNodes;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Keep non empty elements or img, hr etc
- if (children.length || /^(br|hr|input|img)$/i.test(node.nodeName)) {
- return;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // TODO fix this complex if
+ if (children.length == 1 && children[0] && children[0].nodeType == 1 &&
+ children[0].getAttribute('data-mce-type') == 'bookmark') {
+ node.parentNode.insertBefore(children[0], node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.remove(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Keep non empty elements or img, hr etc
+ if (children.length || /^(br|hr|input|img)$/i.test(node.nodeName)) {
+ return;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.remove(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (parentElm && splitElm) {
- // Get before chunk
- r.setStart(parentElm.parentNode, self.nodeIndex(parentElm));
- r.setEnd(splitElm.parentNode, self.nodeIndex(splitElm));
- bef = r.extractContents();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Get after chunk
- r = self.createRng();
- r.setStart(splitElm.parentNode, self.nodeIndex(splitElm) + 1);
- r.setEnd(parentElm.parentNode, self.nodeIndex(parentElm) + 1);
- aft = r.extractContents();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parentElm && splitElm) {
+ // Get before chunk
+ r.setStart(parentElm.parentNode, self.nodeIndex(parentElm));
+ r.setEnd(splitElm.parentNode, self.nodeIndex(splitElm));
+ bef = r.extractContents();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Insert before chunk
- pa = parentElm.parentNode;
- pa.insertBefore(trimNode(bef), parentElm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get after chunk
+ r = self.createRng();
+ r.setStart(splitElm.parentNode, self.nodeIndex(splitElm) + 1);
+ r.setEnd(parentElm.parentNode, self.nodeIndex(parentElm) + 1);
+ aft = r.extractContents();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Insert middle chunk
- if (replacementElm) {
- pa.insertBefore(replacementElm, parentElm);
- //pa.replaceChild(replacementElm, splitElm);
- } else {
- pa.insertBefore(splitElm, parentElm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Insert before chunk
+ pa = parentElm.parentNode;
+ pa.insertBefore(trimNode(bef), parentElm);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Insert after chunk
- pa.insertBefore(trimNode(aft), parentElm);
- self.remove(parentElm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Insert middle chunk
+ if (replacementElm) {
+ pa.insertBefore(replacementElm, parentElm);
+ //pa.replaceChild(replacementElm, splitElm);
+ } else {
+ pa.insertBefore(splitElm, parentElm);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return replacementElm || splitElm;
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Insert after chunk
+ pa.insertBefore(trimNode(aft), parentElm);
+ self.remove(parentElm);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds an event handler to the specified object.
- *
- * @method bind
- * @param {Element/Document/Window/Array} target Target element to bind events to.
- * handler to or an array of elements/ids/documents.
- * @param {String} name Name of event handler to add, for example: click.
- * @param {function} func Function to execute when the event occurs.
- * @param {Object} scope Optional scope to execute the function in.
- * @return {function} Function callback handler the same as the one passed in.
- */
- bind: function(target, name, func, scope) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return replacementElm || splitElm;
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (Tools.isArray(target)) {
- var i = target.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds an event handler to the specified object.
+ *
+ * @method bind
+ * @param {Element/Document/Window/Array} target Target element to bind events to.
+ * handler to or an array of elements/ids/documents.
+ * @param {String} name Name of event handler to add, for example: click.
+ * @param {function} func Function to execute when the event occurs.
+ * @param {Object} scope Optional scope to execute the function in.
+ * @return {function} Function callback handler the same as the one passed in.
+ */
+ bind: function (target, name, func, scope) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- target[i] = self.bind(target[i], name, func, scope);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (Tools.isArray(target)) {
+ var i = target.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return target;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ target[i] = self.bind(target[i], name, func, scope);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Collect all window/document events bound by editor instance
- if (self.settings.collect && (target === self.doc || target === self.win)) {
- self.boundEvents.push([target, name, func, scope]);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return target;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self.events.bind(target, name, func, scope || self);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Collect all window/document events bound by editor instance
+ if (self.settings.collect && (target === self.doc || target === self.win)) {
+ self.boundEvents.push([target, name, func, scope]);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes the specified event handler by name and function from an element or collection of elements.
- *
- * @method unbind
- * @param {Element/Document/Window/Array} target Target element to unbind events on.
- * @param {String} name Event handler name, for example: "click"
- * @param {function} func Function to remove.
- * @return {bool/Array} Bool state of true if the handler was removed, or an array of states if multiple input elements
- * were passed in.
- */
- unbind: function(target, name, func) {
- var self = this, i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self.events.bind(target, name, func, scope || self);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (Tools.isArray(target)) {
- i = target.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes the specified event handler by name and function from an element or collection of elements.
+ *
+ * @method unbind
+ * @param {Element/Document/Window/Array} target Target element to unbind events on.
+ * @param {String} name Event handler name, for example: "click"
+ * @param {function} func Function to remove.
+ * @return {bool/Array} Bool state of true if the handler was removed, or an array of states if multiple input elements
+ * were passed in.
+ */
+ unbind: function (target, name, func) {
+ var self = this, i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- target[i] = self.unbind(target[i], name, func);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (Tools.isArray(target)) {
+ i = target.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return target;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ target[i] = self.unbind(target[i], name, func);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove any bound events matching the input
- if (self.boundEvents && (target === self.doc || target === self.win)) {
- i = self.boundEvents.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return target;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- var item = self.boundEvents[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove any bound events matching the input
+ if (self.boundEvents && (target === self.doc || target === self.win)) {
+ i = self.boundEvents.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (target == item[0] && (!name || name == item[1]) && (!func || func == item[2])) {
- this.events.unbind(item[0], item[1], item[2]);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ var item = self.boundEvents[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this.events.unbind(target, name, func);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (target == item[0] && (!name || name == item[1]) && (!func || func == item[2])) {
+ this.events.unbind(item[0], item[1], item[2]);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Fires the specified event name with object on target.
- *
- * @method fire
- * @param {Node/Document/Window} target Target element or object to fire event on.
- * @param {String} name Name of the event to fire.
- * @param {Object} evt Event object to send.
- * @return {Event} Event object.
- */
- fire: function(target, name, evt) {
- return this.events.fire(target, name, evt);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this.events.unbind(target, name, func);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Returns the content editable state of a node
- getContentEditable: function(node) {
- var contentEditable;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Fires the specified event name with object on target.
+ *
+ * @method fire
+ * @param {Node/Document/Window} target Target element or object to fire event on.
+ * @param {String} name Name of the event to fire.
+ * @param {Object} evt Event object to send.
+ * @return {Event} Event object.
+ */
+ fire: function (target, name, evt) {
+ return this.events.fire(target, name, evt);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check type
- if (!node || node.nodeType != 1) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Returns the content editable state of a node
+ getContentEditable: function (node) {
+ var contentEditable;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check for fake content editable
- contentEditable = node.getAttribute("data-mce-contenteditable");
- if (contentEditable && contentEditable !== "inherit") {
- return contentEditable;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check type
+ if (!node || node.nodeType != 1) {
+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check for real content editable
- return node.contentEditable !== "inherit" ? node.contentEditable : null;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check for fake content editable
+ contentEditable = node.getAttribute("data-mce-contenteditable");
+ if (contentEditable && contentEditable !== "inherit") {
+ return contentEditable;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- getContentEditableParent: function(node) {
- var root = this.getRoot(), state = null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check for real content editable
+ return node.contentEditable !== "inherit" ? node.contentEditable : null;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (; node && node !== root; node = node.parentNode) {
- state = this.getContentEditable(node);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ getContentEditableParent: function (node) {
+ var root = this.getRoot(), state = null;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (state !== null) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (; node && node !== root; node = node.parentNode) {
+ state = this.getContentEditable(node);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return state;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (state !== null) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Destroys all internal references to the DOM to solve IE leak issues.
- *
- * @method destroy
- */
- destroy: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return state;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Unbind all events bound to window/document by editor instance
- if (self.boundEvents) {
- var i = self.boundEvents.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Destroys all internal references to the DOM to solve IE leak issues.
+ *
+ * @method destroy
+ */
+ destroy: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- var item = self.boundEvents[i];
- this.events.unbind(item[0], item[1], item[2]);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Unbind all events bound to window/document by editor instance
+ if (self.boundEvents) {
+ var i = self.boundEvents.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.boundEvents = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ var item = self.boundEvents[i];
+ this.events.unbind(item[0], item[1], item[2]);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Restore sizzle document to window.document
- // Since the current document might be removed producing "Permission denied" on IE see #6325
- if (Sizzle.setDocument) {
- Sizzle.setDocument();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.boundEvents = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.win = self.doc = self.root = self.events = self.frag = null;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Restore sizzle document to window.document
+ // Since the current document might be removed producing "Permission denied" on IE see #6325
+ if (Sizzle.setDocument) {
+ Sizzle.setDocument();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- isChildOf: function(node, parent) {
- while (node) {
- if (parent === node) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.win = self.doc = self.root = self.events = self.frag = null;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ isChildOf: function (node, parent) {
+ while (node) {
+ if (parent === node) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // #ifdef debug
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dumpRng: function(r) {
- return (
- 'startContainer: ' + r.startContainer.nodeName +
- ', startOffset: ' + r.startOffset +
- ', endContainer: ' + r.endContainer.nodeName +
- ', endOffset: ' + r.endOffset
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // #ifdef debug
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // #endif
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dumpRng: function (r) {
+ return (
+ 'startContainer: ' + r.startContainer.nodeName +
+ ', startOffset: ' + r.startOffset +
+ ', endContainer: ' + r.endContainer.nodeName +
+ ', endOffset: ' + r.endOffset
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- _findSib: function(node, selector, name) {
- var self = this, func = selector;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // #endif
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node) {
- // If expression make a function of it using is
- if (typeof func == 'string') {
- func = function(node) {
- return self.is(node, selector);
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ _findSib: function (node, selector, name) {
+ var self = this, func = selector;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Loop all siblings
- for (node = node[name]; node; node = node[name]) {
- if (func(node)) {
- return node;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node) {
+ // If expression make a function of it using is
+ if (typeof func == 'string') {
+ func = function (node) {
+ return self.is(node, selector);
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Loop all siblings
+ for (node = node[name]; node; node = node[name]) {
+ if (func(node)) {
+ return node;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Instance of DOMUtils for the current document.
- *
- * @static
- * @property DOM
- * @type tinymce.dom.DOMUtils
- * @example
- * // Example of how to add a class to some element by id
- * tinymce.DOM.addClass('someid', 'someclass');
- */
- DOMUtils.DOM = new DOMUtils(document);
- DOMUtils.nodeIndex = nodeIndex;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return DOMUtils;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Instance of DOMUtils for the current document.
+ *
+ * @static
+ * @property DOM
+ * @type tinymce.dom.DOMUtils
+ * @example
+ * // Example of how to add a class to some element by id
+ * tinymce.DOM.addClass('someid', 'someclass');
+ */
+ DOMUtils.DOM = new DOMUtils(document);
+ DOMUtils.nodeIndex = nodeIndex;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/dom/ScriptLoader.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return DOMUtils;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * ScriptLoader.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -9424,275 +11493,277 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * alert('All scripts are now loaded.');
</span><span class="cx" style="display: block; padding: 0 10px"> * });
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/dom/ScriptLoader", [
- "tinymce/dom/DOMUtils",
- "tinymce/util/Tools"
-], function(DOMUtils, Tools) {
- var DOM = DOMUtils.DOM;
- var each = Tools.each, grep = Tools.grep;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.ScriptLoader',
+ [
+ "tinymce.core.dom.DOMUtils",
+ "tinymce.core.util.Tools"
+ ],
+ function (DOMUtils, Tools) {
+ var DOM = DOMUtils.DOM;
+ var each = Tools.each, grep = Tools.grep;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isFunction = function (f) {
- return typeof f === 'function';
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isFunction = function (f) {
+ return typeof f === 'function';
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function ScriptLoader() {
- var QUEUED = 0,
- LOADING = 1,
- LOADED = 2,
- FAILED = 3,
- states = {},
- queue = [],
- scriptLoadedCallbacks = {},
- queueLoadedCallbacks = [],
- loading = 0,
- undef;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function ScriptLoader() {
+ var QUEUED = 0,
+ LOADING = 1,
+ LOADED = 2,
+ FAILED = 3,
+ states = {},
+ queue = [],
+ scriptLoadedCallbacks = {},
+ queueLoadedCallbacks = [],
+ loading = 0,
+ undef;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Loads a specific script directly without adding it to the load queue.
- *
- * @method load
- * @param {String} url Absolute URL to script to add.
- * @param {function} callback Optional success callback function when the script loaded successfully.
- * @param {function} callback Optional failure callback function when the script failed to load.
- */
- function loadScript(url, success, failure) {
- var dom = DOM, elm, id;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Loads a specific script directly without adding it to the load queue.
+ *
+ * @method load
+ * @param {String} url Absolute URL to script to add.
+ * @param {function} callback Optional success callback function when the script loaded successfully.
+ * @param {function} callback Optional failure callback function when the script failed to load.
+ */
+ function loadScript(url, success, failure) {
+ var dom = DOM, elm, id;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Execute callback when script is loaded
- function done() {
- dom.remove(id);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Execute callback when script is loaded
+ function done() {
+ dom.remove(id);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elm) {
- elm.onreadystatechange = elm.onload = elm = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (elm) {
+ elm.onreadystatechange = elm.onload = elm = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- success();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ success();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function error() {
- /*eslint no-console:0 */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function error() {
+ /*eslint no-console:0 */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // We can't mark it as done if there is a load error since
- // A) We don't want to produce 404 errors on the server and
- // B) the onerror event won't fire on all browsers.
- // done();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // We can't mark it as done if there is a load error since
+ // A) We don't want to produce 404 errors on the server and
+ // B) the onerror event won't fire on all browsers.
+ // done();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isFunction(failure)) {
- failure();
- } else {
- // Report the error so it's easier for people to spot loading errors
- if (typeof console !== "undefined" && console.log) {
- console.log("Failed to load script: " + url);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isFunction(failure)) {
+ failure();
+ } else {
+ // Report the error so it's easier for people to spot loading errors
+ if (typeof console !== "undefined" && console.log) {
+ console.log("Failed to load script: " + url);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- id = dom.uniqueId();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ id = dom.uniqueId();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Create new script element
- elm = document.createElement('script');
- elm.id = id;
- elm.type = 'text/javascript';
- elm.src = Tools._addCacheSuffix(url);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Create new script element
+ elm = document.createElement('script');
+ elm.id = id;
+ elm.type = 'text/javascript';
+ elm.src = Tools._addCacheSuffix(url);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Seems that onreadystatechange works better on IE 10 onload seems to fire incorrectly
- if ("onreadystatechange" in elm) {
- elm.onreadystatechange = function() {
- if (/loaded|complete/.test(elm.readyState)) {
- done();
- }
- };
- } else {
- elm.onload = done;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Seems that onreadystatechange works better on IE 10 onload seems to fire incorrectly
+ if ("onreadystatechange" in elm) {
+ elm.onreadystatechange = function () {
+ if (/loaded|complete/.test(elm.readyState)) {
+ done();
+ }
+ };
+ } else {
+ elm.onload = done;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add onerror event will get fired on some browsers but not all of them
- elm.onerror = error;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add onerror event will get fired on some browsers but not all of them
+ elm.onerror = error;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add script to document
- (document.getElementsByTagName('head')[0] || document.body).appendChild(elm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add script to document
+ (document.getElementsByTagName('head')[0] || document.body).appendChild(elm);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if a script has been loaded or not.
- *
- * @method isDone
- * @param {String} url URL to check for.
- * @return {Boolean} true/false if the URL is loaded.
- */
- this.isDone = function(url) {
- return states[url] == LOADED;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if a script has been loaded or not.
+ *
+ * @method isDone
+ * @param {String} url URL to check for.
+ * @return {Boolean} true/false if the URL is loaded.
+ */
+ this.isDone = function (url) {
+ return states[url] == LOADED;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Marks a specific script to be loaded. This can be useful if a script got loaded outside
- * the script loader or to skip it from loading some script.
- *
- * @method markDone
- * @param {string} url Absolute URL to the script to mark as loaded.
- */
- this.markDone = function(url) {
- states[url] = LOADED;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Marks a specific script to be loaded. This can be useful if a script got loaded outside
+ * the script loader or to skip it from loading some script.
+ *
+ * @method markDone
+ * @param {string} url Absolute URL to the script to mark as loaded.
+ */
+ this.markDone = function (url) {
+ states[url] = LOADED;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds a specific script to the load queue of the script loader.
- *
- * @method add
- * @param {String} url Absolute URL to script to add.
- * @param {function} success Optional success callback function to execute when the script loades successfully.
- * @param {Object} scope Optional scope to execute callback in.
- * @param {function} failure Optional failure callback function to execute when the script failed to load.
- */
- this.add = this.load = function(url, success, scope, failure) {
- var state = states[url];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds a specific script to the load queue of the script loader.
+ *
+ * @method add
+ * @param {String} url Absolute URL to script to add.
+ * @param {function} success Optional success callback function to execute when the script loades successfully.
+ * @param {Object} scope Optional scope to execute callback in.
+ * @param {function} failure Optional failure callback function to execute when the script failed to load.
+ */
+ this.add = this.load = function (url, success, scope, failure) {
+ var state = states[url];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add url to load queue
- if (state == undef) {
- queue.push(url);
- states[url] = QUEUED;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add url to load queue
+ if (state == undef) {
+ queue.push(url);
+ states[url] = QUEUED;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (success) {
- // Store away callback for later execution
- if (!scriptLoadedCallbacks[url]) {
- scriptLoadedCallbacks[url] = [];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (success) {
+ // Store away callback for later execution
+ if (!scriptLoadedCallbacks[url]) {
+ scriptLoadedCallbacks[url] = [];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- scriptLoadedCallbacks[url].push({
- success: success,
- failure: failure,
- scope: scope || this
- });
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ scriptLoadedCallbacks[url].push({
+ success: success,
+ failure: failure,
+ scope: scope || this
+ });
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.remove = function(url) {
- delete states[url];
- delete scriptLoadedCallbacks[url];
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.remove = function (url) {
+ delete states[url];
+ delete scriptLoadedCallbacks[url];
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Starts the loading of the queue.
- *
- * @method loadQueue
- * @param {function} success Optional callback to execute when all queued items are loaded.
- * @param {function} failure Optional callback to execute when queued items failed to load.
- * @param {Object} scope Optional scope to execute the callback in.
- */
- this.loadQueue = function(success, scope, failure) {
- this.loadScripts(queue, success, scope, failure);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Starts the loading of the queue.
+ *
+ * @method loadQueue
+ * @param {function} success Optional callback to execute when all queued items are loaded.
+ * @param {function} failure Optional callback to execute when queued items failed to load.
+ * @param {Object} scope Optional scope to execute the callback in.
+ */
+ this.loadQueue = function (success, scope, failure) {
+ this.loadScripts(queue, success, scope, failure);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Loads the specified queue of files and executes the callback ones they are loaded.
- * This method is generally not used outside this class but it might be useful in some scenarios.
- *
- * @method loadScripts
- * @param {Array} scripts Array of queue items to load.
- * @param {function} callback Optional callback to execute when scripts is loaded successfully.
- * @param {Object} scope Optional scope to execute callback in.
- * @param {function} callback Optional callback to execute if scripts failed to load.
- */
- this.loadScripts = function(scripts, success, scope, failure) {
- var loadScripts, failures = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Loads the specified queue of files and executes the callback ones they are loaded.
+ * This method is generally not used outside this class but it might be useful in some scenarios.
+ *
+ * @method loadScripts
+ * @param {Array} scripts Array of queue items to load.
+ * @param {function} callback Optional callback to execute when scripts is loaded successfully.
+ * @param {Object} scope Optional scope to execute callback in.
+ * @param {function} callback Optional callback to execute if scripts failed to load.
+ */
+ this.loadScripts = function (scripts, success, scope, failure) {
+ var loadScripts, failures = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function execCallbacks(name, url) {
- // Execute URL callback functions
- each(scriptLoadedCallbacks[url], function(callback) {
- if (isFunction(callback[name])) {
- callback[name].call(callback.scope);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function execCallbacks(name, url) {
+ // Execute URL callback functions
+ each(scriptLoadedCallbacks[url], function (callback) {
+ if (isFunction(callback[name])) {
+ callback[name].call(callback.scope);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- scriptLoadedCallbacks[url] = undef;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ scriptLoadedCallbacks[url] = undef;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- queueLoadedCallbacks.push({
- success: success,
- failure: failure,
- scope: scope || this
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ queueLoadedCallbacks.push({
+ success: success,
+ failure: failure,
+ scope: scope || this
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- loadScripts = function() {
- var loadingScripts = grep(scripts);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ loadScripts = function () {
+ var loadingScripts = grep(scripts);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Current scripts has been handled
- scripts.length = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Current scripts has been handled
+ scripts.length = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Load scripts that needs to be loaded
- each(loadingScripts, function(url) {
- // Script is already loaded then execute script callbacks directly
- if (states[url] === LOADED) {
- execCallbacks('success', url);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Load scripts that needs to be loaded
+ each(loadingScripts, function (url) {
+ // Script is already loaded then execute script callbacks directly
+ if (states[url] === LOADED) {
+ execCallbacks('success', url);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (states[url] === FAILED) {
- execCallbacks('failure', url);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (states[url] === FAILED) {
+ execCallbacks('failure', url);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Is script not loading then start loading it
- if (states[url] !== LOADING) {
- states[url] = LOADING;
- loading++;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Is script not loading then start loading it
+ if (states[url] !== LOADING) {
+ states[url] = LOADING;
+ loading++;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- loadScript(url, function() {
- states[url] = LOADED;
- loading--;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ loadScript(url, function () {
+ states[url] = LOADED;
+ loading--;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- execCallbacks('success', url);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ execCallbacks('success', url);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Load more scripts if they where added by the recently loaded script
- loadScripts();
- }, function () {
- states[url] = FAILED;
- loading--;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Load more scripts if they where added by the recently loaded script
+ loadScripts();
+ }, function () {
+ states[url] = FAILED;
+ loading--;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- failures.push(url);
- execCallbacks('failure', url);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ failures.push(url);
+ execCallbacks('failure', url);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Load more scripts if they where added by the recently loaded script
- loadScripts();
- });
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Load more scripts if they where added by the recently loaded script
+ loadScripts();
+ });
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // No scripts are currently loading then execute all pending queue loaded callbacks
- if (!loading) {
- each(queueLoadedCallbacks, function(callback) {
- if (failures.length === 0) {
- if (isFunction(callback.success)) {
- callback.success.call(callback.scope);
- }
- } else {
- if (isFunction(callback.failure)) {
- callback.failure.call(callback.scope, failures);
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // No scripts are currently loading then execute all pending queue loaded callbacks
+ if (!loading) {
+ each(queueLoadedCallbacks, function (callback) {
+ if (failures.length === 0) {
+ if (isFunction(callback.success)) {
+ callback.success.call(callback.scope);
+ }
+ } else {
+ if (isFunction(callback.failure)) {
+ callback.failure.call(callback.scope, failures);
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- queueLoadedCallbacks.length = 0;
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ queueLoadedCallbacks.length = 0;
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- loadScripts();
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ loadScripts();
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ScriptLoader.ScriptLoader = new ScriptLoader();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ScriptLoader.ScriptLoader = new ScriptLoader();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return ScriptLoader;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return ScriptLoader;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/AddOnManager.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * AddOnManager.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -9703,202 +11774,206 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.AddOnManager
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/AddOnManager", [
- "tinymce/dom/ScriptLoader",
- "tinymce/util/Tools"
-], function(ScriptLoader, Tools) {
- var each = Tools.each;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.AddOnManager',
+ [
+ "tinymce.core.dom.ScriptLoader",
+ "tinymce.core.util.Tools"
+ ],
+ function (ScriptLoader, Tools) {
+ var each = Tools.each;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function AddOnManager() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function AddOnManager() {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.items = [];
- self.urls = {};
- self.lookup = {};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.items = [];
+ self.urls = {};
+ self.lookup = {};
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- AddOnManager.prototype = {
- /**
- * Returns the specified add on by the short name.
- *
- * @method get
- * @param {String} name Add-on to look for.
- * @return {tinymce.Theme/tinymce.Plugin} Theme or plugin add-on instance or undefined.
- */
- get: function(name) {
- if (this.lookup[name]) {
- return this.lookup[name].instance;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ AddOnManager.prototype = {
+ /**
+ * Returns the specified add on by the short name.
+ *
+ * @method get
+ * @param {String} name Add-on to look for.
+ * @return {tinymce.Theme/tinymce.Plugin} Theme or plugin add-on instance or undefined.
+ */
+ get: function (name) {
+ if (this.lookup[name]) {
+ return this.lookup[name].instance;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return undefined;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return undefined;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dependencies: function(name) {
- var result;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dependencies: function (name) {
+ var result;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.lookup[name]) {
- result = this.lookup[name].dependencies;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.lookup[name]) {
+ result = this.lookup[name].dependencies;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return result || [];
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return result || [];
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Loads a language pack for the specified add-on.
- *
- * @method requireLangPack
- * @param {String} name Short name of the add-on.
- * @param {String} languages Optional comma or space separated list of languages to check if it matches the name.
- */
- requireLangPack: function(name, languages) {
- var language = AddOnManager.language;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Loads a language pack for the specified add-on.
+ *
+ * @method requireLangPack
+ * @param {String} name Short name of the add-on.
+ * @param {String} languages Optional comma or space separated list of languages to check if it matches the name.
+ */
+ requireLangPack: function (name, languages) {
+ var language = AddOnManager.language;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (language && AddOnManager.languageLoad !== false) {
- if (languages) {
- languages = ',' + languages + ',';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (language && AddOnManager.languageLoad !== false) {
+ if (languages) {
+ languages = ',' + languages + ',';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Load short form sv.js or long form sv_SE.js
- if (languages.indexOf(',' + language.substr(0, 2) + ',') != -1) {
- language = language.substr(0, 2);
- } else if (languages.indexOf(',' + language + ',') == -1) {
- return;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Load short form sv.js or long form sv_SE.js
+ if (languages.indexOf(',' + language.substr(0, 2) + ',') != -1) {
+ language = language.substr(0, 2);
+ } else if (languages.indexOf(',' + language + ',') == -1) {
+ return;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ScriptLoader.ScriptLoader.add(this.urls[name] + '/langs/' + language + '.js');
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ScriptLoader.ScriptLoader.add(this.urls[name] + '/langs/' + language + '.js');
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds a instance of the add-on by it's short name.
- *
- * @method add
- * @param {String} id Short name/id for the add-on.
- * @param {tinymce.Theme/tinymce.Plugin} addOn Theme or plugin to add.
- * @return {tinymce.Theme/tinymce.Plugin} The same theme or plugin instance that got passed in.
- * @example
- * // Create a simple plugin
- * tinymce.create('tinymce.plugins.TestPlugin', {
- * TestPlugin: function(ed, url) {
- * ed.on('click', function(e) {
- * ed.windowManager.alert('Hello World!');
- * });
- * }
- * });
- *
- * // Register plugin using the add method
- * tinymce.PluginManager.add('test', tinymce.plugins.TestPlugin);
- *
- * // Initialize TinyMCE
- * tinymce.init({
- * ...
- * plugins: '-test' // Init the plugin but don't try to load it
- * });
- */
- add: function(id, addOn, dependencies) {
- this.items.push(addOn);
- this.lookup[id] = {instance: addOn, dependencies: dependencies};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds a instance of the add-on by it's short name.
+ *
+ * @method add
+ * @param {String} id Short name/id for the add-on.
+ * @param {tinymce.Theme/tinymce.Plugin} addOn Theme or plugin to add.
+ * @return {tinymce.Theme/tinymce.Plugin} The same theme or plugin instance that got passed in.
+ * @example
+ * // Create a simple plugin
+ * tinymce.create('tinymce.plugins.TestPlugin', {
+ * TestPlugin: function(ed, url) {
+ * ed.on('click', function(e) {
+ * ed.windowManager.alert('Hello World!');
+ * });
+ * }
+ * });
+ *
+ * // Register plugin using the add method
+ * tinymce.PluginManager.add('test', tinymce.plugins.TestPlugin);
+ *
+ * // Initialize TinyMCE
+ * tinymce.init({
+ * ...
+ * plugins: '-test' // Init the plugin but don't try to load it
+ * });
+ */
+ add: function (id, addOn, dependencies) {
+ this.items.push(addOn);
+ this.lookup[id] = { instance: addOn, dependencies: dependencies };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return addOn;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return addOn;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- remove: function(name) {
- delete this.urls[name];
- delete this.lookup[name];
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ remove: function (name) {
+ delete this.urls[name];
+ delete this.lookup[name];
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- createUrl: function(baseUrl, dep) {
- if (typeof dep === "object") {
- return dep;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ createUrl: function (baseUrl, dep) {
+ if (typeof dep === "object") {
+ return dep;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {prefix: baseUrl.prefix, resource: dep, suffix: baseUrl.suffix};
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return { prefix: baseUrl.prefix, resource: dep, suffix: baseUrl.suffix };
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Add a set of components that will make up the add-on. Using the url of the add-on name as the base url.
- * This should be used in development mode. A new compressor/javascript munger process will ensure that the
- * components are put together into the plugin.js file and compressed correctly.
- *
- * @method addComponents
- * @param {String} pluginName name of the plugin to load scripts from (will be used to get the base url for the plugins).
- * @param {Array} scripts Array containing the names of the scripts to load.
- */
- addComponents: function(pluginName, scripts) {
- var pluginUrl = this.urls[pluginName];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Add a set of components that will make up the add-on. Using the url of the add-on name as the base url.
+ * This should be used in development mode. A new compressor/javascript munger process will ensure that the
+ * components are put together into the plugin.js file and compressed correctly.
+ *
+ * @method addComponents
+ * @param {String} pluginName name of the plugin to load scripts from (will be used to get the base url for the plugins).
+ * @param {Array} scripts Array containing the names of the scripts to load.
+ */
+ addComponents: function (pluginName, scripts) {
+ var pluginUrl = this.urls[pluginName];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(scripts, function(script) {
- ScriptLoader.ScriptLoader.add(pluginUrl + "/" + script);
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(scripts, function (script) {
+ ScriptLoader.ScriptLoader.add(pluginUrl + "/" + script);
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Loads an add-on from a specific url.
- *
- * @method load
- * @param {String} name Short name of the add-on that gets loaded.
- * @param {String} addOnUrl URL to the add-on that will get loaded.
- * @param {function} success Optional success callback to execute when an add-on is loaded.
- * @param {Object} scope Optional scope to execute the callback in.
- * @param {function} failure Optional failure callback to execute when an add-on failed to load.
- * @example
- * // Loads a plugin from an external URL
- * tinymce.PluginManager.load('myplugin', '/some/dir/someplugin/plugin.js');
- *
- * // Initialize TinyMCE
- * tinymce.init({
- * ...
- * plugins: '-myplugin' // Don't try to load it again
- * });
- */
- load: function(name, addOnUrl, success, scope, failure) {
- var self = this, url = addOnUrl;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Loads an add-on from a specific url.
+ *
+ * @method load
+ * @param {String} name Short name of the add-on that gets loaded.
+ * @param {String} addOnUrl URL to the add-on that will get loaded.
+ * @param {function} success Optional success callback to execute when an add-on is loaded.
+ * @param {Object} scope Optional scope to execute the callback in.
+ * @param {function} failure Optional failure callback to execute when an add-on failed to load.
+ * @example
+ * // Loads a plugin from an external URL
+ * tinymce.PluginManager.load('myplugin', '/some/dir/someplugin/plugin.js');
+ *
+ * // Initialize TinyMCE
+ * tinymce.init({
+ * ...
+ * plugins: '-myplugin' // Don't try to load it again
+ * });
+ */
+ load: function (name, addOnUrl, success, scope, failure) {
+ var self = this, url = addOnUrl;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function loadDependencies() {
- var dependencies = self.dependencies(name);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function loadDependencies() {
+ var dependencies = self.dependencies(name);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(dependencies, function(dep) {
- var newUrl = self.createUrl(addOnUrl, dep);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(dependencies, function (dep) {
+ var newUrl = self.createUrl(addOnUrl, dep);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.load(newUrl.resource, newUrl, undefined, undefined);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.load(newUrl.resource, newUrl, undefined, undefined);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (success) {
- if (scope) {
- success.call(scope);
- } else {
- success.call(ScriptLoader);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (success) {
+ if (scope) {
+ success.call(scope);
+ } else {
+ success.call(ScriptLoader);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.urls[name]) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.urls[name]) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof addOnUrl === "object") {
- url = addOnUrl.prefix + addOnUrl.resource + addOnUrl.suffix;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof addOnUrl === "object") {
+ url = addOnUrl.prefix + addOnUrl.resource + addOnUrl.suffix;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (url.indexOf('/') !== 0 && url.indexOf('://') == -1) {
- url = AddOnManager.baseURL + '/' + url;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (url.indexOf('/') !== 0 && url.indexOf('://') == -1) {
+ url = AddOnManager.baseURL + '/' + url;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.urls[name] = url.substring(0, url.lastIndexOf('/'));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.urls[name] = url.substring(0, url.lastIndexOf('/'));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.lookup[name]) {
- loadDependencies();
- } else {
- ScriptLoader.ScriptLoader.add(url, loadDependencies, scope, failure);
- }
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.lookup[name]) {
+ loadDependencies();
+ } else {
+ ScriptLoader.ScriptLoader.add(url, loadDependencies, scope, failure);
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- AddOnManager.PluginManager = new AddOnManager();
- AddOnManager.ThemeManager = new AddOnManager();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ AddOnManager.PluginManager = new AddOnManager();
+ AddOnManager.ThemeManager = new AddOnManager();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return AddOnManager;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return AddOnManager;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * TinyMCE theme class.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -9960,13 +12035,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * });
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/dom/NodeType.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * NodeType.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -9978,108 +12051,117 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.dom.NodeType
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/dom/NodeType", [], function() {
- function isNodeType(type) {
- return function(node) {
- return !!node && node.nodeType == type;
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.NodeType',
+ [
+ ],
+ function () {
+ function isNodeType(type) {
+ return function (node) {
+ return !!node && node.nodeType == type;
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isElement = isNodeType(1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isElement = isNodeType(1);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function matchNodeNames(names) {
- names = names.toLowerCase().split(' ');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function matchNodeNames(names) {
+ names = names.toLowerCase().split(' ');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function(node) {
- var i, name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function (node) {
+ var i, name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node && node.nodeType) {
- name = node.nodeName.toLowerCase();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node && node.nodeType) {
+ name = node.nodeName.toLowerCase();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0; i < names.length; i++) {
- if (name === names[i]) {
- return true;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0; i < names.length; i++) {
+ if (name === names[i]) {
+ return true;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function matchStyleValues(name, values) {
- values = values.toLowerCase().split(' ');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function matchStyleValues(name, values) {
+ values = values.toLowerCase().split(' ');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function(node) {
- var i, cssValue;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function (node) {
+ var i, cssValue;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isElement(node)) {
- for (i = 0; i < values.length; i++) {
- cssValue = getComputedStyle(node, null).getPropertyValue(name);
- if (cssValue === values[i]) {
- return true;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isElement(node)) {
+ for (i = 0; i < values.length; i++) {
+ cssValue = node.ownerDocument.defaultView.getComputedStyle(node, null).getPropertyValue(name);
+ if (cssValue === values[i]) {
+ return true;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hasPropValue(propName, propValue) {
- return function(node) {
- return isElement(node) && node[propName] === propValue;
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hasPropValue(propName, propValue) {
+ return function (node) {
+ return isElement(node) && node[propName] === propValue;
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hasAttributeValue(attrName, attrValue) {
- return function(node) {
- return isElement(node) && node.getAttribute(attrName) === attrValue;
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hasAttribute(attrName, attrValue) {
+ return function (node) {
+ return isElement(node) && node.hasAttribute(attrName);
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isBogus(node) {
- return isElement(node) && node.hasAttribute('data-mce-bogus');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hasAttributeValue(attrName, attrValue) {
+ return function (node) {
+ return isElement(node) && node.getAttribute(attrName) === attrValue;
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hasContentEditableState(value) {
- return function(node) {
- if (isElement(node)) {
- if (node.contentEditable === value) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isBogus(node) {
+ return isElement(node) && node.hasAttribute('data-mce-bogus');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.getAttribute('data-mce-contenteditable') === value) {
- return true;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hasContentEditableState(value) {
+ return function (node) {
+ if (isElement(node)) {
+ if (node.contentEditable === value) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.getAttribute('data-mce-contenteditable') === value) {
+ return true;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- isText: isNodeType(3),
- isElement: isElement,
- isComment: isNodeType(8),
- isBr: matchNodeNames('br'),
- isContentEditableTrue: hasContentEditableState('true'),
- isContentEditableFalse: hasContentEditableState('false'),
- matchNodeNames: matchNodeNames,
- hasPropValue: hasPropValue,
- hasAttributeValue: hasAttributeValue,
- matchStyleValues: matchStyleValues,
- isBogus: isBogus
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/text/Zwsp.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ isText: isNodeType(3),
+ isElement: isElement,
+ isComment: isNodeType(8),
+ isBr: matchNodeNames('br'),
+ isContentEditableTrue: hasContentEditableState('true'),
+ isContentEditableFalse: hasContentEditableState('false'),
+ matchNodeNames: matchNodeNames,
+ hasPropValue: hasPropValue,
+ hasAttribute: hasAttribute,
+ hasAttributeValue: hasAttributeValue,
+ matchStyleValues: matchStyleValues,
+ isBogus: isBogus
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Zwsp.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -10095,31 +12177,34 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * var isZwsp = Zwsp.isZwsp('\uFEFF');
</span><span class="cx" style="display: block; padding: 0 10px"> * var abc = Zwsp.trim('a\uFEFFc');
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/text/Zwsp", [], function() {
- var ZWSP = '\uFEFF';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.text.Zwsp',
+ [
+ ],
+ function () {
+ // This is technically not a ZWSP but a ZWNBSP or a BYTE ORDER MARK it used to be a ZWSP
+ var ZWSP = '\uFEFF';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isZwsp(chr) {
- return chr == ZWSP;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isZwsp = function (chr) {
+ return chr === ZWSP;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function trim(str) {
- return str.replace(new RegExp(ZWSP, 'g'), '');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var trim = function (text) {
+ return text.replace(new RegExp(ZWSP, 'g'), '');
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- isZwsp: isZwsp,
- ZWSP: ZWSP,
- trim: trim
- };
-});
-
-// Included from: js/tinymce/classes/caret/CaretContainer.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ isZwsp: isZwsp,
+ ZWSP: ZWSP,
+ trim: trim
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * CaretContainer.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -10132,194 +12217,191 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.caret.CaretContainer
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/caret/CaretContainer", [
- "tinymce/dom/NodeType",
- "tinymce/text/Zwsp"
-], function(NodeType, Zwsp) {
- var isElement = NodeType.isElement,
- isText = NodeType.isText;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.caret.CaretContainer',
+ [
+ "tinymce.core.dom.NodeType",
+ "tinymce.core.text.Zwsp"
+ ],
+ function (NodeType, Zwsp) {
+ var isElement = NodeType.isElement,
+ isText = NodeType.isText;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isCaretContainerBlock(node) {
- if (isText(node)) {
- node = node.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isCaretContainerBlock(node) {
+ if (isText(node)) {
+ node = node.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return isElement(node) && node.hasAttribute('data-mce-caret');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return isElement(node) && node.hasAttribute('data-mce-caret');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isCaretContainerInline(node) {
- return isText(node) && Zwsp.isZwsp(node.data);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isCaretContainerInline(node) {
+ return isText(node) && Zwsp.isZwsp(node.data);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isCaretContainer(node) {
- return isCaretContainerBlock(node) || isCaretContainerInline(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isCaretContainer(node) {
+ return isCaretContainerBlock(node) || isCaretContainerInline(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function removeNode(node) {
- var parentNode = node.parentNode;
- if (parentNode) {
- parentNode.removeChild(node);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var hasContent = function (node) {
+ return node.firstChild !== node.lastChild || !NodeType.isBr(node.firstChild);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getNodeValue(node) {
- try {
- return node.nodeValue;
- } catch (ex) {
- // IE sometimes produces "Invalid argument" on nodes
- return "";
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function insertInline(node, before) {
+ var doc, sibling, textNode, parentNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setNodeValue(node, text) {
- if (text.length === 0) {
- removeNode(node);
- } else {
- node.nodeValue = text;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ doc = node.ownerDocument;
+ textNode = doc.createTextNode(Zwsp.ZWSP);
+ parentNode = node.parentNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function insertInline(node, before) {
- var doc, sibling, textNode, parentNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!before) {
+ sibling = node.nextSibling;
+ if (isText(sibling)) {
+ if (isCaretContainer(sibling)) {
+ return sibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- doc = node.ownerDocument;
- textNode = doc.createTextNode(Zwsp.ZWSP);
- parentNode = node.parentNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (startsWithCaretContainer(sibling)) {
+ sibling.splitText(1);
+ return sibling;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!before) {
- sibling = node.nextSibling;
- if (isText(sibling)) {
- if (isCaretContainer(sibling)) {
- return sibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.nextSibling) {
+ parentNode.insertBefore(textNode, node.nextSibling);
+ } else {
+ parentNode.appendChild(textNode);
+ }
+ } else {
+ sibling = node.previousSibling;
+ if (isText(sibling)) {
+ if (isCaretContainer(sibling)) {
+ return sibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (startsWithCaretContainer(sibling)) {
- sibling.splitText(1);
- return sibling;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (endsWithCaretContainer(sibling)) {
+ return sibling.splitText(sibling.data.length - 1);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.nextSibling) {
- parentNode.insertBefore(textNode, node.nextSibling);
- } else {
- parentNode.appendChild(textNode);
- }
- } else {
- sibling = node.previousSibling;
- if (isText(sibling)) {
- if (isCaretContainer(sibling)) {
- return sibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parentNode.insertBefore(textNode, node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (endsWithCaretContainer(sibling)) {
- return sibling.splitText(sibling.data.length - 1);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return textNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parentNode.insertBefore(textNode, node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var prependInline = function (node) {
+ if (NodeType.isText(node)) {
+ var data = node.data;
+ if (data.length > 0 && data.charAt(0) !== Zwsp.ZWSP) {
+ node.insertData(0, Zwsp.ZWSP);
+ }
+ return node;
+ } else {
+ return null;
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return textNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var appendInline = function (node) {
+ if (NodeType.isText(node)) {
+ var data = node.data;
+ if (data.length > 0 && data.charAt(data.length - 1) !== Zwsp.ZWSP) {
+ node.insertData(data.length, Zwsp.ZWSP);
+ }
+ return node;
+ } else {
+ return null;
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function createBogusBr() {
- var br = document.createElement('br');
- br.setAttribute('data-mce-bogus', '1');
- return br;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isBeforeInline = function (pos) {
+ return pos && NodeType.isText(pos.container()) && pos.container().data.charAt(pos.offset()) === Zwsp.ZWSP;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function insertBlock(blockName, node, before) {
- var doc, blockNode, parentNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isAfterInline = function (pos) {
+ return pos && NodeType.isText(pos.container()) && pos.container().data.charAt(pos.offset() - 1) === Zwsp.ZWSP;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- doc = node.ownerDocument;
- blockNode = doc.createElement(blockName);
- blockNode.setAttribute('data-mce-caret', before ? 'before' : 'after');
- blockNode.setAttribute('data-mce-bogus', 'all');
- blockNode.appendChild(createBogusBr());
- parentNode = node.parentNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function createBogusBr() {
+ var br = document.createElement('br');
+ br.setAttribute('data-mce-bogus', '1');
+ return br;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!before) {
- if (node.nextSibling) {
- parentNode.insertBefore(blockNode, node.nextSibling);
- } else {
- parentNode.appendChild(blockNode);
- }
- } else {
- parentNode.insertBefore(blockNode, node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function insertBlock(blockName, node, before) {
+ var doc, blockNode, parentNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return blockNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ doc = node.ownerDocument;
+ blockNode = doc.createElement(blockName);
+ blockNode.setAttribute('data-mce-caret', before ? 'before' : 'after');
+ blockNode.setAttribute('data-mce-bogus', 'all');
+ blockNode.appendChild(createBogusBr());
+ parentNode = node.parentNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hasContent(node) {
- return node.firstChild !== node.lastChild || !NodeType.isBr(node.firstChild);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!before) {
+ if (node.nextSibling) {
+ parentNode.insertBefore(blockNode, node.nextSibling);
+ } else {
+ parentNode.appendChild(blockNode);
+ }
+ } else {
+ parentNode.insertBefore(blockNode, node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function remove(caretContainerNode) {
- if (isElement(caretContainerNode) && isCaretContainer(caretContainerNode)) {
- if (hasContent(caretContainerNode)) {
- caretContainerNode.removeAttribute('data-mce-caret');
- } else {
- removeNode(caretContainerNode);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return blockNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isText(caretContainerNode)) {
- var text = Zwsp.trim(getNodeValue(caretContainerNode));
- setNodeValue(caretContainerNode, text);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function startsWithCaretContainer(node) {
+ return isText(node) && node.data[0] == Zwsp.ZWSP;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function startsWithCaretContainer(node) {
- return isText(node) && node.data[0] == Zwsp.ZWSP;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function endsWithCaretContainer(node) {
+ return isText(node) && node.data[node.data.length - 1] == Zwsp.ZWSP;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function endsWithCaretContainer(node) {
- return isText(node) && node.data[node.data.length - 1] == Zwsp.ZWSP;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function trimBogusBr(elm) {
+ var brs = elm.getElementsByTagName('br');
+ var lastBr = brs[brs.length - 1];
+ if (NodeType.isBogus(lastBr)) {
+ lastBr.parentNode.removeChild(lastBr);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function trimBogusBr(elm) {
- var brs = elm.getElementsByTagName('br');
- var lastBr = brs[brs.length - 1];
- if (NodeType.isBogus(lastBr)) {
- lastBr.parentNode.removeChild(lastBr);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function showCaretContainerBlock(caretContainer) {
+ if (caretContainer && caretContainer.hasAttribute('data-mce-caret')) {
+ trimBogusBr(caretContainer);
+ caretContainer.removeAttribute('data-mce-caret');
+ caretContainer.removeAttribute('data-mce-bogus');
+ caretContainer.removeAttribute('style');
+ caretContainer.removeAttribute('_moz_abspos');
+ return caretContainer;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function showCaretContainerBlock(caretContainer) {
- if (caretContainer && caretContainer.hasAttribute('data-mce-caret')) {
- trimBogusBr(caretContainer);
- caretContainer.removeAttribute('data-mce-caret');
- caretContainer.removeAttribute('data-mce-bogus');
- caretContainer.removeAttribute('style');
- caretContainer.removeAttribute('_moz_abspos');
- return caretContainer;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
-
- return {
- isCaretContainer: isCaretContainer,
- isCaretContainerBlock: isCaretContainerBlock,
- isCaretContainerInline: isCaretContainerInline,
- showCaretContainerBlock: showCaretContainerBlock,
- insertInline: insertInline,
- insertBlock: insertBlock,
- hasContent: hasContent,
- remove: remove,
- startsWithCaretContainer: startsWithCaretContainer,
- endsWithCaretContainer: endsWithCaretContainer
- };
-});
-
-// Included from: js/tinymce/classes/dom/RangeUtils.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ isCaretContainer: isCaretContainer,
+ isCaretContainerBlock: isCaretContainerBlock,
+ isCaretContainerInline: isCaretContainerInline,
+ showCaretContainerBlock: showCaretContainerBlock,
+ insertInline: insertInline,
+ prependInline: prependInline,
+ appendInline: appendInline,
+ isBeforeInline: isBeforeInline,
+ isAfterInline: isAfterInline,
+ insertBlock: insertBlock,
+ hasContent: hasContent,
+ startsWithCaretContainer: startsWithCaretContainer,
+ endsWithCaretContainer: endsWithCaretContainer
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * RangeUtils.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -10330,830 +12412,680 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.dom.RangeUtils
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/dom/RangeUtils", [
- "tinymce/util/Tools",
- "tinymce/dom/TreeWalker",
- "tinymce/dom/NodeType",
- "tinymce/dom/Range",
- "tinymce/caret/CaretContainer"
-], function(Tools, TreeWalker, NodeType, Range, CaretContainer) {
- var each = Tools.each,
- isContentEditableTrue = NodeType.isContentEditableTrue,
- isContentEditableFalse = NodeType.isContentEditableFalse,
- isCaretContainer = CaretContainer.isCaretContainer;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.RangeUtils',
+ [
+ "tinymce.core.util.Tools",
+ "tinymce.core.dom.TreeWalker",
+ "tinymce.core.dom.NodeType",
+ "tinymce.core.dom.Range",
+ "tinymce.core.caret.CaretContainer"
+ ],
+ function (Tools, TreeWalker, NodeType, Range, CaretContainer) {
+ var each = Tools.each,
+ isContentEditableTrue = NodeType.isContentEditableTrue,
+ isContentEditableFalse = NodeType.isContentEditableFalse,
+ isCaretContainer = CaretContainer.isCaretContainer;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hasCeProperty(node) {
- return isContentEditableTrue(node) || isContentEditableFalse(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hasCeProperty(node) {
+ return isContentEditableTrue(node) || isContentEditableFalse(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getEndChild(container, index) {
- var childNodes = container.childNodes;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getEndChild(container, index) {
+ var childNodes = container.childNodes;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- index--;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ index--;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (index > childNodes.length - 1) {
- index = childNodes.length - 1;
- } else if (index < 0) {
- index = 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (index > childNodes.length - 1) {
+ index = childNodes.length - 1;
+ } else if (index < 0) {
+ index = 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return childNodes[index] || container;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return childNodes[index] || container;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function findParent(node, rootNode, predicate) {
- while (node && node !== rootNode) {
- if (predicate(node)) {
- return node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function findParent(node, rootNode, predicate) {
+ while (node && node !== rootNode) {
+ if (predicate(node)) {
+ return node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hasParent(node, rootNode, predicate) {
- return findParent(node, rootNode, predicate) !== null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hasParent(node, rootNode, predicate) {
+ return findParent(node, rootNode, predicate) !== null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isFormatterCaret(node) {
- return node.id === '_mce_caret';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hasParentWithName(node, rootNode, name) {
+ return hasParent(node, rootNode, function (node) {
+ return node.nodeName === name;
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isCeFalseCaretContainer(node, rootNode) {
- return isCaretContainer(node) && hasParent(node, rootNode, isFormatterCaret) === false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isFormatterCaret(node) {
+ return node.id === '_mce_caret';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function RangeUtils(dom) {
- /**
- * Walks the specified range like object and executes the callback for each sibling collection it finds.
- *
- * @private
- * @method walk
- * @param {Object} rng Range like object.
- * @param {function} callback Callback function to execute for each sibling collection.
- */
- this.walk = function(rng, callback) {
- var startContainer = rng.startContainer,
- startOffset = rng.startOffset,
- endContainer = rng.endContainer,
- endOffset = rng.endOffset,
- ancestor, startPoint,
- endPoint, node, parent, siblings, nodes;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isCeFalseCaretContainer(node, rootNode) {
+ return isCaretContainer(node) && hasParent(node, rootNode, isFormatterCaret) === false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle table cell selection the table plugin enables
- // you to fake select table cells and perform formatting actions on them
- nodes = dom.select('td[data-mce-selected],th[data-mce-selected]');
- if (nodes.length > 0) {
- each(nodes, function(node) {
- callback([node]);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function RangeUtils(dom) {
+ /**
+ * Walks the specified range like object and executes the callback for each sibling collection it finds.
+ *
+ * @private
+ * @method walk
+ * @param {Object} rng Range like object.
+ * @param {function} callback Callback function to execute for each sibling collection.
+ */
+ this.walk = function (rng, callback) {
+ var startContainer = rng.startContainer,
+ startOffset = rng.startOffset,
+ endContainer = rng.endContainer,
+ endOffset = rng.endOffset,
+ ancestor, startPoint,
+ endPoint, node, parent, siblings, nodes;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handle table cell selection the table plugin enables
+ // you to fake select table cells and perform formatting actions on them
+ nodes = dom.select('td[data-mce-selected],th[data-mce-selected]');
+ if (nodes.length > 0) {
+ each(nodes, function (node) {
+ callback([node]);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Excludes start/end text node if they are out side the range
- *
- * @private
- * @param {Array} nodes Nodes to exclude items from.
- * @return {Array} Array with nodes excluding the start/end container if needed.
- */
- function exclude(nodes) {
- var node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // First node is excluded
- node = nodes[0];
- if (node.nodeType === 3 && node === startContainer && startOffset >= node.nodeValue.length) {
- nodes.splice(0, 1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Excludes start/end text node if they are out side the range
+ *
+ * @private
+ * @param {Array} nodes Nodes to exclude items from.
+ * @return {Array} Array with nodes excluding the start/end container if needed.
+ */
+ function exclude(nodes) {
+ var node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Last node is excluded
- node = nodes[nodes.length - 1];
- if (endOffset === 0 && nodes.length > 0 && node === endContainer && node.nodeType === 3) {
- nodes.splice(nodes.length - 1, 1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // First node is excluded
+ node = nodes[0];
+ if (node.nodeType === 3 && node === startContainer && startOffset >= node.nodeValue.length) {
+ nodes.splice(0, 1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return nodes;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Last node is excluded
+ node = nodes[nodes.length - 1];
+ if (endOffset === 0 && nodes.length > 0 && node === endContainer && node.nodeType === 3) {
+ nodes.splice(nodes.length - 1, 1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Collects siblings
- *
- * @private
- * @param {Node} node Node to collect siblings from.
- * @param {String} name Name of the sibling to check for.
- * @param {Node} end_node
- * @return {Array} Array of collected siblings.
- */
- function collectSiblings(node, name, end_node) {
- var siblings = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return nodes;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (; node && node != end_node; node = node[name]) {
- siblings.push(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Collects siblings
+ *
+ * @private
+ * @param {Node} node Node to collect siblings from.
+ * @param {String} name Name of the sibling to check for.
+ * @param {Node} endNode
+ * @return {Array} Array of collected siblings.
+ */
+ function collectSiblings(node, name, endNode) {
+ var siblings = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return siblings;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (; node && node != endNode; node = node[name]) {
+ siblings.push(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Find an end point this is the node just before the common ancestor root.
- *
- * @private
- * @param {Node} node Node to start at.
- * @param {Node} root Root/ancestor element to stop just before.
- * @return {Node} Node just before the root element.
- */
- function findEndPoint(node, root) {
- do {
- if (node.parentNode == root) {
- return node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return siblings;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.parentNode;
- } while (node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Find an end point this is the node just before the common ancestor root.
+ *
+ * @private
+ * @param {Node} node Node to start at.
+ * @param {Node} root Root/ancestor element to stop just before.
+ * @return {Node} Node just before the root element.
+ */
+ function findEndPoint(node, root) {
+ do {
+ if (node.parentNode == root) {
+ return node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function walkBoundary(start_node, end_node, next) {
- var siblingName = next ? 'nextSibling' : 'previousSibling';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node.parentNode;
+ } while (node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (node = start_node, parent = node.parentNode; node && node != end_node; node = parent) {
- parent = node.parentNode;
- siblings = collectSiblings(node == start_node ? node : node[siblingName], siblingName);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function walkBoundary(startNode, endNode, next) {
+ var siblingName = next ? 'nextSibling' : 'previousSibling';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (siblings.length) {
- if (!next) {
- siblings.reverse();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (node = startNode, parent = node.parentNode; node && node != endNode; node = parent) {
+ parent = node.parentNode;
+ siblings = collectSiblings(node == startNode ? node : node[siblingName], siblingName);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- callback(exclude(siblings));
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (siblings.length) {
+ if (!next) {
+ siblings.reverse();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If index based start position then resolve it
- if (startContainer.nodeType == 1 && startContainer.hasChildNodes()) {
- startContainer = startContainer.childNodes[startOffset];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ callback(exclude(siblings));
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If index based end position then resolve it
- if (endContainer.nodeType == 1 && endContainer.hasChildNodes()) {
- endContainer = getEndChild(endContainer, endOffset);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If index based start position then resolve it
+ if (startContainer.nodeType == 1 && startContainer.hasChildNodes()) {
+ startContainer = startContainer.childNodes[startOffset];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Same container
- if (startContainer == endContainer) {
- return callback(exclude([startContainer]));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If index based end position then resolve it
+ if (endContainer.nodeType == 1 && endContainer.hasChildNodes()) {
+ endContainer = getEndChild(endContainer, endOffset);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Find common ancestor and end points
- ancestor = dom.findCommonAncestor(startContainer, endContainer);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Same container
+ if (startContainer == endContainer) {
+ return callback(exclude([startContainer]));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Process left side
- for (node = startContainer; node; node = node.parentNode) {
- if (node === endContainer) {
- return walkBoundary(startContainer, ancestor, true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find common ancestor and end points
+ ancestor = dom.findCommonAncestor(startContainer, endContainer);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node === ancestor) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Process left side
+ for (node = startContainer; node; node = node.parentNode) {
+ if (node === endContainer) {
+ return walkBoundary(startContainer, ancestor, true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Process right side
- for (node = endContainer; node; node = node.parentNode) {
- if (node === startContainer) {
- return walkBoundary(endContainer, ancestor);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node === ancestor) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node === ancestor) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Process right side
+ for (node = endContainer; node; node = node.parentNode) {
+ if (node === startContainer) {
+ return walkBoundary(endContainer, ancestor);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Find start/end point
- startPoint = findEndPoint(startContainer, ancestor) || startContainer;
- endPoint = findEndPoint(endContainer, ancestor) || endContainer;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node === ancestor) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Walk left leaf
- walkBoundary(startContainer, startPoint, true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find start/end point
+ startPoint = findEndPoint(startContainer, ancestor) || startContainer;
+ endPoint = findEndPoint(endContainer, ancestor) || endContainer;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Walk the middle from start to end point
- siblings = collectSiblings(
- startPoint == startContainer ? startPoint : startPoint.nextSibling,
- 'nextSibling',
- endPoint == endContainer ? endPoint.nextSibling : endPoint
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Walk left leaf
+ walkBoundary(startContainer, startPoint, true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (siblings.length) {
- callback(exclude(siblings));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Walk the middle from start to end point
+ siblings = collectSiblings(
+ startPoint == startContainer ? startPoint : startPoint.nextSibling,
+ 'nextSibling',
+ endPoint == endContainer ? endPoint.nextSibling : endPoint
+ );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Walk right leaf
- walkBoundary(endContainer, endPoint);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (siblings.length) {
+ callback(exclude(siblings));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Splits the specified range at it's start/end points.
- *
- * @private
- * @param {Range/RangeObject} rng Range to split.
- * @return {Object} Range position object.
- */
- this.split = function(rng) {
- var startContainer = rng.startContainer,
- startOffset = rng.startOffset,
- endContainer = rng.endContainer,
- endOffset = rng.endOffset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Walk right leaf
+ walkBoundary(endContainer, endPoint);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function splitText(node, offset) {
- return node.splitText(offset);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Splits the specified range at it's start/end points.
+ *
+ * @private
+ * @param {Range/RangeObject} rng Range to split.
+ * @return {Object} Range position object.
+ */
+ this.split = function (rng) {
+ var startContainer = rng.startContainer,
+ startOffset = rng.startOffset,
+ endContainer = rng.endContainer,
+ endOffset = rng.endOffset;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle single text node
- if (startContainer == endContainer && startContainer.nodeType == 3) {
- if (startOffset > 0 && startOffset < startContainer.nodeValue.length) {
- endContainer = splitText(startContainer, startOffset);
- startContainer = endContainer.previousSibling;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function splitText(node, offset) {
+ return node.splitText(offset);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (endOffset > startOffset) {
- endOffset = endOffset - startOffset;
- startContainer = endContainer = splitText(endContainer, endOffset).previousSibling;
- endOffset = endContainer.nodeValue.length;
- startOffset = 0;
- } else {
- endOffset = 0;
- }
- }
- } else {
- // Split startContainer text node if needed
- if (startContainer.nodeType == 3 && startOffset > 0 && startOffset < startContainer.nodeValue.length) {
- startContainer = splitText(startContainer, startOffset);
- startOffset = 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handle single text node
+ if (startContainer == endContainer && startContainer.nodeType == 3) {
+ if (startOffset > 0 && startOffset < startContainer.nodeValue.length) {
+ endContainer = splitText(startContainer, startOffset);
+ startContainer = endContainer.previousSibling;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Split endContainer text node if needed
- if (endContainer.nodeType == 3 && endOffset > 0 && endOffset < endContainer.nodeValue.length) {
- endContainer = splitText(endContainer, endOffset).previousSibling;
- endOffset = endContainer.nodeValue.length;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (endOffset > startOffset) {
+ endOffset = endOffset - startOffset;
+ startContainer = endContainer = splitText(endContainer, endOffset).previousSibling;
+ endOffset = endContainer.nodeValue.length;
+ startOffset = 0;
+ } else {
+ endOffset = 0;
+ }
+ }
+ } else {
+ // Split startContainer text node if needed
+ if (startContainer.nodeType == 3 && startOffset > 0 && startOffset < startContainer.nodeValue.length) {
+ startContainer = splitText(startContainer, startOffset);
+ startOffset = 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- startContainer: startContainer,
- startOffset: startOffset,
- endContainer: endContainer,
- endOffset: endOffset
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Split endContainer text node if needed
+ if (endContainer.nodeType == 3 && endOffset > 0 && endOffset < endContainer.nodeValue.length) {
+ endContainer = splitText(endContainer, endOffset).previousSibling;
+ endOffset = endContainer.nodeValue.length;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Normalizes the specified range by finding the closest best suitable caret location.
- *
- * @private
- * @param {Range} rng Range to normalize.
- * @return {Boolean} True/false if the specified range was normalized or not.
- */
- this.normalize = function(rng) {
- var normalized, collapsed;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ startContainer: startContainer,
+ startOffset: startOffset,
+ endContainer: endContainer,
+ endOffset: endOffset
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function normalizeEndPoint(start) {
- var container, offset, walker, body = dom.getRoot(), node, nonEmptyElementsMap;
- var directionLeft, isAfterNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Normalizes the specified range by finding the closest best suitable caret location.
+ *
+ * @private
+ * @param {Range} rng Range to normalize.
+ * @return {Boolean} True/false if the specified range was normalized or not.
+ */
+ this.normalize = function (rng) {
+ var normalized = false, collapsed;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isTableCell(node) {
- return node && /^(TD|TH|CAPTION)$/.test(node.nodeName);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function normalizeEndPoint(start) {
+ var container, offset, walker, body = dom.getRoot(), node, nonEmptyElementsMap;
+ var directionLeft, isAfterNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hasBrBeforeAfter(node, left) {
- var walker = new TreeWalker(node, dom.getParent(node.parentNode, dom.isBlock) || body);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isTableCell(node) {
+ return node && /^(TD|TH|CAPTION)$/.test(node.nodeName);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while ((node = walker[left ? 'prev' : 'next']())) {
- if (node.nodeName === "BR") {
- return true;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hasBrBeforeAfter(node, left) {
+ var walker = new TreeWalker(node, dom.getParent(node.parentNode, dom.isBlock) || body);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hasContentEditableFalseParent(node) {
- while (node && node != body) {
- if (isContentEditableFalse(node)) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while ((node = walker[left ? 'prev' : 'next']())) {
+ if (node.nodeName === "BR") {
+ return true;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hasContentEditableFalseParent(node) {
+ while (node && node != body) {
+ if (isContentEditableFalse(node)) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isPrevNode(node, name) {
- return node.previousSibling && node.previousSibling.nodeName == name;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Walks the dom left/right to find a suitable text node to move the endpoint into
- // It will only walk within the current parent block or body and will stop if it hits a block or a BR/IMG
- function findTextNodeRelative(left, startNode) {
- var walker, lastInlineElement, parentBlockContainer;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isPrevNode(node, name) {
+ return node.previousSibling && node.previousSibling.nodeName == name;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- startNode = startNode || container;
- parentBlockContainer = dom.getParent(startNode.parentNode, dom.isBlock) || body;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Walks the dom left/right to find a suitable text node to move the endpoint into
+ // It will only walk within the current parent block or body and will stop if it hits a block or a BR/IMG
+ function findTextNodeRelative(left, startNode) {
+ var walker, lastInlineElement, parentBlockContainer;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Lean left before the BR element if it's the only BR within a block element. Gecko bug: #6680
- // This: <p><br>|</p> becomes <p>|<br></p>
- if (left && startNode.nodeName == 'BR' && isAfterNode && dom.isEmpty(parentBlockContainer)) {
- container = startNode.parentNode;
- offset = dom.nodeIndex(startNode);
- normalized = true;
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ startNode = startNode || container;
+ parentBlockContainer = dom.getParent(startNode.parentNode, dom.isBlock) || body;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Walk left until we hit a text node we can move to or a block/br/img
- walker = new TreeWalker(startNode, parentBlockContainer);
- while ((node = walker[left ? 'prev' : 'next']())) {
- // Break if we hit a non content editable node
- if (dom.getContentEditableParent(node) === "false" || isCeFalseCaretContainer(node, dom.getRoot())) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Lean left before the BR element if it's the only BR within a block element. Gecko bug: #6680
+ // This: <p><br>|</p> becomes <p>|<br></p>
+ if (left && startNode.nodeName == 'BR' && isAfterNode && dom.isEmpty(parentBlockContainer)) {
+ container = startNode.parentNode;
+ offset = dom.nodeIndex(startNode);
+ normalized = true;
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Found text node that has a length
- if (node.nodeType === 3 && node.nodeValue.length > 0) {
- container = node;
- offset = left ? node.nodeValue.length : 0;
- normalized = true;
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Walk left until we hit a text node we can move to or a block/br/img
+ walker = new TreeWalker(startNode, parentBlockContainer);
+ while ((node = walker[left ? 'prev' : 'next']())) {
+ // Break if we hit a non content editable node
+ if (dom.getContentEditableParent(node) === "false" || isCeFalseCaretContainer(node, dom.getRoot())) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Break if we find a block or a BR/IMG/INPUT etc
- if (dom.isBlock(node) || nonEmptyElementsMap[node.nodeName.toLowerCase()]) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Found text node that has a length
+ if (node.nodeType === 3 && node.nodeValue.length > 0) {
+ if (hasParentWithName(node, body, 'A') === false) {
+ container = node;
+ offset = left ? node.nodeValue.length : 0;
+ normalized = true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- lastInlineElement = node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Only fetch the last inline element when in caret mode for now
- if (collapsed && lastInlineElement) {
- container = lastInlineElement;
- normalized = true;
- offset = 0;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Break if we find a block or a BR/IMG/INPUT etc
+ if (dom.isBlock(node) || nonEmptyElementsMap[node.nodeName.toLowerCase()]) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = rng[(start ? 'start' : 'end') + 'Container'];
- offset = rng[(start ? 'start' : 'end') + 'Offset'];
- isAfterNode = container.nodeType == 1 && offset === container.childNodes.length;
- nonEmptyElementsMap = dom.schema.getNonEmptyElements();
- directionLeft = start;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ lastInlineElement = node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isCaretContainer(container)) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Only fetch the last inline element when in caret mode for now
+ if (collapsed && lastInlineElement) {
+ container = lastInlineElement;
+ normalized = true;
+ offset = 0;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (container.nodeType == 1 && offset > container.childNodes.length - 1) {
- directionLeft = false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = rng[(start ? 'start' : 'end') + 'Container'];
+ offset = rng[(start ? 'start' : 'end') + 'Offset'];
+ isAfterNode = container.nodeType == 1 && offset === container.childNodes.length;
+ nonEmptyElementsMap = dom.schema.getNonEmptyElements();
+ directionLeft = start;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If the container is a document move it to the body element
- if (container.nodeType === 9) {
- container = dom.getRoot();
- offset = 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isCaretContainer(container)) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If the container is body try move it into the closest text node or position
- if (container === body) {
- // If start is before/after a image, table etc
- if (directionLeft) {
- node = container.childNodes[offset > 0 ? offset - 1 : 0];
- if (node) {
- if (isCaretContainer(node)) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (container.nodeType == 1 && offset > container.childNodes.length - 1) {
+ directionLeft = false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (nonEmptyElementsMap[node.nodeName] || node.nodeName == "TABLE") {
- return;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If the container is a document move it to the body element
+ if (container.nodeType === 9) {
+ container = dom.getRoot();
+ offset = 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Resolve the index
- if (container.hasChildNodes()) {
- offset = Math.min(!directionLeft && offset > 0 ? offset - 1 : offset, container.childNodes.length - 1);
- container = container.childNodes[offset];
- offset = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If the container is body try move it into the closest text node or position
+ if (container === body) {
+ // If start is before/after a image, table etc
+ if (directionLeft) {
+ node = container.childNodes[offset > 0 ? offset - 1 : 0];
+ if (node) {
+ if (isCaretContainer(node)) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Don't normalize non collapsed selections like <p>[a</p><table></table>]
- if (!collapsed && container === body.lastChild && container.nodeName === 'TABLE') {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (nonEmptyElementsMap[node.nodeName] || node.nodeName == "TABLE") {
+ return;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (hasContentEditableFalseParent(container) || isCaretContainer(container)) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Resolve the index
+ if (container.hasChildNodes()) {
+ offset = Math.min(!directionLeft && offset > 0 ? offset - 1 : offset, container.childNodes.length - 1);
+ container = container.childNodes[offset];
+ offset = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Don't walk into elements that doesn't have any child nodes like a IMG
- if (container.hasChildNodes() && !/TABLE/.test(container.nodeName)) {
- // Walk the DOM to find a text node to place the caret at or a BR
- node = container;
- walker = new TreeWalker(container, body);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't normalize non collapsed selections like <p>[a</p><table></table>]
+ if (!collapsed && container === body.lastChild && container.nodeName === 'TABLE') {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- do {
- if (isContentEditableFalse(node) || isCaretContainer(node)) {
- normalized = false;
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (hasContentEditableFalseParent(container) || isCaretContainer(container)) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Found a text node use that position
- if (node.nodeType === 3 && node.nodeValue.length > 0) {
- offset = directionLeft ? 0 : node.nodeValue.length;
- container = node;
- normalized = true;
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't walk into elements that doesn't have any child nodes like a IMG
+ if (container.hasChildNodes() && !/TABLE/.test(container.nodeName)) {
+ // Walk the DOM to find a text node to place the caret at or a BR
+ node = container;
+ walker = new TreeWalker(container, body);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Found a BR/IMG element that we can place the caret before
- if (nonEmptyElementsMap[node.nodeName.toLowerCase()] && !isTableCell(node)) {
- offset = dom.nodeIndex(node);
- container = node.parentNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ do {
+ if (isContentEditableFalse(node) || isCaretContainer(node)) {
+ normalized = false;
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Put caret after image when moving the end point
- if (node.nodeName == "IMG" && !directionLeft) {
- offset++;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Found a text node use that position
+ if (node.nodeType === 3 && node.nodeValue.length > 0) {
+ offset = directionLeft ? 0 : node.nodeValue.length;
+ container = node;
+ normalized = true;
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- normalized = true;
- break;
- }
- } while ((node = (directionLeft ? walker.next() : walker.prev())));
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Found a BR/IMG element that we can place the caret before
+ if (nonEmptyElementsMap[node.nodeName.toLowerCase()] && !isTableCell(node)) {
+ offset = dom.nodeIndex(node);
+ container = node.parentNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Lean the caret to the left if possible
- if (collapsed) {
- // So this: <b>x</b><i>|x</i>
- // Becomes: <b>x|</b><i>x</i>
- // Seems that only gecko has issues with this
- if (container.nodeType === 3 && offset === 0) {
- findTextNodeRelative(true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Put caret after image when moving the end point
+ if (node.nodeName == "IMG" && !directionLeft) {
+ offset++;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Lean left into empty inline elements when the caret is before a BR
- // So this: <i><b></b><i>|<br></i>
- // Becomes: <i><b>|</b><i><br></i>
- // Seems that only gecko has issues with this.
- // Special edge case for <p><a>x</a>|<br></p> since we don't want <p><a>x|</a><br></p>
- if (container.nodeType === 1) {
- node = container.childNodes[offset];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ normalized = true;
+ break;
+ }
+ } while ((node = (directionLeft ? walker.next() : walker.prev())));
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Offset is after the containers last child
- // then use the previous child for normalization
- if (!node) {
- node = container.childNodes[offset - 1];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Lean the caret to the left if possible
+ if (collapsed) {
+ // So this: <b>x</b><i>|x</i>
+ // Becomes: <b>x|</b><i>x</i>
+ // Seems that only gecko has issues with this
+ if (container.nodeType === 3 && offset === 0) {
+ findTextNodeRelative(true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node && node.nodeName === 'BR' && !isPrevNode(node, 'A') &&
- !hasBrBeforeAfter(node) && !hasBrBeforeAfter(node, true)) {
- findTextNodeRelative(true, node);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Lean left into empty inline elements when the caret is before a BR
+ // So this: <i><b></b><i>|<br></i>
+ // Becomes: <i><b>|</b><i><br></i>
+ // Seems that only gecko has issues with this.
+ // Special edge case for <p><a>x</a>|<br></p> since we don't want <p><a>x|</a><br></p>
+ if (container.nodeType === 1) {
+ node = container.childNodes[offset];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Lean the start of the selection right if possible
- // So this: x[<b>x]</b>
- // Becomes: x<b>[x]</b>
- if (directionLeft && !collapsed && container.nodeType === 3 && offset === container.nodeValue.length) {
- findTextNodeRelative(false);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Offset is after the containers last child
+ // then use the previous child for normalization
+ if (!node) {
+ node = container.childNodes[offset - 1];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set endpoint if it was normalized
- if (normalized) {
- rng['set' + (start ? 'Start' : 'End')](container, offset);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node && node.nodeName === 'BR' && !isPrevNode(node, 'A') &&
+ !hasBrBeforeAfter(node) && !hasBrBeforeAfter(node, true)) {
+ findTextNodeRelative(true, node);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- collapsed = rng.collapsed;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Lean the start of the selection right if possible
+ // So this: x[<b>x]</b>
+ // Becomes: x<b>[x]</b>
+ if (directionLeft && !collapsed && container.nodeType === 3 && offset === container.nodeValue.length) {
+ findTextNodeRelative(false);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- normalizeEndPoint(true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set endpoint if it was normalized
+ if (normalized) {
+ rng['set' + (start ? 'Start' : 'End')](container, offset);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!collapsed) {
- normalizeEndPoint();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ collapsed = rng.collapsed;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If it was collapsed then make sure it still is
- if (normalized && collapsed) {
- rng.collapse(true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ normalizeEndPoint(true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return normalized;
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!collapsed) {
+ normalizeEndPoint();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Compares two ranges and checks if they are equal.
- *
- * @static
- * @method compareRanges
- * @param {DOMRange} rng1 First range to compare.
- * @param {DOMRange} rng2 First range to compare.
- * @return {Boolean} true/false if the ranges are equal.
- */
- RangeUtils.compareRanges = function(rng1, rng2) {
- if (rng1 && rng2) {
- // Compare native IE ranges
- if (rng1.item || rng1.duplicate) {
- // Both are control ranges and the selected element matches
- if (rng1.item && rng2.item && rng1.item(0) === rng2.item(0)) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If it was collapsed then make sure it still is
+ if (normalized && collapsed) {
+ rng.collapse(true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Both are text ranges and the range matches
- if (rng1.isEqual && rng2.isEqual && rng2.isEqual(rng1)) {
- return true;
- }
- } else {
- // Compare w3c ranges
- return rng1.startContainer == rng2.startContainer && rng1.startOffset == rng2.startOffset;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return normalized;
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Compares two ranges and checks if they are equal.
+ *
+ * @static
+ * @method compareRanges
+ * @param {DOMRange} rng1 First range to compare.
+ * @param {DOMRange} rng2 First range to compare.
+ * @return {Boolean} true/false if the ranges are equal.
+ */
+ RangeUtils.compareRanges = function (rng1, rng2) {
+ if (rng1 && rng2) {
+ // Compare native IE ranges
+ if (rng1.item || rng1.duplicate) {
+ // Both are control ranges and the selected element matches
+ if (rng1.item && rng2.item && rng1.item(0) === rng2.item(0)) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Finds the closest selection rect tries to get the range from that.
- */
- function findClosestIeRange(clientX, clientY, doc) {
- var element, rng, rects;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Both are text ranges and the range matches
+ if (rng1.isEqual && rng2.isEqual && rng2.isEqual(rng1)) {
+ return true;
+ }
+ } else {
+ // Compare w3c ranges
+ return rng1.startContainer == rng2.startContainer && rng1.startOffset == rng2.startOffset;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- element = doc.elementFromPoint(clientX, clientY);
- rng = doc.body.createTextRange();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!element || element.tagName == 'HTML') {
- element = doc.body;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Finds the closest selection rect tries to get the range from that.
+ */
+ function findClosestIeRange(clientX, clientY, doc) {
+ var element, rng, rects;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng.moveToElementText(element);
- rects = Tools.toArray(rng.getClientRects());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ element = doc.elementFromPoint(clientX, clientY);
+ rng = doc.body.createTextRange();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rects = rects.sort(function(a, b) {
- a = Math.abs(Math.max(a.top - clientY, a.bottom - clientY));
- b = Math.abs(Math.max(b.top - clientY, b.bottom - clientY));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!element || element.tagName == 'HTML') {
+ element = doc.body;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return a - b;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng.moveToElementText(element);
+ rects = Tools.toArray(rng.getClientRects());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rects.length > 0) {
- clientY = (rects[0].bottom + rects[0].top) / 2;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rects = rects.sort(function (a, b) {
+ a = Math.abs(Math.max(a.top - clientY, a.bottom - clientY));
+ b = Math.abs(Math.max(b.top - clientY, b.bottom - clientY));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- try {
- rng.moveToPoint(clientX, clientY);
- rng.collapse(true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return a - b;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return rng;
- } catch (ex) {
- // At least we tried
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rects.length > 0) {
+ clientY = (rects[0].bottom + rects[0].top) / 2;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ try {
+ rng.moveToPoint(clientX, clientY);
+ rng.collapse(true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function moveOutOfContentEditableFalse(rng, rootNode) {
- var parentElement = rng && rng.parentElement ? rng.parentElement() : null;
- return isContentEditableFalse(findParent(parentElement, rootNode, hasCeProperty)) ? null : rng;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return rng;
+ } catch (ex) {
+ // At least we tried
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Gets the caret range for the given x/y location.
- *
- * @static
- * @method getCaretRangeFromPoint
- * @param {Number} clientX X coordinate for range
- * @param {Number} clientY Y coordinate for range
- * @param {Document} doc Document that x/y are relative to
- * @returns {Range} caret range
- */
- RangeUtils.getCaretRangeFromPoint = function(clientX, clientY, doc) {
- var rng, point;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (doc.caretPositionFromPoint) {
- point = doc.caretPositionFromPoint(clientX, clientY);
- rng = doc.createRange();
- rng.setStart(point.offsetNode, point.offset);
- rng.collapse(true);
- } else if (doc.caretRangeFromPoint) {
- rng = doc.caretRangeFromPoint(clientX, clientY);
- } else if (doc.body.createTextRange) {
- rng = doc.body.createTextRange();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function moveOutOfContentEditableFalse(rng, rootNode) {
+ var parentElement = rng && rng.parentElement ? rng.parentElement() : null;
+ return isContentEditableFalse(findParent(parentElement, rootNode, hasCeProperty)) ? null : rng;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- try {
- rng.moveToPoint(clientX, clientY);
- rng.collapse(true);
- } catch (ex) {
- rng = findClosestIeRange(clientX, clientY, doc);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Gets the caret range for the given x/y location.
+ *
+ * @static
+ * @method getCaretRangeFromPoint
+ * @param {Number} clientX X coordinate for range
+ * @param {Number} clientY Y coordinate for range
+ * @param {Document} doc Document that x/y are relative to
+ * @returns {Range} caret range
+ */
+ RangeUtils.getCaretRangeFromPoint = function (clientX, clientY, doc) {
+ var rng, point;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return moveOutOfContentEditableFalse(rng, doc.body);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (doc.caretPositionFromPoint) {
+ point = doc.caretPositionFromPoint(clientX, clientY);
+ rng = doc.createRange();
+ rng.setStart(point.offsetNode, point.offset);
+ rng.collapse(true);
+ } else if (doc.caretRangeFromPoint) {
+ rng = doc.caretRangeFromPoint(clientX, clientY);
+ } else if (doc.body.createTextRange) {
+ rng = doc.body.createTextRange();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return rng;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ try {
+ rng.moveToPoint(clientX, clientY);
+ rng.collapse(true);
+ } catch (ex) {
+ rng = findClosestIeRange(clientX, clientY, doc);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- RangeUtils.getSelectedNode = function(range) {
- var startContainer = range.startContainer,
- startOffset = range.startOffset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return moveOutOfContentEditableFalse(rng, doc.body);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (startContainer.hasChildNodes() && range.endOffset == startOffset + 1) {
- return startContainer.childNodes[startOffset];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return rng;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ RangeUtils.getSelectedNode = function (range) {
+ var startContainer = range.startContainer,
+ startOffset = range.startOffset;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- RangeUtils.getNode = function(container, offset) {
- if (container.nodeType == 1 && container.hasChildNodes()) {
- if (offset >= container.childNodes.length) {
- offset = container.childNodes.length - 1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (startContainer.hasChildNodes() && range.endOffset == startOffset + 1) {
+ return startContainer.childNodes[startOffset];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = container.childNodes[offset];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return container;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ RangeUtils.getNode = function (container, offset) {
+ if (container.nodeType == 1 && container.hasChildNodes()) {
+ if (offset >= container.childNodes.length) {
+ offset = container.childNodes.length - 1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return RangeUtils;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = container.childNodes[offset];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/NodeChange.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return container;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * NodeChange.js
- *
- * Released under LGPL License.
- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return RangeUtils;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * This class handles the nodechange event dispatching both manual and through selection change events.
- *
- * @class tinymce.NodeChange
- * @private
- */
-define("tinymce/NodeChange", [
- "tinymce/dom/RangeUtils",
- "tinymce/Env",
- "tinymce/util/Delay"
-], function(RangeUtils, Env, Delay) {
- return function(editor) {
- var lastRng, lastPath = [];
-
- /**
- * Returns true/false if the current element path has been changed or not.
- *
- * @private
- * @return {Boolean} True if the element path is the same false if it's not.
- */
- function isSameElementPath(startElm) {
- var i, currentPath;
-
- currentPath = editor.$(startElm).parentsUntil(editor.getBody()).add(startElm);
- if (currentPath.length === lastPath.length) {
- for (i = currentPath.length; i >= 0; i--) {
- if (currentPath[i] !== lastPath[i]) {
- break;
- }
- }
-
- if (i === -1) {
- lastPath = currentPath;
- return true;
- }
- }
-
- lastPath = currentPath;
-
- return false;
- }
-
- // Gecko doesn't support the "selectionchange" event
- if (!('onselectionchange' in editor.getDoc())) {
- editor.on('NodeChange Click MouseUp KeyUp Focus', function(e) {
- var nativeRng, fakeRng;
-
- // Since DOM Ranges mutate on modification
- // of the DOM we need to clone it's contents
- nativeRng = editor.selection.getRng();
- fakeRng = {
- startContainer: nativeRng.startContainer,
- startOffset: nativeRng.startOffset,
- endContainer: nativeRng.endContainer,
- endOffset: nativeRng.endOffset
- };
-
- // Always treat nodechange as a selectionchange since applying
- // formatting to the current range wouldn't update the range but it's parent
- if (e.type == 'nodechange' || !RangeUtils.compareRanges(fakeRng, lastRng)) {
- editor.fire('SelectionChange');
- }
-
- lastRng = fakeRng;
- });
- }
-
- // IE has a bug where it fires a selectionchange on right click that has a range at the start of the body
- // When the contextmenu event fires the selection is located at the right location
- editor.on('contextmenu', function() {
- editor.fire('SelectionChange');
- });
-
- // Selection change is delayed ~200ms on IE when you click inside the current range
- editor.on('SelectionChange', function() {
- var startElm = editor.selection.getStart(true);
-
- // IE 8 will fire a selectionchange event with an incorrect selection
- // when focusing out of table cells. Click inside cell -> toolbar = Invalid SelectionChange event
- if (!Env.range && editor.selection.isCollapsed()) {
- return;
- }
-
- if (!isSameElementPath(startElm) && editor.dom.isChildOf(startElm, editor.getBody())) {
- editor.nodeChanged({selectionChange: true});
- }
- });
-
- // Fire an extra nodeChange on mouseup for compatibility reasons
- editor.on('MouseUp', function(e) {
- if (!e.isDefaultPrevented()) {
- // Delay nodeChanged call for WebKit edge case issue where the range
- // isn't updated until after you click outside a selected image
- if (editor.selection.getNode().nodeName == 'IMG') {
- Delay.setEditorTimeout(editor, function() {
- editor.nodeChanged();
- });
- } else {
- editor.nodeChanged();
- }
- }
- });
-
- /**
- * Dispatches out a onNodeChange event to all observers. This method should be called when you
- * need to update the UI states or element path etc.
- *
- * @method nodeChanged
- * @param {Object} args Optional args to pass to NodeChange event handlers.
- */
- this.nodeChanged = function(args) {
- var selection = editor.selection, node, parents, root;
-
- // Fix for bug #1896577 it seems that this can not be fired while the editor is loading
- if (editor.initialized && selection && !editor.settings.disable_nodechange && !editor.readonly) {
- // Get start node
- root = editor.getBody();
- node = selection.getStart() || root;
-
- // Make sure the node is within the editor root or is the editor root
- if (node.ownerDocument != editor.getDoc() || !editor.dom.isChildOf(node, root)) {
- node = root;
- }
-
- // Edge case for <p>|<img></p>
- if (node.nodeName == 'IMG' && selection.isCollapsed()) {
- node = node.parentNode;
- }
-
- // Get parents and add them to object
- parents = [];
- editor.dom.getParent(node, function(node) {
- if (node === root) {
- return true;
- }
-
- parents.push(node);
- });
-
- args = args || {};
- args.element = node;
- args.parents = parents;
-
- editor.fire('NodeChange', args);
- }
- };
- };
-});
-
-// Included from: js/tinymce/classes/html/Node.js
-
-/**
</del><span class="cx" style="display: block; padding: 0 10px"> * Node.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -11169,1526 +13101,502 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.html.Node
</span><span class="cx" style="display: block; padding: 0 10px"> * @version 3.4
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/html/Node", [], function() {
- var whiteSpaceRegExp = /^[ \t\r\n]*$/, typeLookup = {
- '#text': 3,
- '#comment': 8,
- '#cdata': 4,
- '#pi': 7,
- '#doctype': 10,
- '#document-fragment': 11
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.html.Node',
+ [
+ ],
+ function () {
+ var whiteSpaceRegExp = /^[ \t\r\n]*$/;
+ var typeLookup = {
+ '#text': 3,
+ '#comment': 8,
+ '#cdata': 4,
+ '#pi': 7,
+ '#doctype': 10,
+ '#document-fragment': 11
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Walks the tree left/right
- function walk(node, root_node, prev) {
- var sibling, parent, startName = prev ? 'lastChild' : 'firstChild', siblingName = prev ? 'prev' : 'next';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Walks the tree left/right
+ function walk(node, rootNode, prev) {
+ var sibling, parent, startName = prev ? 'lastChild' : 'firstChild', siblingName = prev ? 'prev' : 'next';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Walk into nodes if it has a start
- if (node[startName]) {
- return node[startName];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Walk into nodes if it has a start
+ if (node[startName]) {
+ return node[startName];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Return the sibling if it has one
- if (node !== root_node) {
- sibling = node[siblingName];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Return the sibling if it has one
+ if (node !== rootNode) {
+ sibling = node[siblingName];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (sibling) {
- return sibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (sibling) {
+ return sibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Walk up the parents to look for siblings
- for (parent = node.parent; parent && parent !== root_node; parent = parent.parent) {
- sibling = parent[siblingName];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Walk up the parents to look for siblings
+ for (parent = node.parent; parent && parent !== rootNode; parent = parent.parent) {
+ sibling = parent[siblingName];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (sibling) {
- return sibling;
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (sibling) {
+ return sibling;
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a new Node instance.
- *
- * @constructor
- * @method Node
- * @param {String} name Name of the node type.
- * @param {Number} type Numeric type representing the node.
- */
- function Node(name, type) {
- this.name = name;
- this.type = type;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a new Node instance.
+ *
+ * @constructor
+ * @method Node
+ * @param {String} name Name of the node type.
+ * @param {Number} type Numeric type representing the node.
+ */
+ function Node(name, type) {
+ this.name = name;
+ this.type = type;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (type === 1) {
- this.attributes = [];
- this.attributes.map = {};
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (type === 1) {
+ this.attributes = [];
+ this.attributes.map = {};
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Node.prototype = {
- /**
- * Replaces the current node with the specified one.
- *
- * @example
- * someNode.replace(someNewNode);
- *
- * @method replace
- * @param {tinymce.html.Node} node Node to replace the current node with.
- * @return {tinymce.html.Node} The old node that got replaced.
- */
- replace: function(node) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Node.prototype = {
+ /**
+ * Replaces the current node with the specified one.
+ *
+ * @example
+ * someNode.replace(someNewNode);
+ *
+ * @method replace
+ * @param {tinymce.html.Node} node Node to replace the current node with.
+ * @return {tinymce.html.Node} The old node that got replaced.
+ */
+ replace: function (node) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.parent) {
- node.remove();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.parent) {
+ node.remove();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.insert(node, self);
- self.remove();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.insert(node, self);
+ self.remove();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Gets/sets or removes an attribute by name.
- *
- * @example
- * someNode.attr("name", "value"); // Sets an attribute
- * console.log(someNode.attr("name")); // Gets an attribute
- * someNode.attr("name", null); // Removes an attribute
- *
- * @method attr
- * @param {String} name Attribute name to set or get.
- * @param {String} value Optional value to set.
- * @return {String/tinymce.html.Node} String or undefined on a get operation or the current node on a set operation.
- */
- attr: function(name, value) {
- var self = this, attrs, i, undef;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Gets/sets or removes an attribute by name.
+ *
+ * @example
+ * someNode.attr("name", "value"); // Sets an attribute
+ * console.log(someNode.attr("name")); // Gets an attribute
+ * someNode.attr("name", null); // Removes an attribute
+ *
+ * @method attr
+ * @param {String} name Attribute name to set or get.
+ * @param {String} value Optional value to set.
+ * @return {String/tinymce.html.Node} String or undefined on a get operation or the current node on a set operation.
+ */
+ attr: function (name, value) {
+ var self = this, attrs, i, undef;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof name !== "string") {
- for (i in name) {
- self.attr(i, name[i]);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof name !== "string") {
+ for (i in name) {
+ self.attr(i, name[i]);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ((attrs = self.attributes)) {
- if (value !== undef) {
- // Remove attribute
- if (value === null) {
- if (name in attrs.map) {
- delete attrs.map[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((attrs = self.attributes)) {
+ if (value !== undef) {
+ // Remove attribute
+ if (value === null) {
+ if (name in attrs.map) {
+ delete attrs.map[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- i = attrs.length;
- while (i--) {
- if (attrs[i].name === name) {
- attrs = attrs.splice(i, 1);
- return self;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ i = attrs.length;
+ while (i--) {
+ if (attrs[i].name === name) {
+ attrs = attrs.splice(i, 1);
+ return self;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set attribute
- if (name in attrs.map) {
- // Set attribute
- i = attrs.length;
- while (i--) {
- if (attrs[i].name === name) {
- attrs[i].value = value;
- break;
- }
- }
- } else {
- attrs.push({name: name, value: value});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set attribute
+ if (name in attrs.map) {
+ // Set attribute
+ i = attrs.length;
+ while (i--) {
+ if (attrs[i].name === name) {
+ attrs[i].value = value;
+ break;
+ }
+ }
+ } else {
+ attrs.push({ name: name, value: value });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- attrs.map[name] = value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ attrs.map[name] = value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return attrs.map[name];
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return attrs.map[name];
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Does a shallow clones the node into a new node. It will also exclude id attributes since
- * there should only be one id per document.
- *
- * @example
- * var clonedNode = node.clone();
- *
- * @method clone
- * @return {tinymce.html.Node} New copy of the original node.
- */
- clone: function() {
- var self = this, clone = new Node(self.name, self.type), i, l, selfAttrs, selfAttr, cloneAttrs;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Does a shallow clones the node into a new node. It will also exclude id attributes since
+ * there should only be one id per document.
+ *
+ * @example
+ * var clonedNode = node.clone();
+ *
+ * @method clone
+ * @return {tinymce.html.Node} New copy of the original node.
+ */
+ clone: function () {
+ var self = this, clone = new Node(self.name, self.type), i, l, selfAttrs, selfAttr, cloneAttrs;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Clone element attributes
- if ((selfAttrs = self.attributes)) {
- cloneAttrs = [];
- cloneAttrs.map = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Clone element attributes
+ if ((selfAttrs = self.attributes)) {
+ cloneAttrs = [];
+ cloneAttrs.map = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0, l = selfAttrs.length; i < l; i++) {
- selfAttr = selfAttrs[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0, l = selfAttrs.length; i < l; i++) {
+ selfAttr = selfAttrs[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Clone everything except id
- if (selfAttr.name !== 'id') {
- cloneAttrs[cloneAttrs.length] = {name: selfAttr.name, value: selfAttr.value};
- cloneAttrs.map[selfAttr.name] = selfAttr.value;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Clone everything except id
+ if (selfAttr.name !== 'id') {
+ cloneAttrs[cloneAttrs.length] = { name: selfAttr.name, value: selfAttr.value };
+ cloneAttrs.map[selfAttr.name] = selfAttr.value;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- clone.attributes = cloneAttrs;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ clone.attributes = cloneAttrs;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- clone.value = self.value;
- clone.shortEnded = self.shortEnded;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ clone.value = self.value;
+ clone.shortEnded = self.shortEnded;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return clone;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return clone;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Wraps the node in in another node.
- *
- * @example
- * node.wrap(wrapperNode);
- *
- * @method wrap
- */
- wrap: function(wrapper) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Wraps the node in in another node.
+ *
+ * @example
+ * node.wrap(wrapperNode);
+ *
+ * @method wrap
+ */
+ wrap: function (wrapper) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.parent.insert(wrapper, self);
- wrapper.append(self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.parent.insert(wrapper, self);
+ wrapper.append(self);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Unwraps the node in other words it removes the node but keeps the children.
- *
- * @example
- * node.unwrap();
- *
- * @method unwrap
- */
- unwrap: function() {
- var self = this, node, next;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Unwraps the node in other words it removes the node but keeps the children.
+ *
+ * @example
+ * node.unwrap();
+ *
+ * @method unwrap
+ */
+ unwrap: function () {
+ var self = this, node, next;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (node = self.firstChild; node;) {
- next = node.next;
- self.insert(node, self, true);
- node = next;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (node = self.firstChild; node;) {
+ next = node.next;
+ self.insert(node, self, true);
+ node = next;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.remove();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.remove();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes the node from it's parent.
- *
- * @example
- * node.remove();
- *
- * @method remove
- * @return {tinymce.html.Node} Current node that got removed.
- */
- remove: function() {
- var self = this, parent = self.parent, next = self.next, prev = self.prev;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes the node from it's parent.
+ *
+ * @example
+ * node.remove();
+ *
+ * @method remove
+ * @return {tinymce.html.Node} Current node that got removed.
+ */
+ remove: function () {
+ var self = this, parent = self.parent, next = self.next, prev = self.prev;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (parent) {
- if (parent.firstChild === self) {
- parent.firstChild = next;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parent) {
+ if (parent.firstChild === self) {
+ parent.firstChild = next;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (next) {
- next.prev = null;
- }
- } else {
- prev.next = next;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (next) {
+ next.prev = null;
+ }
+ } else {
+ prev.next = next;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (parent.lastChild === self) {
- parent.lastChild = prev;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parent.lastChild === self) {
+ parent.lastChild = prev;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (prev) {
- prev.next = null;
- }
- } else {
- next.prev = prev;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (prev) {
+ prev.next = null;
+ }
+ } else {
+ next.prev = prev;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.parent = self.next = self.prev = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.parent = self.next = self.prev = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Appends a new node as a child of the current node.
- *
- * @example
- * node.append(someNode);
- *
- * @method append
- * @param {tinymce.html.Node} node Node to append as a child of the current one.
- * @return {tinymce.html.Node} The node that got appended.
- */
- append: function(node) {
- var self = this, last;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Appends a new node as a child of the current node.
+ *
+ * @example
+ * node.append(someNode);
+ *
+ * @method append
+ * @param {tinymce.html.Node} node Node to append as a child of the current one.
+ * @return {tinymce.html.Node} The node that got appended.
+ */
+ append: function (node) {
+ var self = this, last;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.parent) {
- node.remove();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.parent) {
+ node.remove();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- last = self.lastChild;
- if (last) {
- last.next = node;
- node.prev = last;
- self.lastChild = node;
- } else {
- self.lastChild = self.firstChild = node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ last = self.lastChild;
+ if (last) {
+ last.next = node;
+ node.prev = last;
+ self.lastChild = node;
+ } else {
+ self.lastChild = self.firstChild = node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node.parent = self;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node.parent = self;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return node;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return node;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Inserts a node at a specific position as a child of the current node.
- *
- * @example
- * parentNode.insert(newChildNode, oldChildNode);
- *
- * @method insert
- * @param {tinymce.html.Node} node Node to insert as a child of the current node.
- * @param {tinymce.html.Node} ref_node Reference node to set node before/after.
- * @param {Boolean} before Optional state to insert the node before the reference node.
- * @return {tinymce.html.Node} The node that got inserted.
- */
- insert: function(node, ref_node, before) {
- var parent;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Inserts a node at a specific position as a child of the current node.
+ *
+ * @example
+ * parentNode.insert(newChildNode, oldChildNode);
+ *
+ * @method insert
+ * @param {tinymce.html.Node} node Node to insert as a child of the current node.
+ * @param {tinymce.html.Node} refNode Reference node to set node before/after.
+ * @param {Boolean} before Optional state to insert the node before the reference node.
+ * @return {tinymce.html.Node} The node that got inserted.
+ */
+ insert: function (node, refNode, before) {
+ var parent;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.parent) {
- node.remove();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.parent) {
+ node.remove();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parent = ref_node.parent || this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parent = refNode.parent || this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (before) {
- if (ref_node === parent.firstChild) {
- parent.firstChild = node;
- } else {
- ref_node.prev.next = node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (before) {
+ if (refNode === parent.firstChild) {
+ parent.firstChild = node;
+ } else {
+ refNode.prev.next = node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node.prev = ref_node.prev;
- node.next = ref_node;
- ref_node.prev = node;
- } else {
- if (ref_node === parent.lastChild) {
- parent.lastChild = node;
- } else {
- ref_node.next.prev = node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node.prev = refNode.prev;
+ node.next = refNode;
+ refNode.prev = node;
+ } else {
+ if (refNode === parent.lastChild) {
+ parent.lastChild = node;
+ } else {
+ refNode.next.prev = node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node.next = ref_node.next;
- node.prev = ref_node;
- ref_node.next = node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node.next = refNode.next;
+ node.prev = refNode;
+ refNode.next = node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node.parent = parent;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node.parent = parent;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return node;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return node;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Get all children by name.
- *
- * @method getAll
- * @param {String} name Name of the child nodes to collect.
- * @return {Array} Array with child nodes matchin the specified name.
- */
- getAll: function(name) {
- var self = this, node, collection = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Get all children by name.
+ *
+ * @method getAll
+ * @param {String} name Name of the child nodes to collect.
+ * @return {Array} Array with child nodes matchin the specified name.
+ */
+ getAll: function (name) {
+ var self = this, node, collection = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (node = self.firstChild; node; node = walk(node, self)) {
- if (node.name === name) {
- collection.push(node);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (node = self.firstChild; node; node = walk(node, self)) {
+ if (node.name === name) {
+ collection.push(node);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return collection;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return collection;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes all children of the current node.
- *
- * @method empty
- * @return {tinymce.html.Node} The current node that got cleared.
- */
- empty: function() {
- var self = this, nodes, i, node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes all children of the current node.
+ *
+ * @method empty
+ * @return {tinymce.html.Node} The current node that got cleared.
+ */
+ empty: function () {
+ var self = this, nodes, i, node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove all children
- if (self.firstChild) {
- nodes = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove all children
+ if (self.firstChild) {
+ nodes = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Collect the children
- for (node = self.firstChild; node; node = walk(node, self)) {
- nodes.push(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Collect the children
+ for (node = self.firstChild; node; node = walk(node, self)) {
+ nodes.push(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove the children
- i = nodes.length;
- while (i--) {
- node = nodes[i];
- node.parent = node.firstChild = node.lastChild = node.next = node.prev = null;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove the children
+ i = nodes.length;
+ while (i--) {
+ node = nodes[i];
+ node.parent = node.firstChild = node.lastChild = node.next = node.prev = null;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.firstChild = self.lastChild = null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.firstChild = self.lastChild = null;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the node is to be considered empty or not.
- *
- * @example
- * node.isEmpty({img: true});
- * @method isEmpty
- * @param {Object} elements Name/value object with elements that are automatically treated as non empty elements.
- * @param {Object} whitespace Name/value object with elements that are automatically treated whitespace preservables.
- * @return {Boolean} true/false if the node is empty or not.
- */
- isEmpty: function(elements, whitespace) {
- var self = this, node = self.firstChild, i, name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the node is to be considered empty or not.
+ *
+ * @example
+ * node.isEmpty({img: true});
+ * @method isEmpty
+ * @param {Object} elements Name/value object with elements that are automatically treated as non empty elements.
+ * @param {Object} whitespace Name/value object with elements that are automatically treated whitespace preservables.
+ * @return {Boolean} true/false if the node is empty or not.
+ */
+ isEmpty: function (elements, whitespace) {
+ var self = this, node = self.firstChild, i, name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- whitespace = whitespace || {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ whitespace = whitespace || {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node) {
- do {
- if (node.type === 1) {
- // Ignore bogus elements
- if (node.attributes.map['data-mce-bogus']) {
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node) {
+ do {
+ if (node.type === 1) {
+ // Ignore bogus elements
+ if (node.attributes.map['data-mce-bogus']) {
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Keep empty elements like <img />
- if (elements[node.name]) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Keep empty elements like <img />
+ if (elements[node.name]) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Keep bookmark nodes and name attribute like <a name="1"></a>
- i = node.attributes.length;
- while (i--) {
- name = node.attributes[i].name;
- if (name === "name" || name.indexOf('data-mce-bookmark') === 0) {
- return false;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Keep bookmark nodes and name attribute like <a name="1"></a>
+ i = node.attributes.length;
+ while (i--) {
+ name = node.attributes[i].name;
+ if (name === "name" || name.indexOf('data-mce-bookmark') === 0) {
+ return false;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Keep comments
- if (node.type === 8) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Keep comments
+ if (node.type === 8) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Keep non whitespace text nodes
- if (node.type === 3 && !whiteSpaceRegExp.test(node.value)) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Keep non whitespace text nodes
+ if (node.type === 3 && !whiteSpaceRegExp.test(node.value)) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Keep whitespace preserve elements
- if (node.type === 3 && node.parent && whitespace[node.parent.name] && whiteSpaceRegExp.test(node.value)) {
- return false;
- }
- } while ((node = walk(node, self)));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Keep whitespace preserve elements
+ if (node.type === 3 && node.parent && whitespace[node.parent.name] && whiteSpaceRegExp.test(node.value)) {
+ return false;
+ }
+ } while ((node = walk(node, self)));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Walks to the next or previous node and returns that node or null if it wasn't found.
- *
- * @method walk
- * @param {Boolean} prev Optional previous node state defaults to false.
- * @return {tinymce.html.Node} Node that is next to or previous of the current node.
- */
- walk: function(prev) {
- return walk(this, null, prev);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Walks to the next or previous node and returns that node or null if it wasn't found.
+ *
+ * @method walk
+ * @param {Boolean} prev Optional previous node state defaults to false.
+ * @return {tinymce.html.Node} Node that is next to or previous of the current node.
+ */
+ walk: function (prev) {
+ return walk(this, null, prev);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates a node of a specific type.
- *
- * @static
- * @method create
- * @param {String} name Name of the node type to create for example "b" or "#text".
- * @param {Object} attrs Name/value collection of attributes that will be applied to elements.
- */
- Node.create = function(name, attrs) {
- var node, attrName;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates a node of a specific type.
+ *
+ * @static
+ * @method create
+ * @param {String} name Name of the node type to create for example "b" or "#text".
+ * @param {Object} attrs Name/value collection of attributes that will be applied to elements.
+ */
+ Node.create = function (name, attrs) {
+ var node, attrName;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Create node
- node = new Node(name, typeLookup[name] || 1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Create node
+ node = new Node(name, typeLookup[name] || 1);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add attributes if needed
- if (attrs) {
- for (attrName in attrs) {
- node.attr(attrName, attrs[attrName]);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add attributes if needed
+ if (attrs) {
+ for (attrName in attrs) {
+ node.attr(attrName, attrs[attrName]);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return node;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return node;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Node;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Node;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/html/Schema.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Schema.js
- *
- * Released under LGPL License.
- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- */
-
-/**
- * Schema validator class.
- *
- * @class tinymce.html.Schema
- * @example
- * if (tinymce.activeEditor.schema.isValidChild('p', 'span'))
- * alert('span is valid child of p.');
- *
- * if (tinymce.activeEditor.schema.getElementRule('p'))
- * alert('P is a valid element.');
- *
- * @class tinymce.html.Schema
- * @version 3.4
- */
-define("tinymce/html/Schema", [
- "tinymce/util/Tools"
-], function(Tools) {
- var mapCache = {}, dummyObj = {};
- var makeMap = Tools.makeMap, each = Tools.each, extend = Tools.extend, explode = Tools.explode, inArray = Tools.inArray;
-
- function split(items, delim) {
- items = Tools.trim(items);
- return items ? items.split(delim || ' ') : [];
- }
-
- /**
- * Builds a schema lookup table
- *
- * @private
- * @param {String} type html4, html5 or html5-strict schema type.
- * @return {Object} Schema lookup table.
- */
- function compileSchema(type) {
- var schema = {}, globalAttributes, blockContent;
- var phrasingContent, flowContent, html4BlockContent, html4PhrasingContent;
-
- function add(name, attributes, children) {
- var ni, attributesOrder, element;
-
- function arrayToMap(array, obj) {
- var map = {}, i, l;
-
- for (i = 0, l = array.length; i < l; i++) {
- map[array[i]] = obj || {};
- }
-
- return map;
- }
-
- children = children || [];
- attributes = attributes || "";
-
- if (typeof children === "string") {
- children = split(children);
- }
-
- name = split(name);
- ni = name.length;
- while (ni--) {
- attributesOrder = split([globalAttributes, attributes].join(' '));
-
- element = {
- attributes: arrayToMap(attributesOrder),
- attributesOrder: attributesOrder,
- children: arrayToMap(children, dummyObj)
- };
-
- schema[name[ni]] = element;
- }
- }
-
- function addAttrs(name, attributes) {
- var ni, schemaItem, i, l;
-
- name = split(name);
- ni = name.length;
- attributes = split(attributes);
- while (ni--) {
- schemaItem = schema[name[ni]];
- for (i = 0, l = attributes.length; i < l; i++) {
- schemaItem.attributes[attributes[i]] = {};
- schemaItem.attributesOrder.push(attributes[i]);
- }
- }
- }
-
- // Use cached schema
- if (mapCache[type]) {
- return mapCache[type];
- }
-
- // Attributes present on all elements
- globalAttributes = "id accesskey class dir lang style tabindex title";
-
- // Event attributes can be opt-in/opt-out
- /*eventAttributes = split("onabort onblur oncancel oncanplay oncanplaythrough onchange onclick onclose oncontextmenu oncuechange " +
- "ondblclick ondrag ondragend ondragenter ondragleave ondragover ondragstart ondrop ondurationchange onemptied onended " +
- "onerror onfocus oninput oninvalid onkeydown onkeypress onkeyup onload onloadeddata onloadedmetadata onloadstart " +
- "onmousedown onmousemove onmouseout onmouseover onmouseup onmousewheel onpause onplay onplaying onprogress onratechange " +
- "onreset onscroll onseeked onseeking onseeking onselect onshow onstalled onsubmit onsuspend ontimeupdate onvolumechange " +
- "onwaiting"
- );*/
-
- // Block content elements
- blockContent =
- "address blockquote div dl fieldset form h1 h2 h3 h4 h5 h6 hr menu ol p pre table ul";
-
- // Phrasing content elements from the HTML5 spec (inline)
- phrasingContent =
- "a abbr b bdo br button cite code del dfn em embed i iframe img input ins kbd " +
- "label map noscript object q s samp script select small span strong sub sup " +
- "textarea u var #text #comment"
- ;
-
- // Add HTML5 items to globalAttributes, blockContent, phrasingContent
- if (type != "html4") {
- globalAttributes += " contenteditable contextmenu draggable dropzone " +
- "hidden spellcheck translate";
- blockContent += " article aside details dialog figure header footer hgroup section nav";
- phrasingContent += " audio canvas command datalist mark meter output picture " +
- "progress time wbr video ruby bdi keygen";
- }
-
- // Add HTML4 elements unless it's html5-strict
- if (type != "html5-strict") {
- globalAttributes += " xml:lang";
-
- html4PhrasingContent = "acronym applet basefont big font strike tt";
- phrasingContent = [phrasingContent, html4PhrasingContent].join(' ');
-
- each(split(html4PhrasingContent), function(name) {
- add(name, "", phrasingContent);
- });
-
- html4BlockContent = "center dir isindex noframes";
- blockContent = [blockContent, html4BlockContent].join(' ');
-
- // Flow content elements from the HTML5 spec (block+inline)
- flowContent = [blockContent, phrasingContent].join(' ');
-
- each(split(html4BlockContent), function(name) {
- add(name, "", flowContent);
- });
- }
-
- // Flow content elements from the HTML5 spec (block+inline)
- flowContent = flowContent || [blockContent, phrasingContent].join(" ");
-
- // HTML4 base schema TODO: Move HTML5 specific attributes to HTML5 specific if statement
- // Schema items <element name>, <specific attributes>, <children ..>
- add("html", "manifest", "head body");
- add("head", "", "base command link meta noscript script style title");
- add("title hr noscript br");
- add("base", "href target");
- add("link", "href rel media hreflang type sizes hreflang");
- add("meta", "name http-equiv content charset");
- add("style", "media type scoped");
- add("script", "src async defer type charset");
- add("body", "onafterprint onbeforeprint onbeforeunload onblur onerror onfocus " +
- "onhashchange onload onmessage onoffline ononline onpagehide onpageshow " +
- "onpopstate onresize onscroll onstorage onunload", flowContent);
- add("address dt dd div caption", "", flowContent);
- add("h1 h2 h3 h4 h5 h6 pre p abbr code var samp kbd sub sup i b u bdo span legend em strong small s cite dfn", "", phrasingContent);
- add("blockquote", "cite", flowContent);
- add("ol", "reversed start type", "li");
- add("ul", "", "li");
- add("li", "value", flowContent);
- add("dl", "", "dt dd");
- add("a", "href target rel media hreflang type", phrasingContent);
- add("q", "cite", phrasingContent);
- add("ins del", "cite datetime", flowContent);
- add("img", "src sizes srcset alt usemap ismap width height");
- add("iframe", "src name width height", flowContent);
- add("embed", "src type width height");
- add("object", "data type typemustmatch name usemap form width height", [flowContent, "param"].join(' '));
- add("param", "name value");
- add("map", "name", [flowContent, "area"].join(' '));
- add("area", "alt coords shape href target rel media hreflang type");
- add("table", "border", "caption colgroup thead tfoot tbody tr" + (type == "html4" ? " col" : ""));
- add("colgroup", "span", "col");
- add("col", "span");
- add("tbody thead tfoot", "", "tr");
- add("tr", "", "td th");
- add("td", "colspan rowspan headers", flowContent);
- add("th", "colspan rowspan headers scope abbr", flowContent);
- add("form", "accept-charset action autocomplete enctype method name novalidate target", flowContent);
- add("fieldset", "disabled form name", [flowContent, "legend"].join(' '));
- add("label", "form for", phrasingContent);
- add("input", "accept alt autocomplete checked dirname disabled form formaction formenctype formmethod formnovalidate " +
- "formtarget height list max maxlength min multiple name pattern readonly required size src step type value width"
- );
- add("button", "disabled form formaction formenctype formmethod formnovalidate formtarget name type value",
- type == "html4" ? flowContent : phrasingContent);
- add("select", "disabled form multiple name required size", "option optgroup");
- add("optgroup", "disabled label", "option");
- add("option", "disabled label selected value");
- add("textarea", "cols dirname disabled form maxlength name readonly required rows wrap");
- add("menu", "type label", [flowContent, "li"].join(' '));
- add("noscript", "", flowContent);
-
- // Extend with HTML5 elements
- if (type != "html4") {
- add("wbr");
- add("ruby", "", [phrasingContent, "rt rp"].join(' '));
- add("figcaption", "", flowContent);
- add("mark rt rp summary bdi", "", phrasingContent);
- add("canvas", "width height", flowContent);
- add("video", "src crossorigin poster preload autoplay mediagroup loop " +
- "muted controls width height buffered", [flowContent, "track source"].join(' '));
- add("audio", "src crossorigin preload autoplay mediagroup loop muted controls " +
- "buffered volume", [flowContent, "track source"].join(' '));
- add("picture", "", "img source");
- add("source", "src srcset type media sizes");
- add("track", "kind src srclang label default");
- add("datalist", "", [phrasingContent, "option"].join(' '));
- add("article section nav aside header footer", "", flowContent);
- add("hgroup", "", "h1 h2 h3 h4 h5 h6");
- add("figure", "", [flowContent, "figcaption"].join(' '));
- add("time", "datetime", phrasingContent);
- add("dialog", "open", flowContent);
- add("command", "type label icon disabled checked radiogroup command");
- add("output", "for form name", phrasingContent);
- add("progress", "value max", phrasingContent);
- add("meter", "value min max low high optimum", phrasingContent);
- add("details", "open", [flowContent, "summary"].join(' '));
- add("keygen", "autofocus challenge disabled form keytype name");
- }
-
- // Extend with HTML4 attributes unless it's html5-strict
- if (type != "html5-strict") {
- addAttrs("script", "language xml:space");
- addAttrs("style", "xml:space");
- addAttrs("object", "declare classid code codebase codetype archive standby align border hspace vspace");
- addAttrs("embed", "align name hspace vspace");
- addAttrs("param", "valuetype type");
- addAttrs("a", "charset name rev shape coords");
- addAttrs("br", "clear");
- addAttrs("applet", "codebase archive code object alt name width height align hspace vspace");
- addAttrs("img", "name longdesc align border hspace vspace");
- addAttrs("iframe", "longdesc frameborder marginwidth marginheight scrolling align");
- addAttrs("font basefont", "size color face");
- addAttrs("input", "usemap align");
- addAttrs("select", "onchange");
- addAttrs("textarea");
- addAttrs("h1 h2 h3 h4 h5 h6 div p legend caption", "align");
- addAttrs("ul", "type compact");
- addAttrs("li", "type");
- addAttrs("ol dl menu dir", "compact");
- addAttrs("pre", "width xml:space");
- addAttrs("hr", "align noshade size width");
- addAttrs("isindex", "prompt");
- addAttrs("table", "summary width frame rules cellspacing cellpadding align bgcolor");
- addAttrs("col", "width align char charoff valign");
- addAttrs("colgroup", "width align char charoff valign");
- addAttrs("thead", "align char charoff valign");
- addAttrs("tr", "align char charoff valign bgcolor");
- addAttrs("th", "axis align char charoff valign nowrap bgcolor width height");
- addAttrs("form", "accept");
- addAttrs("td", "abbr axis scope align char charoff valign nowrap bgcolor width height");
- addAttrs("tfoot", "align char charoff valign");
- addAttrs("tbody", "align char charoff valign");
- addAttrs("area", "nohref");
- addAttrs("body", "background bgcolor text link vlink alink");
- }
-
- // Extend with HTML5 attributes unless it's html4
- if (type != "html4") {
- addAttrs("input button select textarea", "autofocus");
- addAttrs("input textarea", "placeholder");
- addAttrs("a", "download");
- addAttrs("link script img", "crossorigin");
- addAttrs("iframe", "sandbox seamless allowfullscreen"); // Excluded: srcdoc
- }
-
- // Special: iframe, ruby, video, audio, label
-
- // Delete children of the same name from it's parent
- // For example: form can't have a child of the name form
- each(split('a form meter progress dfn'), function(name) {
- if (schema[name]) {
- delete schema[name].children[name];
- }
- });
-
- // Delete header, footer, sectioning and heading content descendants
- /*each('dt th address', function(name) {
- delete schema[name].children[name];
- });*/
-
- // Caption can't have tables
- delete schema.caption.children.table;
-
- // Delete scripts by default due to possible XSS
- delete schema.script;
-
- // TODO: LI:s can only have value if parent is OL
-
- // TODO: Handle transparent elements
- // a ins del canvas map
-
- mapCache[type] = schema;
-
- return schema;
- }
-
- function compileElementMap(value, mode) {
- var styles;
-
- if (value) {
- styles = {};
-
- if (typeof value == 'string') {
- value = {
- '*': value
- };
- }
-
- // Convert styles into a rule list
- each(value, function(value, key) {
- styles[key] = styles[key.toUpperCase()] = mode == 'map' ? makeMap(value, /[, ]/) : explode(value, /[, ]/);
- });
- }
-
- return styles;
- }
-
- /**
- * Constructs a new Schema instance.
- *
- * @constructor
- * @method Schema
- * @param {Object} settings Name/value settings object.
- */
- return function(settings) {
- var self = this, elements = {}, children = {}, patternElements = [], validStyles, invalidStyles, schemaItems;
- var whiteSpaceElementsMap, selfClosingElementsMap, shortEndedElementsMap, boolAttrMap, validClasses;
- var blockElementsMap, nonEmptyElementsMap, moveCaretBeforeOnEnterElementsMap, textBlockElementsMap, textInlineElementsMap;
- var customElementsMap = {}, specialElements = {};
-
- // Creates an lookup table map object for the specified option or the default value
- function createLookupTable(option, default_value, extendWith) {
- var value = settings[option];
-
- if (!value) {
- // Get cached default map or make it if needed
- value = mapCache[option];
-
- if (!value) {
- value = makeMap(default_value, ' ', makeMap(default_value.toUpperCase(), ' '));
- value = extend(value, extendWith);
-
- mapCache[option] = value;
- }
- } else {
- // Create custom map
- value = makeMap(value, /[, ]/, makeMap(value.toUpperCase(), /[, ]/));
- }
-
- return value;
- }
-
- settings = settings || {};
- schemaItems = compileSchema(settings.schema);
-
- // Allow all elements and attributes if verify_html is set to false
- if (settings.verify_html === false) {
- settings.valid_elements = '*[*]';
- }
-
- validStyles = compileElementMap(settings.valid_styles);
- invalidStyles = compileElementMap(settings.invalid_styles, 'map');
- validClasses = compileElementMap(settings.valid_classes, 'map');
-
- // Setup map objects
- whiteSpaceElementsMap = createLookupTable(
- 'whitespace_elements',
- 'pre script noscript style textarea video audio iframe object code'
- );
- selfClosingElementsMap = createLookupTable('self_closing_elements', 'colgroup dd dt li option p td tfoot th thead tr');
- shortEndedElementsMap = createLookupTable('short_ended_elements', 'area base basefont br col frame hr img input isindex link ' +
- 'meta param embed source wbr track');
- boolAttrMap = createLookupTable('boolean_attributes', 'checked compact declare defer disabled ismap multiple nohref noresize ' +
- 'noshade nowrap readonly selected autoplay loop controls');
- nonEmptyElementsMap = createLookupTable('non_empty_elements', 'td th iframe video audio object ' +
- 'script pre code', shortEndedElementsMap);
- moveCaretBeforeOnEnterElementsMap = createLookupTable('move_caret_before_on_enter_elements', 'table', nonEmptyElementsMap);
- textBlockElementsMap = createLookupTable('text_block_elements', 'h1 h2 h3 h4 h5 h6 p div address pre form ' +
- 'blockquote center dir fieldset header footer article section hgroup aside nav figure');
- blockElementsMap = createLookupTable('block_elements', 'hr table tbody thead tfoot ' +
- 'th tr td li ol ul caption dl dt dd noscript menu isindex option ' +
- 'datalist select optgroup figcaption', textBlockElementsMap);
- textInlineElementsMap = createLookupTable('text_inline_elements', 'span strong b em i font strike u var cite ' +
- 'dfn code mark q sup sub samp');
-
- each((settings.special || 'script noscript style textarea').split(' '), function(name) {
- specialElements[name] = new RegExp('<\/' + name + '[^>]*>', 'gi');
- });
-
- // Converts a wildcard expression string to a regexp for example *a will become /.*a/.
- function patternToRegExp(str) {
- return new RegExp('^' + str.replace(/([?+*])/g, '.$1') + '$');
- }
-
- // Parses the specified valid_elements string and adds to the current rules
- // This function is a bit hard to read since it's heavily optimized for speed
- function addValidElements(validElements) {
- var ei, el, ai, al, matches, element, attr, attrData, elementName, attrName, attrType, attributes, attributesOrder,
- prefix, outputName, globalAttributes, globalAttributesOrder, key, value,
- elementRuleRegExp = /^([#+\-])?([^\[!\/]+)(?:\/([^\[!]+))?(?:(!?)\[([^\]]+)\])?$/,
- attrRuleRegExp = /^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/,
- hasPatternsRegExp = /[*?+]/;
-
- if (validElements) {
- // Split valid elements into an array with rules
- validElements = split(validElements, ',');
-
- if (elements['@']) {
- globalAttributes = elements['@'].attributes;
- globalAttributesOrder = elements['@'].attributesOrder;
- }
-
- // Loop all rules
- for (ei = 0, el = validElements.length; ei < el; ei++) {
- // Parse element rule
- matches = elementRuleRegExp.exec(validElements[ei]);
- if (matches) {
- // Setup local names for matches
- prefix = matches[1];
- elementName = matches[2];
- outputName = matches[3];
- attrData = matches[5];
-
- // Create new attributes and attributesOrder
- attributes = {};
- attributesOrder = [];
-
- // Create the new element
- element = {
- attributes: attributes,
- attributesOrder: attributesOrder
- };
-
- // Padd empty elements prefix
- if (prefix === '#') {
- element.paddEmpty = true;
- }
-
- // Remove empty elements prefix
- if (prefix === '-') {
- element.removeEmpty = true;
- }
-
- if (matches[4] === '!') {
- element.removeEmptyAttrs = true;
- }
-
- // Copy attributes from global rule into current rule
- if (globalAttributes) {
- for (key in globalAttributes) {
- attributes[key] = globalAttributes[key];
- }
-
- attributesOrder.push.apply(attributesOrder, globalAttributesOrder);
- }
-
- // Attributes defined
- if (attrData) {
- attrData = split(attrData, '|');
- for (ai = 0, al = attrData.length; ai < al; ai++) {
- matches = attrRuleRegExp.exec(attrData[ai]);
- if (matches) {
- attr = {};
- attrType = matches[1];
- attrName = matches[2].replace(/::/g, ':');
- prefix = matches[3];
- value = matches[4];
-
- // Required
- if (attrType === '!') {
- element.attributesRequired = element.attributesRequired || [];
- element.attributesRequired.push(attrName);
- attr.required = true;
- }
-
- // Denied from global
- if (attrType === '-') {
- delete attributes[attrName];
- attributesOrder.splice(inArray(attributesOrder, attrName), 1);
- continue;
- }
-
- // Default value
- if (prefix) {
- // Default value
- if (prefix === '=') {
- element.attributesDefault = element.attributesDefault || [];
- element.attributesDefault.push({name: attrName, value: value});
- attr.defaultValue = value;
- }
-
- // Forced value
- if (prefix === ':') {
- element.attributesForced = element.attributesForced || [];
- element.attributesForced.push({name: attrName, value: value});
- attr.forcedValue = value;
- }
-
- // Required values
- if (prefix === '<') {
- attr.validValues = makeMap(value, '?');
- }
- }
-
- // Check for attribute patterns
- if (hasPatternsRegExp.test(attrName)) {
- element.attributePatterns = element.attributePatterns || [];
- attr.pattern = patternToRegExp(attrName);
- element.attributePatterns.push(attr);
- } else {
- // Add attribute to order list if it doesn't already exist
- if (!attributes[attrName]) {
- attributesOrder.push(attrName);
- }
-
- attributes[attrName] = attr;
- }
- }
- }
- }
-
- // Global rule, store away these for later usage
- if (!globalAttributes && elementName == '@') {
- globalAttributes = attributes;
- globalAttributesOrder = attributesOrder;
- }
-
- // Handle substitute elements such as b/strong
- if (outputName) {
- element.outputName = elementName;
- elements[outputName] = element;
- }
-
- // Add pattern or exact element
- if (hasPatternsRegExp.test(elementName)) {
- element.pattern = patternToRegExp(elementName);
- patternElements.push(element);
- } else {
- elements[elementName] = element;
- }
- }
- }
- }
- }
-
- function setValidElements(validElements) {
- elements = {};
- patternElements = [];
-
- addValidElements(validElements);
-
- each(schemaItems, function(element, name) {
- children[name] = element.children;
- });
- }
-
- // Adds custom non HTML elements to the schema
- function addCustomElements(customElements) {
- var customElementRegExp = /^(~)?(.+)$/;
-
- if (customElements) {
- // Flush cached items since we are altering the default maps
- mapCache.text_block_elements = mapCache.block_elements = null;
-
- each(split(customElements, ','), function(rule) {
- var matches = customElementRegExp.exec(rule),
- inline = matches[1] === '~',
- cloneName = inline ? 'span' : 'div',
- name = matches[2];
-
- children[name] = children[cloneName];
- customElementsMap[name] = cloneName;
-
- // If it's not marked as inline then add it to valid block elements
- if (!inline) {
- blockElementsMap[name.toUpperCase()] = {};
- blockElementsMap[name] = {};
- }
-
- // Add elements clone if needed
- if (!elements[name]) {
- var customRule = elements[cloneName];
-
- customRule = extend({}, customRule);
- delete customRule.removeEmptyAttrs;
- delete customRule.removeEmpty;
-
- elements[name] = customRule;
- }
-
- // Add custom elements at span/div positions
- each(children, function(element, elmName) {
- if (element[cloneName]) {
- children[elmName] = element = extend({}, children[elmName]);
- element[name] = element[cloneName];
- }
- });
- });
- }
- }
-
- // Adds valid children to the schema object
- function addValidChildren(validChildren) {
- var childRuleRegExp = /^([+\-]?)(\w+)\[([^\]]+)\]$/;
-
- // Invalidate the schema cache if the schema is mutated
- mapCache[settings.schema] = null;
-
- if (validChildren) {
- each(split(validChildren, ','), function(rule) {
- var matches = childRuleRegExp.exec(rule), parent, prefix;
-
- if (matches) {
- prefix = matches[1];
-
- // Add/remove items from default
- if (prefix) {
- parent = children[matches[2]];
- } else {
- parent = children[matches[2]] = {'#comment': {}};
- }
-
- parent = children[matches[2]];
-
- each(split(matches[3], '|'), function(child) {
- if (prefix === '-') {
- delete parent[child];
- } else {
- parent[child] = {};
- }
- });
- }
- });
- }
- }
-
- function getElementRule(name) {
- var element = elements[name], i;
-
- // Exact match found
- if (element) {
- return element;
- }
-
- // No exact match then try the patterns
- i = patternElements.length;
- while (i--) {
- element = patternElements[i];
-
- if (element.pattern.test(name)) {
- return element;
- }
- }
- }
-
- if (!settings.valid_elements) {
- // No valid elements defined then clone the elements from the schema spec
- each(schemaItems, function(element, name) {
- elements[name] = {
- attributes: element.attributes,
- attributesOrder: element.attributesOrder
- };
-
- children[name] = element.children;
- });
-
- // Switch these on HTML4
- if (settings.schema != "html5") {
- each(split('strong/b em/i'), function(item) {
- item = split(item, '/');
- elements[item[1]].outputName = item[0];
- });
- }
-
- // Add default alt attribute for images, removed since alt="" is treated as presentational.
- // elements.img.attributesDefault = [{name: 'alt', value: ''}];
-
- // Remove these if they are empty by default
- each(split('ol ul sub sup blockquote span font a table tbody tr strong em b i'), function(name) {
- if (elements[name]) {
- elements[name].removeEmpty = true;
- }
- });
-
- // Padd these by default
- each(split('p h1 h2 h3 h4 h5 h6 th td pre div address caption'), function(name) {
- elements[name].paddEmpty = true;
- });
-
- // Remove these if they have no attributes
- each(split('span'), function(name) {
- elements[name].removeEmptyAttrs = true;
- });
-
- // Remove these by default
- // TODO: Reenable in 4.1
- /*each(split('script style'), function(name) {
- delete elements[name];
- });*/
- } else {
- setValidElements(settings.valid_elements);
- }
-
- addCustomElements(settings.custom_elements);
- addValidChildren(settings.valid_children);
- addValidElements(settings.extended_valid_elements);
-
- // Todo: Remove this when we fix list handling to be valid
- addValidChildren('+ol[ul|ol],+ul[ul|ol]');
-
-
- // Some elements are not valid by themselves - require parents
- each({
- dd: 'dl',
- dt: 'dl',
- li: 'ul ol',
- td: 'tr',
- th: 'tr',
- tr: 'tbody thead tfoot',
- tbody: 'table',
- thead: 'table',
- tfoot: 'table',
- legend: 'fieldset',
- area: 'map',
- param: 'video audio object'
- }, function(parents, item) {
- if (elements[item]) {
- elements[item].parentsRequired = split(parents);
- }
- });
-
-
- // Delete invalid elements
- if (settings.invalid_elements) {
- each(explode(settings.invalid_elements), function(item) {
- if (elements[item]) {
- delete elements[item];
- }
- });
- }
-
- // If the user didn't allow span only allow internal spans
- if (!getElementRule('span')) {
- addValidElements('span[!data-mce-type|*]');
- }
-
- /**
- * Name/value map object with valid parents and children to those parents.
- *
- * @example
- * children = {
- * div:{p:{}, h1:{}}
- * };
- * @field children
- * @type Object
- */
- self.children = children;
-
- /**
- * Name/value map object with valid styles for each element.
- *
- * @method getValidStyles
- * @type Object
- */
- self.getValidStyles = function() {
- return validStyles;
- };
-
- /**
- * Name/value map object with valid styles for each element.
- *
- * @method getInvalidStyles
- * @type Object
- */
- self.getInvalidStyles = function() {
- return invalidStyles;
- };
-
- /**
- * Name/value map object with valid classes for each element.
- *
- * @method getValidClasses
- * @type Object
- */
- self.getValidClasses = function() {
- return validClasses;
- };
-
- /**
- * Returns a map with boolean attributes.
- *
- * @method getBoolAttrs
- * @return {Object} Name/value lookup map for boolean attributes.
- */
- self.getBoolAttrs = function() {
- return boolAttrMap;
- };
-
- /**
- * Returns a map with block elements.
- *
- * @method getBlockElements
- * @return {Object} Name/value lookup map for block elements.
- */
- self.getBlockElements = function() {
- return blockElementsMap;
- };
-
- /**
- * Returns a map with text block elements. Such as: p,h1-h6,div,address
- *
- * @method getTextBlockElements
- * @return {Object} Name/value lookup map for block elements.
- */
- self.getTextBlockElements = function() {
- return textBlockElementsMap;
- };
-
- /**
- * Returns a map of inline text format nodes for example strong/span or ins.
- *
- * @method getTextInlineElements
- * @return {Object} Name/value lookup map for text format elements.
- */
- self.getTextInlineElements = function() {
- return textInlineElementsMap;
- };
-
- /**
- * Returns a map with short ended elements such as BR or IMG.
- *
- * @method getShortEndedElements
- * @return {Object} Name/value lookup map for short ended elements.
- */
- self.getShortEndedElements = function() {
- return shortEndedElementsMap;
- };
-
- /**
- * Returns a map with self closing tags such as <li>.
- *
- * @method getSelfClosingElements
- * @return {Object} Name/value lookup map for self closing tags elements.
- */
- self.getSelfClosingElements = function() {
- return selfClosingElementsMap;
- };
-
- /**
- * Returns a map with elements that should be treated as contents regardless if it has text
- * content in them or not such as TD, VIDEO or IMG.
- *
- * @method getNonEmptyElements
- * @return {Object} Name/value lookup map for non empty elements.
- */
- self.getNonEmptyElements = function() {
- return nonEmptyElementsMap;
- };
-
- /**
- * Returns a map with elements that the caret should be moved in front of after enter is
- * pressed
- *
- * @method getMoveCaretBeforeOnEnterElements
- * @return {Object} Name/value lookup map for elements to place the caret in front of.
- */
- self.getMoveCaretBeforeOnEnterElements = function() {
- return moveCaretBeforeOnEnterElementsMap;
- };
-
- /**
- * Returns a map with elements where white space is to be preserved like PRE or SCRIPT.
- *
- * @method getWhiteSpaceElements
- * @return {Object} Name/value lookup map for white space elements.
- */
- self.getWhiteSpaceElements = function() {
- return whiteSpaceElementsMap;
- };
-
- /**
- * Returns a map with special elements. These are elements that needs to be parsed
- * in a special way such as script, style, textarea etc. The map object values
- * are regexps used to find the end of the element.
- *
- * @method getSpecialElements
- * @return {Object} Name/value lookup map for special elements.
- */
- self.getSpecialElements = function() {
- return specialElements;
- };
-
- /**
- * Returns true/false if the specified element and it's child is valid or not
- * according to the schema.
- *
- * @method isValidChild
- * @param {String} name Element name to check for.
- * @param {String} child Element child to verify.
- * @return {Boolean} True/false if the element is a valid child of the specified parent.
- */
- self.isValidChild = function(name, child) {
- var parent = children[name];
-
- return !!(parent && parent[child]);
- };
-
- /**
- * Returns true/false if the specified element name and optional attribute is
- * valid according to the schema.
- *
- * @method isValid
- * @param {String} name Name of element to check.
- * @param {String} attr Optional attribute name to check for.
- * @return {Boolean} True/false if the element and attribute is valid.
- */
- self.isValid = function(name, attr) {
- var attrPatterns, i, rule = getElementRule(name);
-
- // Check if it's a valid element
- if (rule) {
- if (attr) {
- // Check if attribute name exists
- if (rule.attributes[attr]) {
- return true;
- }
-
- // Check if attribute matches a regexp pattern
- attrPatterns = rule.attributePatterns;
- if (attrPatterns) {
- i = attrPatterns.length;
- while (i--) {
- if (attrPatterns[i].pattern.test(name)) {
- return true;
- }
- }
- }
- } else {
- return true;
- }
- }
-
- // No match
- return false;
- };
-
- /**
- * Returns true/false if the specified element is valid or not
- * according to the schema.
- *
- * @method getElementRule
- * @param {String} name Element name to check for.
- * @return {Object} Element object or undefined if the element isn't valid.
- */
- self.getElementRule = getElementRule;
-
- /**
- * Returns an map object of all custom elements.
- *
- * @method getCustomElements
- * @return {Object} Name/value map object of all custom elements.
- */
- self.getCustomElements = function() {
- return customElementsMap;
- };
-
- /**
- * Parses a valid elements string and adds it to the schema. The valid elements
- * format is for example "element[attr=default|otherattr]".
- * Existing rules will be replaced with the ones specified, so this extends the schema.
- *
- * @method addValidElements
- * @param {String} valid_elements String in the valid elements format to be parsed.
- */
- self.addValidElements = addValidElements;
-
- /**
- * Parses a valid elements string and sets it to the schema. The valid elements
- * format is for example "element[attr=default|otherattr]".
- * Existing rules will be replaced with the ones specified, so this extends the schema.
- *
- * @method setValidElements
- * @param {String} valid_elements String in the valid elements format to be parsed.
- */
- self.setValidElements = setValidElements;
-
- /**
- * Adds custom non HTML elements to the schema.
- *
- * @method addCustomElements
- * @param {String} custom_elements Comma separated list of custom elements to add.
- */
- self.addCustomElements = addCustomElements;
-
- /**
- * Parses a valid children string and adds them to the schema structure. The valid children
- * format is for example: "element[child1|child2]".
- *
- * @method addValidChildren
- * @param {String} valid_children Valid children elements string to parse
- */
- self.addValidChildren = addValidChildren;
-
- self.elements = elements;
- };
-});
-
-// Included from: js/tinymce/classes/html/SaxParser.js
-
-/**
</del><span class="cx" style="display: block; padding: 0 10px"> * SaxParser.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -12736,436 +13644,449 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.html.SaxParser
</span><span class="cx" style="display: block; padding: 0 10px"> * @version 3.4
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/html/SaxParser", [
- "tinymce/html/Schema",
- "tinymce/html/Entities",
- "tinymce/util/Tools"
-], function(Schema, Entities, Tools) {
- var each = Tools.each;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.html.SaxParser',
+ [
+ "tinymce.core.html.Schema",
+ "tinymce.core.html.Entities",
+ "tinymce.core.util.Tools"
+ ],
+ function (Schema, Entities, Tools) {
+ var each = Tools.each;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the index of the end tag for a specific start tag. This can be
- * used to skip all children of a parent element from being processed.
- *
- * @private
- * @method findEndTag
- * @param {tinymce.html.Schema} schema Schema instance to use to match short ended elements.
- * @param {String} html HTML string to find the end tag in.
- * @param {Number} startIndex Indext to start searching at should be after the start tag.
- * @return {Number} Index of the end tag.
- */
- function findEndTag(schema, html, startIndex) {
- var count = 1, index, matches, tokenRegExp, shortEndedElements;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isValidPrefixAttrName = function (name) {
+ return name.indexOf('data-') === 0 || name.indexOf('aria-') === 0;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- shortEndedElements = schema.getShortEndedElements();
- tokenRegExp = /<([!?\/])?([A-Za-z0-9\-_\:\.]+)((?:\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\/|\s+)>/g;
- tokenRegExp.lastIndex = index = startIndex;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the index of the end tag for a specific start tag. This can be
+ * used to skip all children of a parent element from being processed.
+ *
+ * @private
+ * @method findEndTag
+ * @param {tinymce.html.Schema} schema Schema instance to use to match short ended elements.
+ * @param {String} html HTML string to find the end tag in.
+ * @param {Number} startIndex Indext to start searching at should be after the start tag.
+ * @return {Number} Index of the end tag.
+ */
+ function findEndTag(schema, html, startIndex) {
+ var count = 1, index, matches, tokenRegExp, shortEndedElements;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while ((matches = tokenRegExp.exec(html))) {
- index = tokenRegExp.lastIndex;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ shortEndedElements = schema.getShortEndedElements();
+ tokenRegExp = /<([!?\/])?([A-Za-z0-9\-_\:\.]+)((?:\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\/|\s+)>/g;
+ tokenRegExp.lastIndex = index = startIndex;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (matches[1] === '/') { // End element
- count--;
- } else if (!matches[1]) { // Start element
- if (matches[2] in shortEndedElements) {
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while ((matches = tokenRegExp.exec(html))) {
+ index = tokenRegExp.lastIndex;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- count++;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (matches[1] === '/') { // End element
+ count--;
+ } else if (!matches[1]) { // Start element
+ if (matches[2] in shortEndedElements) {
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (count === 0) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ count++;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return index;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (count === 0) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a new SaxParser instance.
- *
- * @constructor
- * @method SaxParser
- * @param {Object} settings Name/value collection of settings. comment, cdata, text, start and end are callbacks.
- * @param {tinymce.html.Schema} schema HTML Schema class to use when parsing.
- */
- function SaxParser(settings, schema) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return index;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function noop() {}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a new SaxParser instance.
+ *
+ * @constructor
+ * @method SaxParser
+ * @param {Object} settings Name/value collection of settings. comment, cdata, text, start and end are callbacks.
+ * @param {tinymce.html.Schema} schema HTML Schema class to use when parsing.
+ */
+ function SaxParser(settings, schema) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- settings = settings || {};
- self.schema = schema = schema || new Schema();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function noop() { }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.fix_self_closing !== false) {
- settings.fix_self_closing = true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ settings = settings || {};
+ self.schema = schema = schema || new Schema();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add handler functions from settings and setup default handlers
- each('comment cdata text start end pi doctype'.split(' '), function(name) {
- if (name) {
- self[name] = settings[name] || noop;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.fix_self_closing !== false) {
+ settings.fix_self_closing = true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Parses the specified HTML string and executes the callbacks for each item it finds.
- *
- * @example
- * new SaxParser({...}).parse('<b>text</b>');
- * @method parse
- * @param {String} html Html string to sax parse.
- */
- self.parse = function(html) {
- var self = this, matches, index = 0, value, endRegExp, stack = [], attrList, i, text, name;
- var isInternalElement, removeInternalElements, shortEndedElements, fillAttrsMap, isShortEnded;
- var validate, elementRule, isValidElement, attr, attribsValue, validAttributesMap, validAttributePatterns;
- var attributesRequired, attributesDefault, attributesForced;
- var anyAttributesRequired, selfClosing, tokenRegExp, attrRegExp, specialElements, attrValue, idCount = 0;
- var decode = Entities.decode, fixSelfClosing, filteredUrlAttrs = Tools.makeMap('src,href,data,background,formaction,poster');
- var scriptUriRegExp = /((java|vb)script|mhtml):/i, dataUriRegExp = /^data:/i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add handler functions from settings and setup default handlers
+ each('comment cdata text start end pi doctype'.split(' '), function (name) {
+ if (name) {
+ self[name] = settings[name] || noop;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function processEndTag(name) {
- var pos, i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Parses the specified HTML string and executes the callbacks for each item it finds.
+ *
+ * @example
+ * new SaxParser({...}).parse('<b>text</b>');
+ * @method parse
+ * @param {String} html Html string to sax parse.
+ */
+ self.parse = function (html) {
+ var self = this, matches, index = 0, value, endRegExp, stack = [], attrList, i, text, name;
+ var isInternalElement, removeInternalElements, shortEndedElements, fillAttrsMap, isShortEnded;
+ var validate, elementRule, isValidElement, attr, attribsValue, validAttributesMap, validAttributePatterns;
+ var attributesRequired, attributesDefault, attributesForced;
+ var anyAttributesRequired, selfClosing, tokenRegExp, attrRegExp, specialElements, attrValue, idCount = 0;
+ var decode = Entities.decode, fixSelfClosing, filteredUrlAttrs = Tools.makeMap('src,href,data,background,formaction,poster');
+ var scriptUriRegExp = /((java|vb)script|mhtml):/i, dataUriRegExp = /^data:/i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Find position of parent of the same type
- pos = stack.length;
- while (pos--) {
- if (stack[pos].name === name) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function processEndTag(name) {
+ var pos, i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Found parent
- if (pos >= 0) {
- // Close all the open elements
- for (i = stack.length - 1; i >= pos; i--) {
- name = stack[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find position of parent of the same type
+ pos = stack.length;
+ while (pos--) {
+ if (stack[pos].name === name) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name.valid) {
- self.end(name.name);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Found parent
+ if (pos >= 0) {
+ // Close all the open elements
+ for (i = stack.length - 1; i >= pos; i--) {
+ name = stack[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove the open elements from the stack
- stack.length = pos;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name.valid) {
+ self.end(name.name);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function parseAttribute(match, name, value, val2, val3) {
- var attrRule, i, trimRegExp = /[\s\u0000-\u001F]+/g;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove the open elements from the stack
+ stack.length = pos;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- name = name.toLowerCase();
- value = name in fillAttrsMap ? name : decode(value || val2 || val3 || ''); // Handle boolean attribute than value attribute
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function parseAttribute(match, name, value, val2, val3) {
+ var attrRule, i, trimRegExp = /[\s\u0000-\u001F]+/g;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Validate name and value pass through all data- attributes
- if (validate && !isInternalElement && name.indexOf('data-') !== 0) {
- attrRule = validAttributesMap[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ name = name.toLowerCase();
+ value = name in fillAttrsMap ? name : decode(value || val2 || val3 || ''); // Handle boolean attribute than value attribute
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Find rule by pattern matching
- if (!attrRule && validAttributePatterns) {
- i = validAttributePatterns.length;
- while (i--) {
- attrRule = validAttributePatterns[i];
- if (attrRule.pattern.test(name)) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Validate name and value pass through all data- attributes
+ if (validate && !isInternalElement && isValidPrefixAttrName(name) === false) {
+ attrRule = validAttributesMap[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // No rule matched
- if (i === -1) {
- attrRule = null;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find rule by pattern matching
+ if (!attrRule && validAttributePatterns) {
+ i = validAttributePatterns.length;
+ while (i--) {
+ attrRule = validAttributePatterns[i];
+ if (attrRule.pattern.test(name)) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // No attribute rule found
- if (!attrRule) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // No rule matched
+ if (i === -1) {
+ attrRule = null;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Validate value
- if (attrRule.validValues && !(value in attrRule.validValues)) {
- return;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // No attribute rule found
+ if (!attrRule) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Block any javascript: urls or non image data uris
- if (filteredUrlAttrs[name] && !settings.allow_script_urls) {
- var uri = value.replace(trimRegExp, '');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Validate value
+ if (attrRule.validValues && !(value in attrRule.validValues)) {
+ return;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- try {
- // Might throw malformed URI sequence
- uri = decodeURIComponent(uri);
- } catch (ex) {
- // Fallback to non UTF-8 decoder
- uri = unescape(uri);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Block any javascript: urls or non image data uris
+ if (filteredUrlAttrs[name] && !settings.allow_script_urls) {
+ var uri = value.replace(trimRegExp, '');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (scriptUriRegExp.test(uri)) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ try {
+ // Might throw malformed URI sequence
+ uri = decodeURIComponent(uri);
+ } catch (ex) {
+ // Fallback to non UTF-8 decoder
+ uri = unescape(uri);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!settings.allow_html_data_urls && dataUriRegExp.test(uri) && !/^data:image\//i.test(uri)) {
- return;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (scriptUriRegExp.test(uri)) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add attribute to list and map
- attrList.map[name] = value;
- attrList.push({
- name: name,
- value: value
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!settings.allow_html_data_urls && dataUriRegExp.test(uri) && !/^data:image\//i.test(uri)) {
+ return;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Precompile RegExps and map objects
- tokenRegExp = new RegExp('<(?:' +
- '(?:!--([\\w\\W]*?)-->)|' + // Comment
- '(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|' + // CDATA
- '(?:!DOCTYPE([\\w\\W]*?)>)|' + // DOCTYPE
- '(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|' + // PI
- '(?:\\/([^>]+)>)|' + // End element
- '(?:([A-Za-z0-9\\-_\\:\\.]+)((?:\\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\\/|\\s+)>)' + // Start element
- ')', 'g');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add attribute to list and map
+ attrList.map[name] = value;
+ attrList.push({
+ name: name,
+ value: value
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- attrRegExp = /([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:[^\"])*)\")|(?:\'((?:[^\'])*)\')|([^>\s]+)))?/g;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Precompile RegExps and map objects
+ tokenRegExp = new RegExp('<(?:' +
+ '(?:!--([\\w\\W]*?)-->)|' + // Comment
+ '(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|' + // CDATA
+ '(?:!DOCTYPE([\\w\\W]*?)>)|' + // DOCTYPE
+ '(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|' + // PI
+ '(?:\\/([A-Za-z][A-Za-z0-9\\-_\\:\\.]*)>)|' + // End element
+ '(?:([A-Za-z][A-Za-z0-9\\-_\\:\\.]*)((?:\\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\\/|\\s+)>)' + // Start element
+ ')', 'g');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup lookup tables for empty elements and boolean attributes
- shortEndedElements = schema.getShortEndedElements();
- selfClosing = settings.self_closing_elements || schema.getSelfClosingElements();
- fillAttrsMap = schema.getBoolAttrs();
- validate = settings.validate;
- removeInternalElements = settings.remove_internals;
- fixSelfClosing = settings.fix_self_closing;
- specialElements = schema.getSpecialElements();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ attrRegExp = /([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:[^\"])*)\")|(?:\'((?:[^\'])*)\')|([^>\s]+)))?/g;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while ((matches = tokenRegExp.exec(html))) {
- // Text
- if (index < matches.index) {
- self.text(decode(html.substr(index, matches.index - index)));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup lookup tables for empty elements and boolean attributes
+ shortEndedElements = schema.getShortEndedElements();
+ selfClosing = settings.self_closing_elements || schema.getSelfClosingElements();
+ fillAttrsMap = schema.getBoolAttrs();
+ validate = settings.validate;
+ removeInternalElements = settings.remove_internals;
+ fixSelfClosing = settings.fix_self_closing;
+ specialElements = schema.getSpecialElements();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ((value = matches[6])) { // End element
- value = value.toLowerCase();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while ((matches = tokenRegExp.exec(html + '>'))) { // Adds and extra '>' to keep regexps from doing catastrofic backtracking on malformed html
+ // Text
+ if (index < matches.index) {
+ self.text(decode(html.substr(index, matches.index - index)));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // IE will add a ":" in front of elements it doesn't understand like custom elements or HTML5 elements
- if (value.charAt(0) === ':') {
- value = value.substr(1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((value = matches[6])) { // End element
+ value = value.toLowerCase();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- processEndTag(value);
- } else if ((value = matches[7])) { // Start element
- value = value.toLowerCase();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // IE will add a ":" in front of elements it doesn't understand like custom elements or HTML5 elements
+ if (value.charAt(0) === ':') {
+ value = value.substr(1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // IE will add a ":" in front of elements it doesn't understand like custom elements or HTML5 elements
- if (value.charAt(0) === ':') {
- value = value.substr(1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ processEndTag(value);
+ } else if ((value = matches[7])) { // Start element
+ // Did we consume the extra character then treat it as text
+ // This handles the case with html like this: "text a<b text"
+ if (matches.index + matches[0].length > html.length) {
+ self.text(decode(html.substr(matches.index)));
+ index = matches.index + matches[0].length;
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- isShortEnded = value in shortEndedElements;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ value = value.toLowerCase();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Is self closing tag for example an <li> after an open <li>
- if (fixSelfClosing && selfClosing[value] && stack.length > 0 && stack[stack.length - 1].name === value) {
- processEndTag(value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // IE will add a ":" in front of elements it doesn't understand like custom elements or HTML5 elements
+ if (value.charAt(0) === ':') {
+ value = value.substr(1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Validate element
- if (!validate || (elementRule = schema.getElementRule(value))) {
- isValidElement = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ isShortEnded = value in shortEndedElements;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Grab attributes map and patters when validation is enabled
- if (validate) {
- validAttributesMap = elementRule.attributes;
- validAttributePatterns = elementRule.attributePatterns;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Is self closing tag for example an <li> after an open <li>
+ if (fixSelfClosing && selfClosing[value] && stack.length > 0 && stack[stack.length - 1].name === value) {
+ processEndTag(value);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Parse attributes
- if ((attribsValue = matches[8])) {
- isInternalElement = attribsValue.indexOf('data-mce-type') !== -1; // Check if the element is an internal element
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Validate element
+ if (!validate || (elementRule = schema.getElementRule(value))) {
+ isValidElement = true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If the element has internal attributes then remove it if we are told to do so
- if (isInternalElement && removeInternalElements) {
- isValidElement = false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Grab attributes map and patters when validation is enabled
+ if (validate) {
+ validAttributesMap = elementRule.attributes;
+ validAttributePatterns = elementRule.attributePatterns;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- attrList = [];
- attrList.map = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Parse attributes
+ if ((attribsValue = matches[8])) {
+ isInternalElement = attribsValue.indexOf('data-mce-type') !== -1; // Check if the element is an internal element
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- attribsValue.replace(attrRegExp, parseAttribute);
- } else {
- attrList = [];
- attrList.map = {};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If the element has internal attributes then remove it if we are told to do so
+ if (isInternalElement && removeInternalElements) {
+ isValidElement = false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Process attributes if validation is enabled
- if (validate && !isInternalElement) {
- attributesRequired = elementRule.attributesRequired;
- attributesDefault = elementRule.attributesDefault;
- attributesForced = elementRule.attributesForced;
- anyAttributesRequired = elementRule.removeEmptyAttrs;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ attrList = [];
+ attrList.map = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if any attribute exists
- if (anyAttributesRequired && !attrList.length) {
- isValidElement = false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ attribsValue.replace(attrRegExp, parseAttribute);
+ } else {
+ attrList = [];
+ attrList.map = {};
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle forced attributes
- if (attributesForced) {
- i = attributesForced.length;
- while (i--) {
- attr = attributesForced[i];
- name = attr.name;
- attrValue = attr.value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Process attributes if validation is enabled
+ if (validate && !isInternalElement) {
+ attributesRequired = elementRule.attributesRequired;
+ attributesDefault = elementRule.attributesDefault;
+ attributesForced = elementRule.attributesForced;
+ anyAttributesRequired = elementRule.removeEmptyAttrs;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (attrValue === '{$uid}') {
- attrValue = 'mce_' + idCount++;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if any attribute exists
+ if (anyAttributesRequired && !attrList.length) {
+ isValidElement = false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- attrList.map[name] = attrValue;
- attrList.push({name: name, value: attrValue});
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handle forced attributes
+ if (attributesForced) {
+ i = attributesForced.length;
+ while (i--) {
+ attr = attributesForced[i];
+ name = attr.name;
+ attrValue = attr.value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle default attributes
- if (attributesDefault) {
- i = attributesDefault.length;
- while (i--) {
- attr = attributesDefault[i];
- name = attr.name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (attrValue === '{$uid}') {
+ attrValue = 'mce_' + idCount++;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!(name in attrList.map)) {
- attrValue = attr.value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ attrList.map[name] = attrValue;
+ attrList.push({ name: name, value: attrValue });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (attrValue === '{$uid}') {
- attrValue = 'mce_' + idCount++;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handle default attributes
+ if (attributesDefault) {
+ i = attributesDefault.length;
+ while (i--) {
+ attr = attributesDefault[i];
+ name = attr.name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- attrList.map[name] = attrValue;
- attrList.push({name: name, value: attrValue});
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!(name in attrList.map)) {
+ attrValue = attr.value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle required attributes
- if (attributesRequired) {
- i = attributesRequired.length;
- while (i--) {
- if (attributesRequired[i] in attrList.map) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (attrValue === '{$uid}') {
+ attrValue = 'mce_' + idCount++;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // None of the required attributes where found
- if (i === -1) {
- isValidElement = false;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ attrList.map[name] = attrValue;
+ attrList.push({ name: name, value: attrValue });
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Invalidate element if it's marked as bogus
- if ((attr = attrList.map['data-mce-bogus'])) {
- if (attr === 'all') {
- index = findEndTag(schema, html, tokenRegExp.lastIndex);
- tokenRegExp.lastIndex = index;
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handle required attributes
+ if (attributesRequired) {
+ i = attributesRequired.length;
+ while (i--) {
+ if (attributesRequired[i] in attrList.map) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- isValidElement = false;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // None of the required attributes where found
+ if (i === -1) {
+ isValidElement = false;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isValidElement) {
- self.start(value, attrList, isShortEnded);
- }
- } else {
- isValidElement = false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Invalidate element if it's marked as bogus
+ if ((attr = attrList.map['data-mce-bogus'])) {
+ if (attr === 'all') {
+ index = findEndTag(schema, html, tokenRegExp.lastIndex);
+ tokenRegExp.lastIndex = index;
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Treat script, noscript and style a bit different since they may include code that looks like elements
- if ((endRegExp = specialElements[value])) {
- endRegExp.lastIndex = index = matches.index + matches[0].length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ isValidElement = false;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ((matches = endRegExp.exec(html))) {
- if (isValidElement) {
- text = html.substr(index, matches.index - index);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isValidElement) {
+ self.start(value, attrList, isShortEnded);
+ }
+ } else {
+ isValidElement = false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- index = matches.index + matches[0].length;
- } else {
- text = html.substr(index);
- index = html.length;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Treat script, noscript and style a bit different since they may include code that looks like elements
+ if ((endRegExp = specialElements[value])) {
+ endRegExp.lastIndex = index = matches.index + matches[0].length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isValidElement) {
- if (text.length > 0) {
- self.text(text, true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((matches = endRegExp.exec(html))) {
+ if (isValidElement) {
+ text = html.substr(index, matches.index - index);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.end(value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ index = matches.index + matches[0].length;
+ } else {
+ text = html.substr(index);
+ index = html.length;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tokenRegExp.lastIndex = index;
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isValidElement) {
+ if (text.length > 0) {
+ self.text(text, true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Push value on to stack
- if (!isShortEnded) {
- if (!attribsValue || attribsValue.indexOf('/') != attribsValue.length - 1) {
- stack.push({name: value, valid: isValidElement});
- } else if (isValidElement) {
- self.end(value);
- }
- }
- } else if ((value = matches[1])) { // Comment
- // Padd comment value to avoid browsers from parsing invalid comments as HTML
- if (value.charAt(0) === '>') {
- value = ' ' + value;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.end(value);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!settings.allow_conditional_comments && value.substr(0, 3).toLowerCase() === '[if') {
- value = ' ' + value;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ tokenRegExp.lastIndex = index;
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.comment(value);
- } else if ((value = matches[2])) { // CDATA
- self.cdata(value);
- } else if ((value = matches[3])) { // DOCTYPE
- self.doctype(value);
- } else if ((value = matches[4])) { // PI
- self.pi(value, matches[5]);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Push value on to stack
+ if (!isShortEnded) {
+ if (!attribsValue || attribsValue.indexOf('/') != attribsValue.length - 1) {
+ stack.push({ name: value, valid: isValidElement });
+ } else if (isValidElement) {
+ self.end(value);
+ }
+ }
+ } else if ((value = matches[1])) { // Comment
+ // Padd comment value to avoid browsers from parsing invalid comments as HTML
+ if (value.charAt(0) === '>') {
+ value = ' ' + value;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- index = matches.index + matches[0].length;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!settings.allow_conditional_comments && value.substr(0, 3).toLowerCase() === '[if') {
+ value = ' ' + value;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Text
- if (index < html.length) {
- self.text(decode(html.substr(index)));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.comment(value);
+ } else if ((value = matches[2])) { // CDATA
+ self.cdata(value);
+ } else if ((value = matches[3])) { // DOCTYPE
+ self.doctype(value);
+ } else if ((value = matches[4])) { // PI
+ self.pi(value, matches[5]);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Close any open elements
- for (i = stack.length - 1; i >= 0; i--) {
- value = stack[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ index = matches.index + matches[0].length;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value.valid) {
- self.end(value.name);
- }
- }
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Text
+ if (index < html.length) {
+ self.text(decode(html.substr(index)));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- SaxParser.findEndTag = findEndTag;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Close any open elements
+ for (i = stack.length - 1; i >= 0; i--) {
+ value = stack[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return SaxParser;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value.valid) {
+ self.end(value.name);
+ }
+ }
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/html/DomParser.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ SaxParser.findEndTag = findEndTag;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return SaxParser;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * DomParser.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -13183,881 +14104,883 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.html.DomParser
</span><span class="cx" style="display: block; padding: 0 10px"> * @version 3.4
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/html/DomParser", [
- "tinymce/html/Node",
- "tinymce/html/Schema",
- "tinymce/html/SaxParser",
- "tinymce/util/Tools"
-], function(Node, Schema, SaxParser, Tools) {
- var makeMap = Tools.makeMap, each = Tools.each, explode = Tools.explode, extend = Tools.extend;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.html.DomParser',
+ [
+ "tinymce.core.html.Node",
+ "tinymce.core.html.Schema",
+ "tinymce.core.html.SaxParser",
+ "tinymce.core.util.Tools"
+ ],
+ function (Node, Schema, SaxParser, Tools) {
+ var makeMap = Tools.makeMap, each = Tools.each, explode = Tools.explode, extend = Tools.extend;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var paddEmptyNode = function (settings, node) {
- if (settings.padd_empty_with_br) {
- node.empty().append(new Node('br', '1')).shortEnded = true;
- } else {
- node.empty().append(new Node('#text', '3')).value = '\u00a0';
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var paddEmptyNode = function (settings, node) {
+ if (settings.padd_empty_with_br) {
+ node.empty().append(new Node('br', '1')).shortEnded = true;
+ } else {
+ node.empty().append(new Node('#text', '3')).value = '\u00a0';
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var hasOnlyChild = function (node, name) {
- return node && node.firstChild === node.lastChild && node.firstChild.name === name;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var hasOnlyChild = function (node, name) {
+ return node && node.firstChild === node.lastChild && node.firstChild.name === name;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a new DomParser instance.
- *
- * @constructor
- * @method DomParser
- * @param {Object} settings Name/value collection of settings. comment, cdata, text, start and end are callbacks.
- * @param {tinymce.html.Schema} schema HTML Schema class to use when parsing.
- */
- return function(settings, schema) {
- var self = this, nodeFilters = {}, attributeFilters = [], matchedNodes = {}, matchedAttributes = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a new DomParser instance.
+ *
+ * @constructor
+ * @method DomParser
+ * @param {Object} settings Name/value collection of settings. comment, cdata, text, start and end are callbacks.
+ * @param {tinymce.html.Schema} schema HTML Schema class to use when parsing.
+ */
+ return function (settings, schema) {
+ var self = this, nodeFilters = {}, attributeFilters = [], matchedNodes = {}, matchedAttributes = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- settings = settings || {};
- settings.validate = "validate" in settings ? settings.validate : true;
- settings.root_name = settings.root_name || 'body';
- self.schema = schema = schema || new Schema();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ settings = settings || {};
+ settings.validate = "validate" in settings ? settings.validate : true;
+ settings.root_name = settings.root_name || 'body';
+ self.schema = schema = schema || new Schema();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function fixInvalidChildren(nodes) {
- var ni, node, parent, parents, newParent, currentNode, tempNode, childNode, i;
- var nonEmptyElements, whitespaceElements, nonSplitableElements, textBlockElements, specialElements, sibling, nextNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function fixInvalidChildren(nodes) {
+ var ni, node, parent, parents, newParent, currentNode, tempNode, childNode, i;
+ var nonEmptyElements, whitespaceElements, nonSplitableElements, textBlockElements, specialElements, sibling, nextNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- nonSplitableElements = makeMap('tr,td,th,tbody,thead,tfoot,table');
- nonEmptyElements = schema.getNonEmptyElements();
- whitespaceElements = schema.getWhiteSpaceElements();
- textBlockElements = schema.getTextBlockElements();
- specialElements = schema.getSpecialElements();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ nonSplitableElements = makeMap('tr,td,th,tbody,thead,tfoot,table');
+ nonEmptyElements = schema.getNonEmptyElements();
+ whitespaceElements = schema.getWhiteSpaceElements();
+ textBlockElements = schema.getTextBlockElements();
+ specialElements = schema.getSpecialElements();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (ni = 0; ni < nodes.length; ni++) {
- node = nodes[ni];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (ni = 0; ni < nodes.length; ni++) {
+ node = nodes[ni];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Already removed or fixed
- if (!node.parent || node.fixed) {
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Already removed or fixed
+ if (!node.parent || node.fixed) {
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If the invalid element is a text block and the text block is within a parent LI element
- // Then unwrap the first text block and convert other sibling text blocks to LI elements similar to Word/Open Office
- if (textBlockElements[node.name] && node.parent.name == 'li') {
- // Move sibling text blocks after LI element
- sibling = node.next;
- while (sibling) {
- if (textBlockElements[sibling.name]) {
- sibling.name = 'li';
- sibling.fixed = true;
- node.parent.insert(sibling, node.parent);
- } else {
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If the invalid element is a text block and the text block is within a parent LI element
+ // Then unwrap the first text block and convert other sibling text blocks to LI elements similar to Word/Open Office
+ if (textBlockElements[node.name] && node.parent.name == 'li') {
+ // Move sibling text blocks after LI element
+ sibling = node.next;
+ while (sibling) {
+ if (textBlockElements[sibling.name]) {
+ sibling.name = 'li';
+ sibling.fixed = true;
+ node.parent.insert(sibling, node.parent);
+ } else {
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- sibling = sibling.next;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ sibling = sibling.next;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Unwrap current text block
- node.unwrap(node);
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Unwrap current text block
+ node.unwrap(node);
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Get list of all parent nodes until we find a valid parent to stick the child into
- parents = [node];
- for (parent = node.parent; parent && !schema.isValidChild(parent.name, node.name) &&
- !nonSplitableElements[parent.name]; parent = parent.parent) {
- parents.push(parent);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get list of all parent nodes until we find a valid parent to stick the child into
+ parents = [node];
+ for (parent = node.parent; parent && !schema.isValidChild(parent.name, node.name) &&
+ !nonSplitableElements[parent.name]; parent = parent.parent) {
+ parents.push(parent);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Found a suitable parent
- if (parent && parents.length > 1) {
- // Reverse the array since it makes looping easier
- parents.reverse();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Found a suitable parent
+ if (parent && parents.length > 1) {
+ // Reverse the array since it makes looping easier
+ parents.reverse();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Clone the related parent and insert that after the moved node
- newParent = currentNode = self.filterNode(parents[0].clone());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Clone the related parent and insert that after the moved node
+ newParent = currentNode = self.filterNode(parents[0].clone());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Start cloning and moving children on the left side of the target node
- for (i = 0; i < parents.length - 1; i++) {
- if (schema.isValidChild(currentNode.name, parents[i].name)) {
- tempNode = self.filterNode(parents[i].clone());
- currentNode.append(tempNode);
- } else {
- tempNode = currentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Start cloning and moving children on the left side of the target node
+ for (i = 0; i < parents.length - 1; i++) {
+ if (schema.isValidChild(currentNode.name, parents[i].name)) {
+ tempNode = self.filterNode(parents[i].clone());
+ currentNode.append(tempNode);
+ } else {
+ tempNode = currentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (childNode = parents[i].firstChild; childNode && childNode != parents[i + 1];) {
- nextNode = childNode.next;
- tempNode.append(childNode);
- childNode = nextNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (childNode = parents[i].firstChild; childNode && childNode != parents[i + 1];) {
+ nextNode = childNode.next;
+ tempNode.append(childNode);
+ childNode = nextNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- currentNode = tempNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ currentNode = tempNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!newParent.isEmpty(nonEmptyElements, whitespaceElements)) {
- parent.insert(newParent, parents[0], true);
- parent.insert(node, newParent);
- } else {
- parent.insert(node, parents[0], true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!newParent.isEmpty(nonEmptyElements, whitespaceElements)) {
+ parent.insert(newParent, parents[0], true);
+ parent.insert(node, newParent);
+ } else {
+ parent.insert(node, parents[0], true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if the element is empty by looking through it's contents and special treatment for <p><br /></p>
- parent = parents[0];
- if (parent.isEmpty(nonEmptyElements, whitespaceElements) || hasOnlyChild(parent, 'br')) {
- parent.empty().remove();
- }
- } else if (node.parent) {
- // If it's an LI try to find a UL/OL for it or wrap it
- if (node.name === 'li') {
- sibling = node.prev;
- if (sibling && (sibling.name === 'ul' || sibling.name === 'ul')) {
- sibling.append(node);
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if the element is empty by looking through it's contents and special treatment for <p><br /></p>
+ parent = parents[0];
+ if (parent.isEmpty(nonEmptyElements, whitespaceElements) || hasOnlyChild(parent, 'br')) {
+ parent.empty().remove();
+ }
+ } else if (node.parent) {
+ // If it's an LI try to find a UL/OL for it or wrap it
+ if (node.name === 'li') {
+ sibling = node.prev;
+ if (sibling && (sibling.name === 'ul' || sibling.name === 'ul')) {
+ sibling.append(node);
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- sibling = node.next;
- if (sibling && (sibling.name === 'ul' || sibling.name === 'ul')) {
- sibling.insert(node, sibling.firstChild, true);
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ sibling = node.next;
+ if (sibling && (sibling.name === 'ul' || sibling.name === 'ul')) {
+ sibling.insert(node, sibling.firstChild, true);
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node.wrap(self.filterNode(new Node('ul', 1)));
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node.wrap(self.filterNode(new Node('ul', 1)));
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Try wrapping the element in a DIV
- if (schema.isValidChild(node.parent.name, 'div') && schema.isValidChild('div', node.name)) {
- node.wrap(self.filterNode(new Node('div', 1)));
- } else {
- // We failed wrapping it, then remove or unwrap it
- if (specialElements[node.name]) {
- node.empty().remove();
- } else {
- node.unwrap();
- }
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Try wrapping the element in a DIV
+ if (schema.isValidChild(node.parent.name, 'div') && schema.isValidChild('div', node.name)) {
+ node.wrap(self.filterNode(new Node('div', 1)));
+ } else {
+ // We failed wrapping it, then remove or unwrap it
+ if (specialElements[node.name]) {
+ node.empty().remove();
+ } else {
+ node.unwrap();
+ }
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Runs the specified node though the element and attributes filters.
- *
- * @method filterNode
- * @param {tinymce.html.Node} Node the node to run filters on.
- * @return {tinymce.html.Node} The passed in node.
- */
- self.filterNode = function(node) {
- var i, name, list;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Runs the specified node though the element and attributes filters.
+ *
+ * @method filterNode
+ * @param {tinymce.html.Node} Node the node to run filters on.
+ * @return {tinymce.html.Node} The passed in node.
+ */
+ self.filterNode = function (node) {
+ var i, name, list;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Run element filters
- if (name in nodeFilters) {
- list = matchedNodes[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Run element filters
+ if (name in nodeFilters) {
+ list = matchedNodes[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (list) {
- list.push(node);
- } else {
- matchedNodes[name] = [node];
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (list) {
+ list.push(node);
+ } else {
+ matchedNodes[name] = [node];
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Run attribute filters
- i = attributeFilters.length;
- while (i--) {
- name = attributeFilters[i].name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Run attribute filters
+ i = attributeFilters.length;
+ while (i--) {
+ name = attributeFilters[i].name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name in node.attributes.map) {
- list = matchedAttributes[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name in node.attributes.map) {
+ list = matchedAttributes[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (list) {
- list.push(node);
- } else {
- matchedAttributes[name] = [node];
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (list) {
+ list.push(node);
+ } else {
+ matchedAttributes[name] = [node];
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return node;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return node;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds a node filter function to the parser, the parser will collect the specified nodes by name
- * and then execute the callback ones it has finished parsing the document.
- *
- * @example
- * parser.addNodeFilter('p,h1', function(nodes, name) {
- * for (var i = 0; i < nodes.length; i++) {
- * console.log(nodes[i].name);
- * }
- * });
- * @method addNodeFilter
- * @method {String} name Comma separated list of nodes to collect.
- * @param {function} callback Callback function to execute once it has collected nodes.
- */
- self.addNodeFilter = function(name, callback) {
- each(explode(name), function(name) {
- var list = nodeFilters[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds a node filter function to the parser, the parser will collect the specified nodes by name
+ * and then execute the callback ones it has finished parsing the document.
+ *
+ * @example
+ * parser.addNodeFilter('p,h1', function(nodes, name) {
+ * for (var i = 0; i < nodes.length; i++) {
+ * console.log(nodes[i].name);
+ * }
+ * });
+ * @method addNodeFilter
+ * @method {String} name Comma separated list of nodes to collect.
+ * @param {function} callback Callback function to execute once it has collected nodes.
+ */
+ self.addNodeFilter = function (name, callback) {
+ each(explode(name), function (name) {
+ var list = nodeFilters[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!list) {
- nodeFilters[name] = list = [];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!list) {
+ nodeFilters[name] = list = [];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- list.push(callback);
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ list.push(callback);
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds a attribute filter function to the parser, the parser will collect nodes that has the specified attributes
- * and then execute the callback ones it has finished parsing the document.
- *
- * @example
- * parser.addAttributeFilter('src,href', function(nodes, name) {
- * for (var i = 0; i < nodes.length; i++) {
- * console.log(nodes[i].name);
- * }
- * });
- * @method addAttributeFilter
- * @method {String} name Comma separated list of nodes to collect.
- * @param {function} callback Callback function to execute once it has collected nodes.
- */
- self.addAttributeFilter = function(name, callback) {
- each(explode(name), function(name) {
- var i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds a attribute filter function to the parser, the parser will collect nodes that has the specified attributes
+ * and then execute the callback ones it has finished parsing the document.
+ *
+ * @example
+ * parser.addAttributeFilter('src,href', function(nodes, name) {
+ * for (var i = 0; i < nodes.length; i++) {
+ * console.log(nodes[i].name);
+ * }
+ * });
+ * @method addAttributeFilter
+ * @method {String} name Comma separated list of nodes to collect.
+ * @param {function} callback Callback function to execute once it has collected nodes.
+ */
+ self.addAttributeFilter = function (name, callback) {
+ each(explode(name), function (name) {
+ var i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0; i < attributeFilters.length; i++) {
- if (attributeFilters[i].name === name) {
- attributeFilters[i].callbacks.push(callback);
- return;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0; i < attributeFilters.length; i++) {
+ if (attributeFilters[i].name === name) {
+ attributeFilters[i].callbacks.push(callback);
+ return;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- attributeFilters.push({name: name, callbacks: [callback]});
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ attributeFilters.push({ name: name, callbacks: [callback] });
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Parses the specified HTML string into a DOM like node tree and returns the result.
- *
- * @example
- * var rootNode = new DomParser({...}).parse('<b>text</b>');
- * @method parse
- * @param {String} html Html string to sax parse.
- * @param {Object} args Optional args object that gets passed to all filter functions.
- * @return {tinymce.html.Node} Root node containing the tree.
- */
- self.parse = function(html, args) {
- var parser, rootNode, node, nodes, i, l, fi, fl, list, name, validate;
- var blockElements, startWhiteSpaceRegExp, invalidChildren = [], isInWhiteSpacePreservedElement;
- var endWhiteSpaceRegExp, allWhiteSpaceRegExp, isAllWhiteSpaceRegExp, whiteSpaceElements;
- var children, nonEmptyElements, rootBlockName;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Parses the specified HTML string into a DOM like node tree and returns the result.
+ *
+ * @example
+ * var rootNode = new DomParser({...}).parse('<b>text</b>');
+ * @method parse
+ * @param {String} html Html string to sax parse.
+ * @param {Object} args Optional args object that gets passed to all filter functions.
+ * @return {tinymce.html.Node} Root node containing the tree.
+ */
+ self.parse = function (html, args) {
+ var parser, rootNode, node, nodes, i, l, fi, fl, list, name, validate;
+ var blockElements, startWhiteSpaceRegExp, invalidChildren = [], isInWhiteSpacePreservedElement;
+ var endWhiteSpaceRegExp, allWhiteSpaceRegExp, isAllWhiteSpaceRegExp, whiteSpaceElements;
+ var children, nonEmptyElements, rootBlockName;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args = args || {};
- matchedNodes = {};
- matchedAttributes = {};
- blockElements = extend(makeMap('script,style,head,html,body,title,meta,param'), schema.getBlockElements());
- nonEmptyElements = schema.getNonEmptyElements();
- children = schema.children;
- validate = settings.validate;
- rootBlockName = "forced_root_block" in args ? args.forced_root_block : settings.forced_root_block;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args = args || {};
+ matchedNodes = {};
+ matchedAttributes = {};
+ blockElements = extend(makeMap('script,style,head,html,body,title,meta,param'), schema.getBlockElements());
+ nonEmptyElements = schema.getNonEmptyElements();
+ children = schema.children;
+ validate = settings.validate;
+ rootBlockName = "forced_root_block" in args ? args.forced_root_block : settings.forced_root_block;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- whiteSpaceElements = schema.getWhiteSpaceElements();
- startWhiteSpaceRegExp = /^[ \t\r\n]+/;
- endWhiteSpaceRegExp = /[ \t\r\n]+$/;
- allWhiteSpaceRegExp = /[ \t\r\n]+/g;
- isAllWhiteSpaceRegExp = /^[ \t\r\n]+$/;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ whiteSpaceElements = schema.getWhiteSpaceElements();
+ startWhiteSpaceRegExp = /^[ \t\r\n]+/;
+ endWhiteSpaceRegExp = /[ \t\r\n]+$/;
+ allWhiteSpaceRegExp = /[ \t\r\n]+/g;
+ isAllWhiteSpaceRegExp = /^[ \t\r\n]+$/;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function addRootBlocks() {
- var node = rootNode.firstChild, next, rootBlockNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function addRootBlocks() {
+ var node = rootNode.firstChild, next, rootBlockNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Removes whitespace at beginning and end of block so:
- // <p> x </p> -> <p>x</p>
- function trim(rootBlockNode) {
- if (rootBlockNode) {
- node = rootBlockNode.firstChild;
- if (node && node.type == 3) {
- node.value = node.value.replace(startWhiteSpaceRegExp, '');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Removes whitespace at beginning and end of block so:
+ // <p> x </p> -> <p>x</p>
+ function trim(rootBlockNode) {
+ if (rootBlockNode) {
+ node = rootBlockNode.firstChild;
+ if (node && node.type == 3) {
+ node.value = node.value.replace(startWhiteSpaceRegExp, '');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = rootBlockNode.lastChild;
- if (node && node.type == 3) {
- node.value = node.value.replace(endWhiteSpaceRegExp, '');
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = rootBlockNode.lastChild;
+ if (node && node.type == 3) {
+ node.value = node.value.replace(endWhiteSpaceRegExp, '');
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if rootBlock is valid within rootNode for example if P is valid in H1 if H1 is the contentEditabe root
- if (!schema.isValidChild(rootNode.name, rootBlockName.toLowerCase())) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if rootBlock is valid within rootNode for example if P is valid in H1 if H1 is the contentEditabe root
+ if (!schema.isValidChild(rootNode.name, rootBlockName.toLowerCase())) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (node) {
- next = node.next;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (node) {
+ next = node.next;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.type == 3 || (node.type == 1 && node.name !== 'p' &&
- !blockElements[node.name] && !node.attr('data-mce-type'))) {
- if (!rootBlockNode) {
- // Create a new root block element
- rootBlockNode = createNode(rootBlockName, 1);
- rootBlockNode.attr(settings.forced_root_block_attrs);
- rootNode.insert(rootBlockNode, node);
- rootBlockNode.append(node);
- } else {
- rootBlockNode.append(node);
- }
- } else {
- trim(rootBlockNode);
- rootBlockNode = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.type == 3 || (node.type == 1 && node.name !== 'p' &&
+ !blockElements[node.name] && !node.attr('data-mce-type'))) {
+ if (!rootBlockNode) {
+ // Create a new root block element
+ rootBlockNode = createNode(rootBlockName, 1);
+ rootBlockNode.attr(settings.forced_root_block_attrs);
+ rootNode.insert(rootBlockNode, node);
+ rootBlockNode.append(node);
+ } else {
+ rootBlockNode.append(node);
+ }
+ } else {
+ trim(rootBlockNode);
+ rootBlockNode = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = next;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = next;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- trim(rootBlockNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ trim(rootBlockNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function createNode(name, type) {
- var node = new Node(name, type), list;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function createNode(name, type) {
+ var node = new Node(name, type), list;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name in nodeFilters) {
- list = matchedNodes[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name in nodeFilters) {
+ list = matchedNodes[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (list) {
- list.push(node);
- } else {
- matchedNodes[name] = [node];
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (list) {
+ list.push(node);
+ } else {
+ matchedNodes[name] = [node];
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function removeWhitespaceBefore(node) {
- var textNode, textNodeNext, textVal, sibling, blockElements = schema.getBlockElements();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function removeWhitespaceBefore(node) {
+ var textNode, textNodeNext, textVal, sibling, blockElements = schema.getBlockElements();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (textNode = node.prev; textNode && textNode.type === 3;) {
- textVal = textNode.value.replace(endWhiteSpaceRegExp, '');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (textNode = node.prev; textNode && textNode.type === 3;) {
+ textVal = textNode.value.replace(endWhiteSpaceRegExp, '');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Found a text node with non whitespace then trim that and break
- if (textVal.length > 0) {
- textNode.value = textVal;
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Found a text node with non whitespace then trim that and break
+ if (textVal.length > 0) {
+ textNode.value = textVal;
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- textNodeNext = textNode.next;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ textNodeNext = textNode.next;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Fix for bug #7543 where bogus nodes would produce empty
- // text nodes and these would be removed if a nested list was before it
- if (textNodeNext) {
- if (textNodeNext.type == 3 && textNodeNext.value.length) {
- textNode = textNode.prev;
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Fix for bug #7543 where bogus nodes would produce empty
+ // text nodes and these would be removed if a nested list was before it
+ if (textNodeNext) {
+ if (textNodeNext.type == 3 && textNodeNext.value.length) {
+ textNode = textNode.prev;
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!blockElements[textNodeNext.name] && textNodeNext.name != 'script' && textNodeNext.name != 'style') {
- textNode = textNode.prev;
- continue;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!blockElements[textNodeNext.name] && textNodeNext.name != 'script' && textNodeNext.name != 'style') {
+ textNode = textNode.prev;
+ continue;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- sibling = textNode.prev;
- textNode.remove();
- textNode = sibling;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ sibling = textNode.prev;
+ textNode.remove();
+ textNode = sibling;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function cloneAndExcludeBlocks(input) {
- var name, output = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function cloneAndExcludeBlocks(input) {
+ var name, output = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (name in input) {
- if (name !== 'li' && name != 'p') {
- output[name] = input[name];
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (name in input) {
+ if (name !== 'li' && name != 'p') {
+ output[name] = input[name];
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return output;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return output;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parser = new SaxParser({
- validate: validate,
- allow_script_urls: settings.allow_script_urls,
- allow_conditional_comments: settings.allow_conditional_comments,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parser = new SaxParser({
+ validate: validate,
+ allow_script_urls: settings.allow_script_urls,
+ allow_conditional_comments: settings.allow_conditional_comments,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Exclude P and LI from DOM parsing since it's treated better by the DOM parser
- self_closing_elements: cloneAndExcludeBlocks(schema.getSelfClosingElements()),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Exclude P and LI from DOM parsing since it's treated better by the DOM parser
+ self_closing_elements: cloneAndExcludeBlocks(schema.getSelfClosingElements()),
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- cdata: function(text) {
- node.append(createNode('#cdata', 4)).value = text;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ cdata: function (text) {
+ node.append(createNode('#cdata', 4)).value = text;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- text: function(text, raw) {
- var textNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ text: function (text, raw) {
+ var textNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Trim all redundant whitespace on non white space elements
- if (!isInWhiteSpacePreservedElement) {
- text = text.replace(allWhiteSpaceRegExp, ' ');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Trim all redundant whitespace on non white space elements
+ if (!isInWhiteSpacePreservedElement) {
+ text = text.replace(allWhiteSpaceRegExp, ' ');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.lastChild && blockElements[node.lastChild.name]) {
- text = text.replace(startWhiteSpaceRegExp, '');
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.lastChild && blockElements[node.lastChild.name]) {
+ text = text.replace(startWhiteSpaceRegExp, '');
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Do we need to create the node
- if (text.length !== 0) {
- textNode = createNode('#text', 3);
- textNode.raw = !!raw;
- node.append(textNode).value = text;
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Do we need to create the node
+ if (text.length !== 0) {
+ textNode = createNode('#text', 3);
+ textNode.raw = !!raw;
+ node.append(textNode).value = text;
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- comment: function(text) {
- node.append(createNode('#comment', 8)).value = text;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ comment: function (text) {
+ node.append(createNode('#comment', 8)).value = text;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- pi: function(name, text) {
- node.append(createNode(name, 7)).value = text;
- removeWhitespaceBefore(node);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ pi: function (name, text) {
+ node.append(createNode(name, 7)).value = text;
+ removeWhitespaceBefore(node);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- doctype: function(text) {
- var newNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ doctype: function (text) {
+ var newNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- newNode = node.append(createNode('#doctype', 10));
- newNode.value = text;
- removeWhitespaceBefore(node);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ newNode = node.append(createNode('#doctype', 10));
+ newNode.value = text;
+ removeWhitespaceBefore(node);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- start: function(name, attrs, empty) {
- var newNode, attrFiltersLen, elementRule, attrName, parent;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ start: function (name, attrs, empty) {
+ var newNode, attrFiltersLen, elementRule, attrName, parent;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elementRule = validate ? schema.getElementRule(name) : {};
- if (elementRule) {
- newNode = createNode(elementRule.outputName || name, 1);
- newNode.attributes = attrs;
- newNode.shortEnded = empty;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elementRule = validate ? schema.getElementRule(name) : {};
+ if (elementRule) {
+ newNode = createNode(elementRule.outputName || name, 1);
+ newNode.attributes = attrs;
+ newNode.shortEnded = empty;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node.append(newNode);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node.append(newNode);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if node is valid child of the parent node is the child is
- // unknown we don't collect it since it's probably a custom element
- parent = children[node.name];
- if (parent && children[newNode.name] && !parent[newNode.name]) {
- invalidChildren.push(newNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if node is valid child of the parent node is the child is
+ // unknown we don't collect it since it's probably a custom element
+ parent = children[node.name];
+ if (parent && children[newNode.name] && !parent[newNode.name]) {
+ invalidChildren.push(newNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- attrFiltersLen = attributeFilters.length;
- while (attrFiltersLen--) {
- attrName = attributeFilters[attrFiltersLen].name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ attrFiltersLen = attributeFilters.length;
+ while (attrFiltersLen--) {
+ attrName = attributeFilters[attrFiltersLen].name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (attrName in attrs.map) {
- list = matchedAttributes[attrName];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (attrName in attrs.map) {
+ list = matchedAttributes[attrName];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (list) {
- list.push(newNode);
- } else {
- matchedAttributes[attrName] = [newNode];
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (list) {
+ list.push(newNode);
+ } else {
+ matchedAttributes[attrName] = [newNode];
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Trim whitespace before block
- if (blockElements[name]) {
- removeWhitespaceBefore(newNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Trim whitespace before block
+ if (blockElements[name]) {
+ removeWhitespaceBefore(newNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Change current node if the element wasn't empty i.e not <br /> or <img />
- if (!empty) {
- node = newNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Change current node if the element wasn't empty i.e not <br /> or <img />
+ if (!empty) {
+ node = newNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if we are inside a whitespace preserved element
- if (!isInWhiteSpacePreservedElement && whiteSpaceElements[name]) {
- isInWhiteSpacePreservedElement = true;
- }
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if we are inside a whitespace preserved element
+ if (!isInWhiteSpacePreservedElement && whiteSpaceElements[name]) {
+ isInWhiteSpacePreservedElement = true;
+ }
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- end: function(name) {
- var textNode, elementRule, text, sibling, tempNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ end: function (name) {
+ var textNode, elementRule, text, sibling, tempNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elementRule = validate ? schema.getElementRule(name) : {};
- if (elementRule) {
- if (blockElements[name]) {
- if (!isInWhiteSpacePreservedElement) {
- // Trim whitespace of the first node in a block
- textNode = node.firstChild;
- if (textNode && textNode.type === 3) {
- text = textNode.value.replace(startWhiteSpaceRegExp, '');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elementRule = validate ? schema.getElementRule(name) : {};
+ if (elementRule) {
+ if (blockElements[name]) {
+ if (!isInWhiteSpacePreservedElement) {
+ // Trim whitespace of the first node in a block
+ textNode = node.firstChild;
+ if (textNode && textNode.type === 3) {
+ text = textNode.value.replace(startWhiteSpaceRegExp, '');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Any characters left after trim or should we remove it
- if (text.length > 0) {
- textNode.value = text;
- textNode = textNode.next;
- } else {
- sibling = textNode.next;
- textNode.remove();
- textNode = sibling;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Any characters left after trim or should we remove it
+ if (text.length > 0) {
+ textNode.value = text;
+ textNode = textNode.next;
+ } else {
+ sibling = textNode.next;
+ textNode.remove();
+ textNode = sibling;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove any pure whitespace siblings
- while (textNode && textNode.type === 3) {
- text = textNode.value;
- sibling = textNode.next;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove any pure whitespace siblings
+ while (textNode && textNode.type === 3) {
+ text = textNode.value;
+ sibling = textNode.next;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (text.length === 0 || isAllWhiteSpaceRegExp.test(text)) {
- textNode.remove();
- textNode = sibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (text.length === 0 || isAllWhiteSpaceRegExp.test(text)) {
+ textNode.remove();
+ textNode = sibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- textNode = sibling;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ textNode = sibling;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Trim whitespace of the last node in a block
- textNode = node.lastChild;
- if (textNode && textNode.type === 3) {
- text = textNode.value.replace(endWhiteSpaceRegExp, '');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Trim whitespace of the last node in a block
+ textNode = node.lastChild;
+ if (textNode && textNode.type === 3) {
+ text = textNode.value.replace(endWhiteSpaceRegExp, '');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Any characters left after trim or should we remove it
- if (text.length > 0) {
- textNode.value = text;
- textNode = textNode.prev;
- } else {
- sibling = textNode.prev;
- textNode.remove();
- textNode = sibling;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Any characters left after trim or should we remove it
+ if (text.length > 0) {
+ textNode.value = text;
+ textNode = textNode.prev;
+ } else {
+ sibling = textNode.prev;
+ textNode.remove();
+ textNode = sibling;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove any pure whitespace siblings
- while (textNode && textNode.type === 3) {
- text = textNode.value;
- sibling = textNode.prev;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove any pure whitespace siblings
+ while (textNode && textNode.type === 3) {
+ text = textNode.value;
+ sibling = textNode.prev;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (text.length === 0 || isAllWhiteSpaceRegExp.test(text)) {
- textNode.remove();
- textNode = sibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (text.length === 0 || isAllWhiteSpaceRegExp.test(text)) {
+ textNode.remove();
+ textNode = sibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- textNode = sibling;
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ textNode = sibling;
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Trim start white space
- // Removed due to: #5424
- /*textNode = node.prev;
- if (textNode && textNode.type === 3) {
- text = textNode.value.replace(startWhiteSpaceRegExp, '');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Trim start white space
+ // Removed due to: #5424
+ /*textNode = node.prev;
+ if (textNode && textNode.type === 3) {
+ text = textNode.value.replace(startWhiteSpaceRegExp, '');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (text.length > 0)
- textNode.value = text;
- else
- textNode.remove();
- }*/
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (text.length > 0)
+ textNode.value = text;
+ else
+ textNode.remove();
+ }*/
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if we exited a whitespace preserved element
- if (isInWhiteSpacePreservedElement && whiteSpaceElements[name]) {
- isInWhiteSpacePreservedElement = false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if we exited a whitespace preserved element
+ if (isInWhiteSpacePreservedElement && whiteSpaceElements[name]) {
+ isInWhiteSpacePreservedElement = false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle empty nodes
- if (elementRule.removeEmpty || elementRule.paddEmpty) {
- if (node.isEmpty(nonEmptyElements, whiteSpaceElements)) {
- if (elementRule.paddEmpty) {
- paddEmptyNode(settings, node);
- } else {
- // Leave nodes that have a name like <a name="name">
- if (!node.attributes.map.name && !node.attributes.map.id) {
- tempNode = node.parent;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handle empty nodes
+ if (elementRule.removeEmpty || elementRule.paddEmpty) {
+ if (node.isEmpty(nonEmptyElements, whiteSpaceElements)) {
+ if (elementRule.paddEmpty) {
+ paddEmptyNode(settings, node);
+ } else {
+ // Leave nodes that have a name like <a name="name">
+ if (!node.attributes.map.name && !node.attributes.map.id) {
+ tempNode = node.parent;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (blockElements[node.name]) {
- node.empty().remove();
- } else {
- node.unwrap();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (blockElements[node.name]) {
+ node.empty().remove();
+ } else {
+ node.unwrap();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = tempNode;
- return;
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = tempNode;
+ return;
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.parent;
- }
- }
- }, schema);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node.parent;
+ }
+ }
+ }, schema);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rootNode = node = new Node(args.context || settings.root_name, 11);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rootNode = node = new Node(args.context || settings.root_name, 11);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parser.parse(html);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parser.parse(html);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Fix invalid children or report invalid children in a contextual parsing
- if (validate && invalidChildren.length) {
- if (!args.context) {
- fixInvalidChildren(invalidChildren);
- } else {
- args.invalid = true;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Fix invalid children or report invalid children in a contextual parsing
+ if (validate && invalidChildren.length) {
+ if (!args.context) {
+ fixInvalidChildren(invalidChildren);
+ } else {
+ args.invalid = true;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Wrap nodes in the root into block elements if the root is body
- if (rootBlockName && (rootNode.name == 'body' || args.isRootContent)) {
- addRootBlocks();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Wrap nodes in the root into block elements if the root is body
+ if (rootBlockName && (rootNode.name == 'body' || args.isRootContent)) {
+ addRootBlocks();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Run filters only when the contents is valid
- if (!args.invalid) {
- // Run node filters
- for (name in matchedNodes) {
- list = nodeFilters[name];
- nodes = matchedNodes[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Run filters only when the contents is valid
+ if (!args.invalid) {
+ // Run node filters
+ for (name in matchedNodes) {
+ list = nodeFilters[name];
+ nodes = matchedNodes[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove already removed children
- fi = nodes.length;
- while (fi--) {
- if (!nodes[fi].parent) {
- nodes.splice(fi, 1);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove already removed children
+ fi = nodes.length;
+ while (fi--) {
+ if (!nodes[fi].parent) {
+ nodes.splice(fi, 1);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0, l = list.length; i < l; i++) {
- list[i](nodes, name, args);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0, l = list.length; i < l; i++) {
+ list[i](nodes, name, args);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Run attribute filters
- for (i = 0, l = attributeFilters.length; i < l; i++) {
- list = attributeFilters[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Run attribute filters
+ for (i = 0, l = attributeFilters.length; i < l; i++) {
+ list = attributeFilters[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (list.name in matchedAttributes) {
- nodes = matchedAttributes[list.name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (list.name in matchedAttributes) {
+ nodes = matchedAttributes[list.name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove already removed children
- fi = nodes.length;
- while (fi--) {
- if (!nodes[fi].parent) {
- nodes.splice(fi, 1);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove already removed children
+ fi = nodes.length;
+ while (fi--) {
+ if (!nodes[fi].parent) {
+ nodes.splice(fi, 1);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (fi = 0, fl = list.callbacks.length; fi < fl; fi++) {
- list.callbacks[fi](nodes, list.name, args);
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (fi = 0, fl = list.callbacks.length; fi < fl; fi++) {
+ list.callbacks[fi](nodes, list.name, args);
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return rootNode;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return rootNode;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove <br> at end of block elements Gecko and WebKit injects BR elements to
- // make it possible to place the caret inside empty blocks. This logic tries to remove
- // these elements and keep br elements that where intended to be there intact
- if (settings.remove_trailing_brs) {
- self.addNodeFilter('br', function(nodes) {
- var i, l = nodes.length, node, blockElements = extend({}, schema.getBlockElements());
- var nonEmptyElements = schema.getNonEmptyElements(), parent, lastParent, prev, prevName;
- var whiteSpaceElements = schema.getNonEmptyElements();
- var elementRule, textNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove <br> at end of block elements Gecko and WebKit injects BR elements to
+ // make it possible to place the caret inside empty blocks. This logic tries to remove
+ // these elements and keep br elements that where intended to be there intact
+ if (settings.remove_trailing_brs) {
+ self.addNodeFilter('br', function (nodes) {
+ var i, l = nodes.length, node, blockElements = extend({}, schema.getBlockElements());
+ var nonEmptyElements = schema.getNonEmptyElements(), parent, lastParent, prev, prevName;
+ var whiteSpaceElements = schema.getNonEmptyElements();
+ var elementRule, textNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove brs from body element as well
- blockElements.body = 1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove brs from body element as well
+ blockElements.body = 1;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Must loop forwards since it will otherwise remove all brs in <p>a<br><br><br></p>
- for (i = 0; i < l; i++) {
- node = nodes[i];
- parent = node.parent;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Must loop forwards since it will otherwise remove all brs in <p>a<br><br><br></p>
+ for (i = 0; i < l; i++) {
+ node = nodes[i];
+ parent = node.parent;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (blockElements[node.parent.name] && node === parent.lastChild) {
- // Loop all nodes to the left of the current node and check for other BR elements
- // excluding bookmarks since they are invisible
- prev = node.prev;
- while (prev) {
- prevName = prev.name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (blockElements[node.parent.name] && node === parent.lastChild) {
+ // Loop all nodes to the left of the current node and check for other BR elements
+ // excluding bookmarks since they are invisible
+ prev = node.prev;
+ while (prev) {
+ prevName = prev.name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Ignore bookmarks
- if (prevName !== "span" || prev.attr('data-mce-type') !== 'bookmark') {
- // Found a non BR element
- if (prevName !== "br") {
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Ignore bookmarks
+ if (prevName !== "span" || prev.attr('data-mce-type') !== 'bookmark') {
+ // Found a non BR element
+ if (prevName !== "br") {
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Found another br it's a <br><br> structure then don't remove anything
- if (prevName === 'br') {
- node = null;
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Found another br it's a <br><br> structure then don't remove anything
+ if (prevName === 'br') {
+ node = null;
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- prev = prev.prev;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ prev = prev.prev;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node) {
- node.remove();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node) {
+ node.remove();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Is the parent to be considered empty after we removed the BR
- if (parent.isEmpty(nonEmptyElements, whiteSpaceElements)) {
- elementRule = schema.getElementRule(parent.name);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Is the parent to be considered empty after we removed the BR
+ if (parent.isEmpty(nonEmptyElements, whiteSpaceElements)) {
+ elementRule = schema.getElementRule(parent.name);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove or padd the element depending on schema rule
- if (elementRule) {
- if (elementRule.removeEmpty) {
- parent.remove();
- } else if (elementRule.paddEmpty) {
- paddEmptyNode(settings, parent);
- }
- }
- }
- }
- } else {
- // Replaces BR elements inside inline elements like <p><b><i><br></i></b></p>
- // so they become <p><b><i> </i></b></p>
- lastParent = node;
- while (parent && parent.firstChild === lastParent && parent.lastChild === lastParent) {
- lastParent = parent;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove or padd the element depending on schema rule
+ if (elementRule) {
+ if (elementRule.removeEmpty) {
+ parent.remove();
+ } else if (elementRule.paddEmpty) {
+ paddEmptyNode(settings, parent);
+ }
+ }
+ }
+ }
+ } else {
+ // Replaces BR elements inside inline elements like <p><b><i><br></i></b></p>
+ // so they become <p><b><i> </i></b></p>
+ lastParent = node;
+ while (parent && parent.firstChild === lastParent && parent.lastChild === lastParent) {
+ lastParent = parent;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (blockElements[parent.name]) {
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (blockElements[parent.name]) {
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parent = parent.parent;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parent = parent.parent;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (lastParent === parent && settings.padd_empty_with_br !== true) {
- textNode = new Node('#text', 3);
- textNode.value = '\u00a0';
- node.replace(textNode);
- }
- }
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (lastParent === parent && settings.padd_empty_with_br !== true) {
+ textNode = new Node('#text', 3);
+ textNode.value = '\u00a0';
+ node.replace(textNode);
+ }
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!settings.allow_unsafe_link_target) {
- self.addAttributeFilter('href', function(nodes) {
- var i = nodes.length, node, rel;
- var rules = 'noopener noreferrer';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!settings.allow_unsafe_link_target) {
+ self.addAttributeFilter('href', function (nodes) {
+ var i = nodes.length, node, rel;
+ var rules = 'noopener noreferrer';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function addTargetRules(rel) {
- rel = removeTargetRules(rel);
- return rel ? [rel, rules].join(' ') : rules;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function addTargetRules(rel) {
+ rel = removeTargetRules(rel);
+ return rel ? [rel, rules].join(' ') : rules;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function removeTargetRules(rel) {
- var regExp = new RegExp('(' + rules.replace(' ', '|') + ')', 'g');
- if (rel) {
- rel = Tools.trim(rel.replace(regExp, ''));
- }
- return rel ? rel : null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function removeTargetRules(rel) {
+ var regExp = new RegExp('(' + rules.replace(' ', '|') + ')', 'g');
+ if (rel) {
+ rel = Tools.trim(rel.replace(regExp, ''));
+ }
+ return rel ? rel : null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function toggleTargetRules(rel, isUnsafe) {
- return isUnsafe ? addTargetRules(rel) : removeTargetRules(rel);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function toggleTargetRules(rel, isUnsafe) {
+ return isUnsafe ? addTargetRules(rel) : removeTargetRules(rel);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i];
- rel = node.attr('rel');
- if (node.name === 'a') {
- node.attr('rel', toggleTargetRules(rel, node.attr('target') == '_blank'));
- }
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i];
+ rel = node.attr('rel');
+ if (node.name === 'a') {
+ node.attr('rel', toggleTargetRules(rel, node.attr('target') == '_blank'));
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Force anchor names closed, unless the setting "allow_html_in_named_anchor" is explicitly included.
- if (!settings.allow_html_in_named_anchor) {
- self.addAttributeFilter('id,name', function(nodes) {
- var i = nodes.length, sibling, prevSibling, parent, node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Force anchor names closed, unless the setting "allow_html_in_named_anchor" is explicitly included.
+ if (!settings.allow_html_in_named_anchor) {
+ self.addAttributeFilter('id,name', function (nodes) {
+ var i = nodes.length, sibling, prevSibling, parent, node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i];
- if (node.name === 'a' && node.firstChild && !node.attr('href')) {
- parent = node.parent;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i];
+ if (node.name === 'a' && node.firstChild && !node.attr('href')) {
+ parent = node.parent;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move children after current node
- sibling = node.lastChild;
- do {
- prevSibling = sibling.prev;
- parent.insert(sibling, node);
- sibling = prevSibling;
- } while (sibling);
- }
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move children after current node
+ sibling = node.lastChild;
+ do {
+ prevSibling = sibling.prev;
+ parent.insert(sibling, node);
+ sibling = prevSibling;
+ } while (sibling);
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.fix_list_elements) {
- self.addNodeFilter('ul,ol', function(nodes) {
- var i = nodes.length, node, parentNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.fix_list_elements) {
+ self.addNodeFilter('ul,ol', function (nodes) {
+ var i = nodes.length, node, parentNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i];
- parentNode = node.parent;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i];
+ parentNode = node.parent;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (parentNode.name === 'ul' || parentNode.name === 'ol') {
- if (node.prev && node.prev.name === 'li') {
- node.prev.append(node);
- } else {
- var li = new Node('li', 1);
- li.attr('style', 'list-style-type: none');
- node.wrap(li);
- }
- }
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parentNode.name === 'ul' || parentNode.name === 'ol') {
+ if (node.prev && node.prev.name === 'li') {
+ node.prev.append(node);
+ } else {
+ var li = new Node('li', 1);
+ li.attr('style', 'list-style-type: none');
+ node.wrap(li);
+ }
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.validate && schema.getValidClasses()) {
- self.addAttributeFilter('class', function(nodes) {
- var i = nodes.length, node, classList, ci, className, classValue;
- var validClasses = schema.getValidClasses(), validClassesMap, valid;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.validate && schema.getValidClasses()) {
+ self.addAttributeFilter('class', function (nodes) {
+ var i = nodes.length, node, classList, ci, className, classValue;
+ var validClasses = schema.getValidClasses(), validClassesMap, valid;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i];
- classList = node.attr('class').split(' ');
- classValue = '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i];
+ classList = node.attr('class').split(' ');
+ classValue = '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (ci = 0; ci < classList.length; ci++) {
- className = classList[ci];
- valid = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (ci = 0; ci < classList.length; ci++) {
+ className = classList[ci];
+ valid = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- validClassesMap = validClasses['*'];
- if (validClassesMap && validClassesMap[className]) {
- valid = true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ validClassesMap = validClasses['*'];
+ if (validClassesMap && validClassesMap[className]) {
+ valid = true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- validClassesMap = validClasses[node.name];
- if (!valid && validClassesMap && validClassesMap[className]) {
- valid = true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ validClassesMap = validClasses[node.name];
+ if (!valid && validClassesMap && validClassesMap[className]) {
+ valid = true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (valid) {
- if (classValue) {
- classValue += ' ';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (valid) {
+ if (classValue) {
+ classValue += ' ';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- classValue += className;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ classValue += className;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!classValue.length) {
- classValue = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!classValue.length) {
+ classValue = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node.attr('class', classValue);
- }
- });
- }
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node.attr('class', classValue);
+ }
+ });
+ }
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/html/Writer.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Writer.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -14075,191 +14998,192 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.html.Writer
</span><span class="cx" style="display: block; padding: 0 10px"> * @version 3.4
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/html/Writer", [
- "tinymce/html/Entities",
- "tinymce/util/Tools"
-], function(Entities, Tools) {
- var makeMap = Tools.makeMap;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.html.Writer',
+ [
+ "tinymce.core.html.Entities",
+ "tinymce.core.util.Tools"
+ ],
+ function (Entities, Tools) {
+ var makeMap = Tools.makeMap;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a new Writer instance.
- *
- * @constructor
- * @method Writer
- * @param {Object} settings Name/value settings object.
- */
- return function(settings) {
- var html = [], indent, indentBefore, indentAfter, encode, htmlOutput;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a new Writer instance.
+ *
+ * @constructor
+ * @method Writer
+ * @param {Object} settings Name/value settings object.
+ */
+ return function (settings) {
+ var html = [], indent, indentBefore, indentAfter, encode, htmlOutput;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- settings = settings || {};
- indent = settings.indent;
- indentBefore = makeMap(settings.indent_before || '');
- indentAfter = makeMap(settings.indent_after || '');
- encode = Entities.getEncodeFunc(settings.entity_encoding || 'raw', settings.entities);
- htmlOutput = settings.element_format == "html";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ settings = settings || {};
+ indent = settings.indent;
+ indentBefore = makeMap(settings.indent_before || '');
+ indentAfter = makeMap(settings.indent_after || '');
+ encode = Entities.getEncodeFunc(settings.entity_encoding || 'raw', settings.entities);
+ htmlOutput = settings.element_format == "html";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- /**
- * Writes the a start element such as <p id="a">.
- *
- * @method start
- * @param {String} name Name of the element.
- * @param {Array} attrs Optional attribute array or undefined if it hasn't any.
- * @param {Boolean} empty Optional empty state if the tag should end like <br />.
- */
- start: function(name, attrs, empty) {
- var i, l, attr, value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ /**
+ * Writes the a start element such as <p id="a">.
+ *
+ * @method start
+ * @param {String} name Name of the element.
+ * @param {Array} attrs Optional attribute array or undefined if it hasn't any.
+ * @param {Boolean} empty Optional empty state if the tag should end like <br />.
+ */
+ start: function (name, attrs, empty) {
+ var i, l, attr, value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (indent && indentBefore[name] && html.length > 0) {
- value = html[html.length - 1];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (indent && indentBefore[name] && html.length > 0) {
+ value = html[html.length - 1];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value.length > 0 && value !== '\n') {
- html.push('\n');
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value.length > 0 && value !== '\n') {
+ html.push('\n');
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- html.push('<', name);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ html.push('<', name);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (attrs) {
- for (i = 0, l = attrs.length; i < l; i++) {
- attr = attrs[i];
- html.push(' ', attr.name, '="', encode(attr.value, true), '"');
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (attrs) {
+ for (i = 0, l = attrs.length; i < l; i++) {
+ attr = attrs[i];
+ html.push(' ', attr.name, '="', encode(attr.value, true), '"');
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!empty || htmlOutput) {
- html[html.length] = '>';
- } else {
- html[html.length] = ' />';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!empty || htmlOutput) {
+ html[html.length] = '>';
+ } else {
+ html[html.length] = ' />';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (empty && indent && indentAfter[name] && html.length > 0) {
- value = html[html.length - 1];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (empty && indent && indentAfter[name] && html.length > 0) {
+ value = html[html.length - 1];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value.length > 0 && value !== '\n') {
- html.push('\n');
- }
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value.length > 0 && value !== '\n') {
+ html.push('\n');
+ }
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Writes the a end element such as </p>.
- *
- * @method end
- * @param {String} name Name of the element.
- */
- end: function(name) {
- var value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Writes the a end element such as </p>.
+ *
+ * @method end
+ * @param {String} name Name of the element.
+ */
+ end: function (name) {
+ var value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /*if (indent && indentBefore[name] && html.length > 0) {
- value = html[html.length - 1];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /*if (indent && indentBefore[name] && html.length > 0) {
+ value = html[html.length - 1];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value.length > 0 && value !== '\n')
- html.push('\n');
- }*/
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value.length > 0 && value !== '\n')
+ html.push('\n');
+ }*/
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- html.push('</', name, '>');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ html.push('</', name, '>');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (indent && indentAfter[name] && html.length > 0) {
- value = html[html.length - 1];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (indent && indentAfter[name] && html.length > 0) {
+ value = html[html.length - 1];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value.length > 0 && value !== '\n') {
- html.push('\n');
- }
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value.length > 0 && value !== '\n') {
+ html.push('\n');
+ }
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Writes a text node.
- *
- * @method text
- * @param {String} text String to write out.
- * @param {Boolean} raw Optional raw state if true the contents wont get encoded.
- */
- text: function(text, raw) {
- if (text.length > 0) {
- html[html.length] = raw ? text : encode(text);
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Writes a text node.
+ *
+ * @method text
+ * @param {String} text String to write out.
+ * @param {Boolean} raw Optional raw state if true the contents wont get encoded.
+ */
+ text: function (text, raw) {
+ if (text.length > 0) {
+ html[html.length] = raw ? text : encode(text);
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Writes a cdata node such as <![CDATA[data]]>.
- *
- * @method cdata
- * @param {String} text String to write out inside the cdata.
- */
- cdata: function(text) {
- html.push('<![CDATA[', text, ']]>');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Writes a cdata node such as <![CDATA[data]]>.
+ *
+ * @method cdata
+ * @param {String} text String to write out inside the cdata.
+ */
+ cdata: function (text) {
+ html.push('<![CDATA[', text, ']]>');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Writes a comment node such as <!-- Comment -->.
- *
- * @method cdata
- * @param {String} text String to write out inside the comment.
- */
- comment: function(text) {
- html.push('<!--', text, '-->');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Writes a comment node such as <!-- Comment -->.
+ *
+ * @method cdata
+ * @param {String} text String to write out inside the comment.
+ */
+ comment: function (text) {
+ html.push('<!--', text, '-->');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Writes a PI node such as <?xml attr="value" ?>.
- *
- * @method pi
- * @param {String} name Name of the pi.
- * @param {String} text String to write out inside the pi.
- */
- pi: function(name, text) {
- if (text) {
- html.push('<?', name, ' ', encode(text), '?>');
- } else {
- html.push('<?', name, '?>');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Writes a PI node such as <?xml attr="value" ?>.
+ *
+ * @method pi
+ * @param {String} name Name of the pi.
+ * @param {String} text String to write out inside the pi.
+ */
+ pi: function (name, text) {
+ if (text) {
+ html.push('<?', name, ' ', encode(text), '?>');
+ } else {
+ html.push('<?', name, '?>');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (indent) {
- html.push('\n');
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (indent) {
+ html.push('\n');
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Writes a doctype node such as <!DOCTYPE data>.
- *
- * @method doctype
- * @param {String} text String to write out inside the doctype.
- */
- doctype: function(text) {
- html.push('<!DOCTYPE', text, '>', indent ? '\n' : '');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Writes a doctype node such as <!DOCTYPE data>.
+ *
+ * @method doctype
+ * @param {String} text String to write out inside the doctype.
+ */
+ doctype: function (text) {
+ html.push('<!DOCTYPE', text, '>', indent ? '\n' : '');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Resets the internal buffer if one wants to reuse the writer.
- *
- * @method reset
- */
- reset: function() {
- html.length = 0;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Resets the internal buffer if one wants to reuse the writer.
+ *
+ * @method reset
+ */
+ reset: function () {
+ html.length = 0;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the contents that got serialized.
- *
- * @method getContent
- * @return {String} HTML contents that got written down.
- */
- getContent: function() {
- return html.join('').replace(/\n$/, '');
- }
- };
- };
-});
-
-// Included from: js/tinymce/classes/html/Serializer.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the contents that got serialized.
+ *
+ * @method getContent
+ * @return {String} HTML contents that got written down.
+ */
+ getContent: function () {
+ return html.join('').replace(/\n$/, '');
+ }
+ };
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Serializer.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -14274,153 +15198,155 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.html.Serializer
</span><span class="cx" style="display: block; padding: 0 10px"> * @version 3.4
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/html/Serializer", [
- "tinymce/html/Writer",
- "tinymce/html/Schema"
-], function(Writer, Schema) {
- /**
- * Constructs a new Serializer instance.
- *
- * @constructor
- * @method Serializer
- * @param {Object} settings Name/value settings object.
- * @param {tinymce.html.Schema} schema Schema instance to use.
- */
- return function(settings, schema) {
- var self = this, writer = new Writer(settings);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.html.Serializer',
+ [
+ "tinymce.core.html.Writer",
+ "tinymce.core.html.Schema"
+ ],
+ function (Writer, Schema) {
+ /**
+ * Constructs a new Serializer instance.
+ *
+ * @constructor
+ * @method Serializer
+ * @param {Object} settings Name/value settings object.
+ * @param {tinymce.html.Schema} schema Schema instance to use.
+ */
+ return function (settings, schema) {
+ var self = this, writer = new Writer(settings);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- settings = settings || {};
- settings.validate = "validate" in settings ? settings.validate : true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ settings = settings || {};
+ settings.validate = "validate" in settings ? settings.validate : true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.schema = schema = schema || new Schema();
- self.writer = writer;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.schema = schema = schema || new Schema();
+ self.writer = writer;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Serializes the specified node into a string.
- *
- * @example
- * new tinymce.html.Serializer().serialize(new tinymce.html.DomParser().parse('<p>text</p>'));
- * @method serialize
- * @param {tinymce.html.Node} node Node instance to serialize.
- * @return {String} String with HTML based on DOM tree.
- */
- self.serialize = function(node) {
- var handlers, validate;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Serializes the specified node into a string.
+ *
+ * @example
+ * new tinymce.html.Serializer().serialize(new tinymce.html.DomParser().parse('<p>text</p>'));
+ * @method serialize
+ * @param {tinymce.html.Node} node Node instance to serialize.
+ * @return {String} String with HTML based on DOM tree.
+ */
+ self.serialize = function (node) {
+ var handlers, validate;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- validate = settings.validate;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ validate = settings.validate;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- handlers = {
- // #text
- 3: function(node) {
- writer.text(node.value, node.raw);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ handlers = {
+ // #text
+ 3: function (node) {
+ writer.text(node.value, node.raw);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // #comment
- 8: function(node) {
- writer.comment(node.value);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // #comment
+ 8: function (node) {
+ writer.comment(node.value);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Processing instruction
- 7: function(node) {
- writer.pi(node.name, node.value);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Processing instruction
+ 7: function (node) {
+ writer.pi(node.name, node.value);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Doctype
- 10: function(node) {
- writer.doctype(node.value);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Doctype
+ 10: function (node) {
+ writer.doctype(node.value);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // CDATA
- 4: function(node) {
- writer.cdata(node.value);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // CDATA
+ 4: function (node) {
+ writer.cdata(node.value);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Document fragment
- 11: function(node) {
- if ((node = node.firstChild)) {
- do {
- walk(node);
- } while ((node = node.next));
- }
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Document fragment
+ 11: function (node) {
+ if ((node = node.firstChild)) {
+ do {
+ walk(node);
+ } while ((node = node.next));
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- writer.reset();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ writer.reset();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function walk(node) {
- var handler = handlers[node.type], name, isEmpty, attrs, attrName, attrValue, sortedAttrs, i, l, elementRule;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function walk(node) {
+ var handler = handlers[node.type], name, isEmpty, attrs, attrName, attrValue, sortedAttrs, i, l, elementRule;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!handler) {
- name = node.name;
- isEmpty = node.shortEnded;
- attrs = node.attributes;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!handler) {
+ name = node.name;
+ isEmpty = node.shortEnded;
+ attrs = node.attributes;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Sort attributes
- if (validate && attrs && attrs.length > 1) {
- sortedAttrs = [];
- sortedAttrs.map = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Sort attributes
+ if (validate && attrs && attrs.length > 1) {
+ sortedAttrs = [];
+ sortedAttrs.map = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elementRule = schema.getElementRule(node.name);
- if (elementRule) {
- for (i = 0, l = elementRule.attributesOrder.length; i < l; i++) {
- attrName = elementRule.attributesOrder[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elementRule = schema.getElementRule(node.name);
+ if (elementRule) {
+ for (i = 0, l = elementRule.attributesOrder.length; i < l; i++) {
+ attrName = elementRule.attributesOrder[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (attrName in attrs.map) {
- attrValue = attrs.map[attrName];
- sortedAttrs.map[attrName] = attrValue;
- sortedAttrs.push({name: attrName, value: attrValue});
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (attrName in attrs.map) {
+ attrValue = attrs.map[attrName];
+ sortedAttrs.map[attrName] = attrValue;
+ sortedAttrs.push({ name: attrName, value: attrValue });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0, l = attrs.length; i < l; i++) {
- attrName = attrs[i].name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0, l = attrs.length; i < l; i++) {
+ attrName = attrs[i].name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!(attrName in sortedAttrs.map)) {
- attrValue = attrs.map[attrName];
- sortedAttrs.map[attrName] = attrValue;
- sortedAttrs.push({name: attrName, value: attrValue});
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!(attrName in sortedAttrs.map)) {
+ attrValue = attrs.map[attrName];
+ sortedAttrs.map[attrName] = attrValue;
+ sortedAttrs.push({ name: attrName, value: attrValue });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- attrs = sortedAttrs;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ attrs = sortedAttrs;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- writer.start(node.name, attrs, isEmpty);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ writer.start(node.name, attrs, isEmpty);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isEmpty) {
- if ((node = node.firstChild)) {
- do {
- walk(node);
- } while ((node = node.next));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isEmpty) {
+ if ((node = node.firstChild)) {
+ do {
+ walk(node);
+ } while ((node = node.next));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- writer.end(name);
- }
- } else {
- handler(node);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ writer.end(name);
+ }
+ } else {
+ handler(node);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Serialize element and treat all non elements as fragments
- if (node.type == 1 && !settings.inner) {
- walk(node);
- } else {
- handlers[11](node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Serialize element and treat all non elements as fragments
+ if (node.type == 1 && !settings.inner) {
+ walk(node);
+ } else {
+ handlers[11](node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return writer.getContent();
- };
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return writer.getContent();
+ };
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/dom/Serializer.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Serializer.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -14432,1002 +15358,493 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.dom.Serializer
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/dom/Serializer", [
- "tinymce/dom/DOMUtils",
- "tinymce/html/DomParser",
- "tinymce/html/SaxParser",
- "tinymce/html/Entities",
- "tinymce/html/Serializer",
- "tinymce/html/Node",
- "tinymce/html/Schema",
- "tinymce/Env",
- "tinymce/util/Tools",
- "tinymce/text/Zwsp"
-], function(DOMUtils, DomParser, SaxParser, Entities, Serializer, Node, Schema, Env, Tools, Zwsp) {
- var each = Tools.each, trim = Tools.trim;
- var DOM = DOMUtils.DOM;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.Serializer',
+ [
+ "tinymce.core.dom.DOMUtils",
+ "tinymce.core.html.DomParser",
+ "tinymce.core.html.SaxParser",
+ "tinymce.core.html.Entities",
+ "tinymce.core.html.Serializer",
+ "tinymce.core.html.Node",
+ "tinymce.core.html.Schema",
+ "tinymce.core.Env",
+ "tinymce.core.util.Tools",
+ "tinymce.core.text.Zwsp"
+ ],
+ function (DOMUtils, DomParser, SaxParser, Entities, Serializer, Node, Schema, Env, Tools, Zwsp) {
+ var each = Tools.each, trim = Tools.trim;
+ var DOM = DOMUtils.DOM;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * IE 11 has a fantastic bug where it will produce two trailing BR elements to iframe bodies when
- * the iframe is hidden by display: none on a parent container. The DOM is actually out of sync
- * with innerHTML in this case. It's like IE adds shadow DOM BR elements that appears on innerHTML
- * but not as the lastChild of the body. So this fix simply removes the last two
- * BR elements at the end of the document.
- *
- * Example of what happens: <body>text</body> becomes <body>text<br><br></body>
- */
- function trimTrailingBr(rootNode) {
- var brNode1, brNode2;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * IE 11 has a fantastic bug where it will produce two trailing BR elements to iframe bodies when
+ * the iframe is hidden by display: none on a parent container. The DOM is actually out of sync
+ * with innerHTML in this case. It's like IE adds shadow DOM BR elements that appears on innerHTML
+ * but not as the lastChild of the body. So this fix simply removes the last two
+ * BR elements at the end of the document.
+ *
+ * Example of what happens: <body>text</body> becomes <body>text<br><br></body>
+ */
+ function trimTrailingBr(rootNode) {
+ var brNode1, brNode2;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isBr(node) {
- return node && node.name === 'br';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isBr(node) {
+ return node && node.name === 'br';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- brNode1 = rootNode.lastChild;
- if (isBr(brNode1)) {
- brNode2 = brNode1.prev;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ brNode1 = rootNode.lastChild;
+ if (isBr(brNode1)) {
+ brNode2 = brNode1.prev;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isBr(brNode2)) {
- brNode1.remove();
- brNode2.remove();
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isBr(brNode2)) {
+ brNode1.remove();
+ brNode2.remove();
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a new DOM serializer class.
- *
- * @constructor
- * @method Serializer
- * @param {Object} settings Serializer settings object.
- * @param {tinymce.Editor} editor Optional editor to bind events to and get schema/dom from.
- */
- return function(settings, editor) {
- var dom, schema, htmlParser, tempAttrs = ["data-mce-selected"];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a new DOM serializer class.
+ *
+ * @constructor
+ * @method Serializer
+ * @param {Object} settings Serializer settings object.
+ * @param {tinymce.Editor} editor Optional editor to bind events to and get schema/dom from.
+ */
+ return function (settings, editor) {
+ var dom, schema, htmlParser, tempAttrs = ["data-mce-selected"];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor) {
- dom = editor.dom;
- schema = editor.schema;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor) {
+ dom = editor.dom;
+ schema = editor.schema;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function trimHtml(html) {
- var trimContentRegExp = new RegExp([
- '<span[^>]+data-mce-bogus[^>]+>[\u200B\uFEFF]+<\\/span>', // Trim bogus spans like caret containers
- '\\s?(' + tempAttrs.join('|') + ')="[^"]+"' // Trim temporaty data-mce prefixed attributes like data-mce-selected
- ].join('|'), 'gi');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function trimHtml(html) {
+ var trimContentRegExp = new RegExp([
+ '<span[^>]+data-mce-bogus[^>]+>[\u200B\uFEFF]+<\\/span>', // Trim bogus spans like caret containers
+ '\\s?(' + tempAttrs.join('|') + ')="[^"]+"' // Trim temporaty data-mce prefixed attributes like data-mce-selected
+ ].join('|'), 'gi');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- html = Zwsp.trim(html.replace(trimContentRegExp, ''));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ html = Zwsp.trim(html.replace(trimContentRegExp, ''));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return html;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return html;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function trimContent(html) {
- var content = html;
- var bogusAllRegExp = /<(\w+) [^>]*data-mce-bogus="all"[^>]*>/g;
- var endTagIndex, index, matchLength, matches, shortEndedElements, schema = editor.schema;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function trimContent(html) {
+ var content = html;
+ var bogusAllRegExp = /<(\w+) [^>]*data-mce-bogus="all"[^>]*>/g;
+ var endTagIndex, index, matchLength, matches, shortEndedElements, schema = editor.schema;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- content = trimHtml(content);
- shortEndedElements = schema.getShortEndedElements();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ content = trimHtml(content);
+ shortEndedElements = schema.getShortEndedElements();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove all bogus elements marked with "all"
- while ((matches = bogusAllRegExp.exec(content))) {
- index = bogusAllRegExp.lastIndex;
- matchLength = matches[0].length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove all bogus elements marked with "all"
+ while ((matches = bogusAllRegExp.exec(content))) {
+ index = bogusAllRegExp.lastIndex;
+ matchLength = matches[0].length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (shortEndedElements[matches[1]]) {
- endTagIndex = index;
- } else {
- endTagIndex = SaxParser.findEndTag(schema, content, index);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (shortEndedElements[matches[1]]) {
+ endTagIndex = index;
+ } else {
+ endTagIndex = SaxParser.findEndTag(schema, content, index);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- content = content.substring(0, index - matchLength) + content.substring(endTagIndex);
- bogusAllRegExp.lastIndex = index - matchLength;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ content = content.substring(0, index - matchLength) + content.substring(endTagIndex);
+ bogusAllRegExp.lastIndex = index - matchLength;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return content;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return content;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a trimmed version of the editor contents to be used for the undo level. This
- * will remove any data-mce-bogus="all" marked elements since these are used for UI it will also
- * remove the data-mce-selected attributes used for selection of objects and caret containers.
- * It will keep all data-mce-bogus="1" elements since these can be used to place the caret etc and will
- * be removed by the serialization logic when you save.
- *
- * @private
- * @return {String} HTML contents of the editor excluding some internal bogus elements.
- */
- function getTrimmedContent() {
- return trimContent(editor.getBody().innerHTML);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a trimmed version of the editor contents to be used for the undo level. This
+ * will remove any data-mce-bogus="all" marked elements since these are used for UI it will also
+ * remove the data-mce-selected attributes used for selection of objects and caret containers.
+ * It will keep all data-mce-bogus="1" elements since these can be used to place the caret etc and will
+ * be removed by the serialization logic when you save.
+ *
+ * @private
+ * @return {String} HTML contents of the editor excluding some internal bogus elements.
+ */
+ function getTrimmedContent() {
+ return trimContent(editor.getBody().innerHTML);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function addTempAttr(name) {
- if (Tools.inArray(tempAttrs, name) === -1) {
- htmlParser.addAttributeFilter(name, function(nodes, name) {
- var i = nodes.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function addTempAttr(name) {
+ if (Tools.inArray(tempAttrs, name) === -1) {
+ htmlParser.addAttributeFilter(name, function (nodes, name) {
+ var i = nodes.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- nodes[i].attr(name, null);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ nodes[i].attr(name, null);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tempAttrs.push(name);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ tempAttrs.push(name);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Default DOM and Schema if they are undefined
- dom = dom || DOM;
- schema = schema || new Schema(settings);
- settings.entity_encoding = settings.entity_encoding || 'named';
- settings.remove_trailing_brs = "remove_trailing_brs" in settings ? settings.remove_trailing_brs : true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Default DOM and Schema if they are undefined
+ dom = dom || DOM;
+ schema = schema || new Schema(settings);
+ settings.entity_encoding = settings.entity_encoding || 'named';
+ settings.remove_trailing_brs = "remove_trailing_brs" in settings ? settings.remove_trailing_brs : true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- htmlParser = new DomParser(settings, schema);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ htmlParser = new DomParser(settings, schema);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Convert tabindex back to elements when serializing contents
- htmlParser.addAttributeFilter('data-mce-tabindex', function(nodes, name) {
- var i = nodes.length, node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Convert tabindex back to elements when serializing contents
+ htmlParser.addAttributeFilter('data-mce-tabindex', function (nodes, name) {
+ var i = nodes.length, node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i];
- node.attr('tabindex', node.attributes.map['data-mce-tabindex']);
- node.attr(name, null);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i];
+ node.attr('tabindex', node.attributes.map['data-mce-tabindex']);
+ node.attr(name, null);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Convert move data-mce-src, data-mce-href and data-mce-style into nodes or process them if needed
- htmlParser.addAttributeFilter('src,href,style', function(nodes, name) {
- var i = nodes.length, node, value, internalName = 'data-mce-' + name;
- var urlConverter = settings.url_converter, urlConverterScope = settings.url_converter_scope, undef;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Convert move data-mce-src, data-mce-href and data-mce-style into nodes or process them if needed
+ htmlParser.addAttributeFilter('src,href,style', function (nodes, name) {
+ var i = nodes.length, node, value, internalName = 'data-mce-' + name;
+ var urlConverter = settings.url_converter, urlConverterScope = settings.url_converter_scope, undef;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- value = node.attributes.map[internalName];
- if (value !== undef) {
- // Set external name to internal value and remove internal
- node.attr(name, value.length > 0 ? value : null);
- node.attr(internalName, null);
- } else {
- // No internal attribute found then convert the value we have in the DOM
- value = node.attributes.map[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ value = node.attributes.map[internalName];
+ if (value !== undef) {
+ // Set external name to internal value and remove internal
+ node.attr(name, value.length > 0 ? value : null);
+ node.attr(internalName, null);
+ } else {
+ // No internal attribute found then convert the value we have in the DOM
+ value = node.attributes.map[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name === "style") {
- value = dom.serializeStyle(dom.parseStyle(value), node.name);
- } else if (urlConverter) {
- value = urlConverter.call(urlConverterScope, value, name, node.name);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name === "style") {
+ value = dom.serializeStyle(dom.parseStyle(value), node.name);
+ } else if (urlConverter) {
+ value = urlConverter.call(urlConverterScope, value, name, node.name);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node.attr(name, value.length > 0 ? value : null);
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node.attr(name, value.length > 0 ? value : null);
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove internal classes mceItem<..> or mceSelected
- htmlParser.addAttributeFilter('class', function(nodes) {
- var i = nodes.length, node, value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove internal classes mceItem<..> or mceSelected
+ htmlParser.addAttributeFilter('class', function (nodes) {
+ var i = nodes.length, node, value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i];
- value = node.attr('class');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i];
+ value = node.attr('class');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value) {
- value = node.attr('class').replace(/(?:^|\s)mce-item-\w+(?!\S)/g, '');
- node.attr('class', value.length > 0 ? value : null);
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value) {
+ value = node.attr('class').replace(/(?:^|\s)mce-item-\w+(?!\S)/g, '');
+ node.attr('class', value.length > 0 ? value : null);
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove bookmark elements
- htmlParser.addAttributeFilter('data-mce-type', function(nodes, name, args) {
- var i = nodes.length, node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove bookmark elements
+ htmlParser.addAttributeFilter('data-mce-type', function (nodes, name, args) {
+ var i = nodes.length, node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.attributes.map['data-mce-type'] === 'bookmark' && !args.cleanup) {
- node.remove();
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.attributes.map['data-mce-type'] === 'bookmark' && !args.cleanup) {
+ node.remove();
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- htmlParser.addNodeFilter('noscript', function(nodes) {
- var i = nodes.length, node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ htmlParser.addNodeFilter('noscript', function (nodes) {
+ var i = nodes.length, node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i].firstChild;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i].firstChild;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node) {
- node.value = Entities.decode(node.value);
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node) {
+ node.value = Entities.decode(node.value);
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Force script into CDATA sections and remove the mce- prefix also add comments around styles
- htmlParser.addNodeFilter('script,style', function(nodes, name) {
- var i = nodes.length, node, value, type;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Force script into CDATA sections and remove the mce- prefix also add comments around styles
+ htmlParser.addNodeFilter('script,style', function (nodes, name) {
+ var i = nodes.length, node, value, type;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function trim(value) {
- /*jshint maxlen:255 */
- /*eslint max-len:0 */
- return value.replace(/(<!--\[CDATA\[|\]\]-->)/g, '\n')
- .replace(/^[\r\n]*|[\r\n]*$/g, '')
- .replace(/^\s*((<!--)?(\s*\/\/)?\s*<!\[CDATA\[|(<!--\s*)?\/\*\s*<!\[CDATA\[\s*\*\/|(\/\/)?\s*<!--|\/\*\s*<!--\s*\*\/)\s*[\r\n]*/gi, '')
- .replace(/\s*(\/\*\s*\]\]>\s*\*\/(-->)?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g, '');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function trim(value) {
+ /*jshint maxlen:255 */
+ /*eslint max-len:0 */
+ return value.replace(/(<!--\[CDATA\[|\]\]-->)/g, '\n')
+ .replace(/^[\r\n]*|[\r\n]*$/g, '')
+ .replace(/^\s*((<!--)?(\s*\/\/)?\s*<!\[CDATA\[|(<!--\s*)?\/\*\s*<!\[CDATA\[\s*\*\/|(\/\/)?\s*<!--|\/\*\s*<!--\s*\*\/)\s*[\r\n]*/gi, '')
+ .replace(/\s*(\/\*\s*\]\]>\s*\*\/(-->)?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g, '');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i];
- value = node.firstChild ? node.firstChild.value : '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i];
+ value = node.firstChild ? node.firstChild.value : '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name === "script") {
- // Remove mce- prefix from script elements and remove default type since the user specified
- // a script element without type attribute
- type = node.attr('type');
- if (type) {
- node.attr('type', type == 'mce-no/type' ? null : type.replace(/^mce\-/, ''));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name === "script") {
+ // Remove mce- prefix from script elements and remove default type since the user specified
+ // a script element without type attribute
+ type = node.attr('type');
+ if (type) {
+ node.attr('type', type == 'mce-no/type' ? null : type.replace(/^mce\-/, ''));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value.length > 0) {
- node.firstChild.value = '// <![CDATA[\n' + trim(value) + '\n// ]]>';
- }
- } else {
- if (value.length > 0) {
- node.firstChild.value = '<!--\n' + trim(value) + '\n-->';
- }
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value.length > 0) {
+ node.firstChild.value = '// <![CDATA[\n' + trim(value) + '\n// ]]>';
+ }
+ } else {
+ if (value.length > 0) {
+ node.firstChild.value = '<!--\n' + trim(value) + '\n-->';
+ }
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Convert comments to cdata and handle protected comments
- htmlParser.addNodeFilter('#comment', function(nodes) {
- var i = nodes.length, node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Convert comments to cdata and handle protected comments
+ htmlParser.addNodeFilter('#comment', function (nodes) {
+ var i = nodes.length, node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.value.indexOf('[CDATA[') === 0) {
- node.name = '#cdata';
- node.type = 4;
- node.value = node.value.replace(/^\[CDATA\[|\]\]$/g, '');
- } else if (node.value.indexOf('mce:protected ') === 0) {
- node.name = "#text";
- node.type = 3;
- node.raw = true;
- node.value = unescape(node.value).substr(14);
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.value.indexOf('[CDATA[') === 0) {
+ node.name = '#cdata';
+ node.type = 4;
+ node.value = node.value.replace(/^\[CDATA\[|\]\]$/g, '');
+ } else if (node.value.indexOf('mce:protected ') === 0) {
+ node.name = "#text";
+ node.type = 3;
+ node.raw = true;
+ node.value = unescape(node.value).substr(14);
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- htmlParser.addNodeFilter('xml:namespace,input', function(nodes, name) {
- var i = nodes.length, node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ htmlParser.addNodeFilter('xml:namespace,input', function (nodes, name) {
+ var i = nodes.length, node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i];
- if (node.type === 7) {
- node.remove();
- } else if (node.type === 1) {
- if (name === "input" && !("type" in node.attributes.map)) {
- node.attr('type', 'text');
- }
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i];
+ if (node.type === 7) {
+ node.remove();
+ } else if (node.type === 1) {
+ if (name === "input" && !("type" in node.attributes.map)) {
+ node.attr('type', 'text');
+ }
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove internal data attributes
- htmlParser.addAttributeFilter(
- 'data-mce-src,data-mce-href,data-mce-style,' +
- 'data-mce-selected,data-mce-expando,' +
- 'data-mce-type,data-mce-resize',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove internal data attributes
+ htmlParser.addAttributeFilter(
+ 'data-mce-src,data-mce-href,data-mce-style,' +
+ 'data-mce-selected,data-mce-expando,' +
+ 'data-mce-type,data-mce-resize',
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function(nodes, name) {
- var i = nodes.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function (nodes, name) {
+ var i = nodes.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- nodes[i].attr(name, null);
- }
- }
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ nodes[i].attr(name, null);
+ }
+ }
+ );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Return public methods
- return {
- /**
- * Schema instance that was used to when the Serializer was constructed.
- *
- * @field {tinymce.html.Schema} schema
- */
- schema: schema,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Return public methods
+ return {
+ /**
+ * Schema instance that was used to when the Serializer was constructed.
+ *
+ * @field {tinymce.html.Schema} schema
+ */
+ schema: schema,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds a node filter function to the parser used by the serializer, the parser will collect the specified nodes by name
- * and then execute the callback ones it has finished parsing the document.
- *
- * @example
- * parser.addNodeFilter('p,h1', function(nodes, name) {
- * for (var i = 0; i < nodes.length; i++) {
- * console.log(nodes[i].name);
- * }
- * });
- * @method addNodeFilter
- * @method {String} name Comma separated list of nodes to collect.
- * @param {function} callback Callback function to execute once it has collected nodes.
- */
- addNodeFilter: htmlParser.addNodeFilter,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds a node filter function to the parser used by the serializer, the parser will collect the specified nodes by name
+ * and then execute the callback ones it has finished parsing the document.
+ *
+ * @example
+ * parser.addNodeFilter('p,h1', function(nodes, name) {
+ * for (var i = 0; i < nodes.length; i++) {
+ * console.log(nodes[i].name);
+ * }
+ * });
+ * @method addNodeFilter
+ * @method {String} name Comma separated list of nodes to collect.
+ * @param {function} callback Callback function to execute once it has collected nodes.
+ */
+ addNodeFilter: htmlParser.addNodeFilter,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds a attribute filter function to the parser used by the serializer, the parser will
- * collect nodes that has the specified attributes
- * and then execute the callback ones it has finished parsing the document.
- *
- * @example
- * parser.addAttributeFilter('src,href', function(nodes, name) {
- * for (var i = 0; i < nodes.length; i++) {
- * console.log(nodes[i].name);
- * }
- * });
- * @method addAttributeFilter
- * @method {String} name Comma separated list of nodes to collect.
- * @param {function} callback Callback function to execute once it has collected nodes.
- */
- addAttributeFilter: htmlParser.addAttributeFilter,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds a attribute filter function to the parser used by the serializer, the parser will
+ * collect nodes that has the specified attributes
+ * and then execute the callback ones it has finished parsing the document.
+ *
+ * @example
+ * parser.addAttributeFilter('src,href', function(nodes, name) {
+ * for (var i = 0; i < nodes.length; i++) {
+ * console.log(nodes[i].name);
+ * }
+ * });
+ * @method addAttributeFilter
+ * @method {String} name Comma separated list of nodes to collect.
+ * @param {function} callback Callback function to execute once it has collected nodes.
+ */
+ addAttributeFilter: htmlParser.addAttributeFilter,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Serializes the specified browser DOM node into a HTML string.
- *
- * @method serialize
- * @param {DOMNode} node DOM node to serialize.
- * @param {Object} args Arguments option that gets passed to event handlers.
- */
- serialize: function(node, args) {
- var self = this, impl, doc, oldDoc, htmlSerializer, content, rootNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Serializes the specified browser DOM node into a HTML string.
+ *
+ * @method serialize
+ * @param {DOMNode} node DOM node to serialize.
+ * @param {Object} args Arguments option that gets passed to event handlers.
+ */
+ serialize: function (node, args) {
+ var self = this, impl, doc, oldDoc, htmlSerializer, content, rootNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Explorer won't clone contents of script and style and the
- // selected index of select elements are cleared on a clone operation.
- if (Env.ie && dom.select('script,style,select,map').length > 0) {
- content = node.innerHTML;
- node = node.cloneNode(false);
- dom.setHTML(node, content);
- } else {
- node = node.cloneNode(true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Explorer won't clone contents of script and style and the
+ // selected index of select elements are cleared on a clone operation.
+ if (Env.ie && dom.select('script,style,select,map').length > 0) {
+ content = node.innerHTML;
+ node = node.cloneNode(false);
+ dom.setHTML(node, content);
+ } else {
+ node = node.cloneNode(true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Nodes needs to be attached to something in WebKit/Opera
- // This fix will make DOM ranges and make Sizzle happy!
- impl = document.implementation;
- if (impl.createHTMLDocument) {
- // Create an empty HTML document
- doc = impl.createHTMLDocument("");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Nodes needs to be attached to something in WebKit/Opera
+ // This fix will make DOM ranges and make Sizzle happy!
+ impl = document.implementation;
+ if (impl.createHTMLDocument) {
+ // Create an empty HTML document
+ doc = impl.createHTMLDocument("");
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add the element or it's children if it's a body element to the new document
- each(node.nodeName == 'BODY' ? node.childNodes : [node], function(node) {
- doc.body.appendChild(doc.importNode(node, true));
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add the element or it's children if it's a body element to the new document
+ each(node.nodeName == 'BODY' ? node.childNodes : [node], function (node) {
+ doc.body.appendChild(doc.importNode(node, true));
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Grab first child or body element for serialization
- if (node.nodeName != 'BODY') {
- node = doc.body.firstChild;
- } else {
- node = doc.body;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Grab first child or body element for serialization
+ if (node.nodeName != 'BODY') {
+ node = doc.body.firstChild;
+ } else {
+ node = doc.body;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // set the new document in DOMUtils so createElement etc works
- oldDoc = dom.doc;
- dom.doc = doc;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // set the new document in DOMUtils so createElement etc works
+ oldDoc = dom.doc;
+ dom.doc = doc;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args = args || {};
- args.format = args.format || 'html';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args = args || {};
+ args.format = args.format || 'html';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Don't wrap content if we want selected html
- if (args.selection) {
- args.forced_root_block = '';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't wrap content if we want selected html
+ if (args.selection) {
+ args.forced_root_block = '';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Pre process
- if (!args.no_events) {
- args.node = node;
- self.onPreProcess(args);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Pre process
+ if (!args.no_events) {
+ args.node = node;
+ self.onPreProcess(args);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Parse HTML
- rootNode = htmlParser.parse(trim(args.getInner ? node.innerHTML : dom.getOuterHTML(node)), args);
- trimTrailingBr(rootNode);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Parse HTML
+ rootNode = htmlParser.parse(trim(args.getInner ? node.innerHTML : dom.getOuterHTML(node)), args);
+ trimTrailingBr(rootNode);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Serialize HTML
- htmlSerializer = new Serializer(settings, schema);
- args.content = htmlSerializer.serialize(rootNode);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Serialize HTML
+ htmlSerializer = new Serializer(settings, schema);
+ args.content = htmlSerializer.serialize(rootNode);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Replace all BOM characters for now until we can find a better solution
- if (!args.cleanup) {
- args.content = Zwsp.trim(args.content);
- args.content = args.content.replace(/\uFEFF/g, '');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Replace all BOM characters for now until we can find a better solution
+ if (!args.cleanup) {
+ args.content = Zwsp.trim(args.content);
+ args.content = args.content.replace(/\uFEFF/g, '');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Post process
- if (!args.no_events) {
- self.onPostProcess(args);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Post process
+ if (!args.no_events) {
+ self.onPostProcess(args);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Restore the old document if it was changed
- if (oldDoc) {
- dom.doc = oldDoc;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Restore the old document if it was changed
+ if (oldDoc) {
+ dom.doc = oldDoc;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args.node = null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args.node = null;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return args.content;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return args.content;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds valid elements rules to the serializers schema instance this enables you to specify things
- * like what elements should be outputted and what attributes specific elements might have.
- * Consult the Wiki for more details on this format.
- *
- * @method addRules
- * @param {String} rules Valid elements rules string to add to schema.
- */
- addRules: function(rules) {
- schema.addValidElements(rules);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds valid elements rules to the serializers schema instance this enables you to specify things
+ * like what elements should be outputted and what attributes specific elements might have.
+ * Consult the Wiki for more details on this format.
+ *
+ * @method addRules
+ * @param {String} rules Valid elements rules string to add to schema.
+ */
+ addRules: function (rules) {
+ schema.addValidElements(rules);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets the valid elements rules to the serializers schema instance this enables you to specify things
- * like what elements should be outputted and what attributes specific elements might have.
- * Consult the Wiki for more details on this format.
- *
- * @method setRules
- * @param {String} rules Valid elements rules string.
- */
- setRules: function(rules) {
- schema.setValidElements(rules);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets the valid elements rules to the serializers schema instance this enables you to specify things
+ * like what elements should be outputted and what attributes specific elements might have.
+ * Consult the Wiki for more details on this format.
+ *
+ * @method setRules
+ * @param {String} rules Valid elements rules string.
+ */
+ setRules: function (rules) {
+ schema.setValidElements(rules);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- onPreProcess: function(args) {
- if (editor) {
- editor.fire('PreProcess', args);
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ onPreProcess: function (args) {
+ if (editor) {
+ editor.fire('PreProcess', args);
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- onPostProcess: function(args) {
- if (editor) {
- editor.fire('PostProcess', args);
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ onPostProcess: function (args) {
+ if (editor) {
+ editor.fire('PostProcess', args);
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds a temporary internal attribute these attributes will get removed on undo and
- * when getting contents out of the editor.
- *
- * @method addTempAttr
- * @param {String} name string
- */
- addTempAttr: addTempAttr,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds a temporary internal attribute these attributes will get removed on undo and
+ * when getting contents out of the editor.
+ *
+ * @method addTempAttr
+ * @param {String} name string
+ */
+ addTempAttr: addTempAttr,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Internal
- trimHtml: trimHtml,
- getTrimmedContent: getTrimmedContent,
- trimContent: trimContent
- };
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Internal
+ trimHtml: trimHtml,
+ getTrimmedContent: getTrimmedContent,
+ trimContent: trimContent
+ };
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/dom/TridentSelection.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * TridentSelection.js
- *
- * Released under LGPL License.
- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- */
-
-/**
- * Selection class for old explorer versions. This one fakes the
- * native selection object available on modern browsers.
- *
- * @private
- * @class tinymce.dom.TridentSelection
- */
-define("tinymce/dom/TridentSelection", [], function() {
- function Selection(selection) {
- var self = this, dom = selection.dom, FALSE = false;
-
- function getPosition(rng, start) {
- var checkRng, startIndex = 0, endIndex, inside,
- children, child, offset, index, position = -1, parent;
-
- // Setup test range, collapse it and get the parent
- checkRng = rng.duplicate();
- checkRng.collapse(start);
- parent = checkRng.parentElement();
-
- // Check if the selection is within the right document
- if (parent.ownerDocument !== selection.dom.doc) {
- return;
- }
-
- // IE will report non editable elements as it's parent so look for an editable one
- while (parent.contentEditable === "false") {
- parent = parent.parentNode;
- }
-
- // If parent doesn't have any children then return that we are inside the element
- if (!parent.hasChildNodes()) {
- return {node: parent, inside: 1};
- }
-
- // Setup node list and endIndex
- children = parent.children;
- endIndex = children.length - 1;
-
- // Perform a binary search for the position
- while (startIndex <= endIndex) {
- index = Math.floor((startIndex + endIndex) / 2);
-
- // Move selection to node and compare the ranges
- child = children[index];
- checkRng.moveToElementText(child);
- position = checkRng.compareEndPoints(start ? 'StartToStart' : 'EndToEnd', rng);
-
- // Before/after or an exact match
- if (position > 0) {
- endIndex = index - 1;
- } else if (position < 0) {
- startIndex = index + 1;
- } else {
- return {node: child};
- }
- }
-
- // Check if child position is before or we didn't find a position
- if (position < 0) {
- // No element child was found use the parent element and the offset inside that
- if (!child) {
- checkRng.moveToElementText(parent);
- checkRng.collapse(true);
- child = parent;
- inside = true;
- } else {
- checkRng.collapse(false);
- }
-
- // Walk character by character in text node until we hit the selected range endpoint,
- // hit the end of document or parent isn't the right one
- // We need to walk char by char since rng.text or rng.htmlText will trim line endings
- offset = 0;
- while (checkRng.compareEndPoints(start ? 'StartToStart' : 'StartToEnd', rng) !== 0) {
- if (checkRng.move('character', 1) === 0 || parent != checkRng.parentElement()) {
- break;
- }
-
- offset++;
- }
- } else {
- // Child position is after the selection endpoint
- checkRng.collapse(true);
-
- // Walk character by character in text node until we hit the selected range endpoint, hit
- // the end of document or parent isn't the right one
- offset = 0;
- while (checkRng.compareEndPoints(start ? 'StartToStart' : 'StartToEnd', rng) !== 0) {
- if (checkRng.move('character', -1) === 0 || parent != checkRng.parentElement()) {
- break;
- }
-
- offset++;
- }
- }
-
- return {node: child, position: position, offset: offset, inside: inside};
- }
-
- // Returns a W3C DOM compatible range object by using the IE Range API
- function getRange() {
- var ieRange = selection.getRng(), domRange = dom.createRng(), element, collapsed, tmpRange, element2, bookmark;
-
- // If selection is outside the current document just return an empty range
- element = ieRange.item ? ieRange.item(0) : ieRange.parentElement();
- if (element.ownerDocument != dom.doc) {
- return domRange;
- }
-
- collapsed = selection.isCollapsed();
-
- // Handle control selection
- if (ieRange.item) {
- domRange.setStart(element.parentNode, dom.nodeIndex(element));
- domRange.setEnd(domRange.startContainer, domRange.startOffset + 1);
-
- return domRange;
- }
-
- function findEndPoint(start) {
- var endPoint = getPosition(ieRange, start), container, offset, textNodeOffset = 0, sibling, undef, nodeValue;
-
- container = endPoint.node;
- offset = endPoint.offset;
-
- if (endPoint.inside && !container.hasChildNodes()) {
- domRange[start ? 'setStart' : 'setEnd'](container, 0);
- return;
- }
-
- if (offset === undef) {
- domRange[start ? 'setStartBefore' : 'setEndAfter'](container);
- return;
- }
-
- if (endPoint.position < 0) {
- sibling = endPoint.inside ? container.firstChild : container.nextSibling;
-
- if (!sibling) {
- domRange[start ? 'setStartAfter' : 'setEndAfter'](container);
- return;
- }
-
- if (!offset) {
- if (sibling.nodeType == 3) {
- domRange[start ? 'setStart' : 'setEnd'](sibling, 0);
- } else {
- domRange[start ? 'setStartBefore' : 'setEndBefore'](sibling);
- }
-
- return;
- }
-
- // Find the text node and offset
- while (sibling) {
- if (sibling.nodeType == 3) {
- nodeValue = sibling.nodeValue;
- textNodeOffset += nodeValue.length;
-
- // We are at or passed the position we where looking for
- if (textNodeOffset >= offset) {
- container = sibling;
- textNodeOffset -= offset;
- textNodeOffset = nodeValue.length - textNodeOffset;
- break;
- }
- }
-
- sibling = sibling.nextSibling;
- }
- } else {
- // Find the text node and offset
- sibling = container.previousSibling;
-
- if (!sibling) {
- return domRange[start ? 'setStartBefore' : 'setEndBefore'](container);
- }
-
- // If there isn't any text to loop then use the first position
- if (!offset) {
- if (container.nodeType == 3) {
- domRange[start ? 'setStart' : 'setEnd'](sibling, container.nodeValue.length);
- } else {
- domRange[start ? 'setStartAfter' : 'setEndAfter'](sibling);
- }
-
- return;
- }
-
- while (sibling) {
- if (sibling.nodeType == 3) {
- textNodeOffset += sibling.nodeValue.length;
-
- // We are at or passed the position we where looking for
- if (textNodeOffset >= offset) {
- container = sibling;
- textNodeOffset -= offset;
- break;
- }
- }
-
- sibling = sibling.previousSibling;
- }
- }
-
- domRange[start ? 'setStart' : 'setEnd'](container, textNodeOffset);
- }
-
- try {
- // Find start point
- findEndPoint(true);
-
- // Find end point if needed
- if (!collapsed) {
- findEndPoint();
- }
- } catch (ex) {
- // IE has a nasty bug where text nodes might throw "invalid argument" when you
- // access the nodeValue or other properties of text nodes. This seems to happen when
- // text nodes are split into two nodes by a delete/backspace call.
- // So let us detect and try to fix it.
- if (ex.number == -2147024809) {
- // Get the current selection
- bookmark = self.getBookmark(2);
-
- // Get start element
- tmpRange = ieRange.duplicate();
- tmpRange.collapse(true);
- element = tmpRange.parentElement();
-
- // Get end element
- if (!collapsed) {
- tmpRange = ieRange.duplicate();
- tmpRange.collapse(false);
- element2 = tmpRange.parentElement();
- element2.innerHTML = element2.innerHTML;
- }
-
- // Remove the broken elements
- element.innerHTML = element.innerHTML;
-
- // Restore the selection
- self.moveToBookmark(bookmark);
-
- // Since the range has moved we need to re-get it
- ieRange = selection.getRng();
-
- // Find start point
- findEndPoint(true);
-
- // Find end point if needed
- if (!collapsed) {
- findEndPoint();
- }
- } else {
- throw ex; // Throw other errors
- }
- }
-
- return domRange;
- }
-
- this.getBookmark = function(type) {
- var rng = selection.getRng(), bookmark = {};
-
- function getIndexes(node) {
- var parent, root, children, i, indexes = [];
-
- parent = node.parentNode;
- root = dom.getRoot().parentNode;
-
- while (parent != root && parent.nodeType !== 9) {
- children = parent.children;
-
- i = children.length;
- while (i--) {
- if (node === children[i]) {
- indexes.push(i);
- break;
- }
- }
-
- node = parent;
- parent = parent.parentNode;
- }
-
- return indexes;
- }
-
- function getBookmarkEndPoint(start) {
- var position;
-
- position = getPosition(rng, start);
- if (position) {
- return {
- position: position.position,
- offset: position.offset,
- indexes: getIndexes(position.node),
- inside: position.inside
- };
- }
- }
-
- // Non ubstructive bookmark
- if (type === 2) {
- // Handle text selection
- if (!rng.item) {
- bookmark.start = getBookmarkEndPoint(true);
-
- if (!selection.isCollapsed()) {
- bookmark.end = getBookmarkEndPoint();
- }
- } else {
- bookmark.start = {ctrl: true, indexes: getIndexes(rng.item(0))};
- }
- }
-
- return bookmark;
- };
-
- this.moveToBookmark = function(bookmark) {
- var rng, body = dom.doc.body;
-
- function resolveIndexes(indexes) {
- var node, i, idx, children;
-
- node = dom.getRoot();
- for (i = indexes.length - 1; i >= 0; i--) {
- children = node.children;
- idx = indexes[i];
-
- if (idx <= children.length - 1) {
- node = children[idx];
- }
- }
-
- return node;
- }
-
- function setBookmarkEndPoint(start) {
- var endPoint = bookmark[start ? 'start' : 'end'], moveLeft, moveRng, undef, offset;
-
- if (endPoint) {
- moveLeft = endPoint.position > 0;
-
- moveRng = body.createTextRange();
- moveRng.moveToElementText(resolveIndexes(endPoint.indexes));
-
- offset = endPoint.offset;
- if (offset !== undef) {
- moveRng.collapse(endPoint.inside || moveLeft);
- moveRng.moveStart('character', moveLeft ? -offset : offset);
- } else {
- moveRng.collapse(start);
- }
-
- rng.setEndPoint(start ? 'StartToStart' : 'EndToStart', moveRng);
-
- if (start) {
- rng.collapse(true);
- }
- }
- }
-
- if (bookmark.start) {
- if (bookmark.start.ctrl) {
- rng = body.createControlRange();
- rng.addElement(resolveIndexes(bookmark.start.indexes));
- rng.select();
- } else {
- rng = body.createTextRange();
- setBookmarkEndPoint(true);
- setBookmarkEndPoint();
- rng.select();
- }
- }
- };
-
- this.addRange = function(rng) {
- var ieRng, ctrlRng, startContainer, startOffset, endContainer, endOffset, sibling,
- doc = selection.dom.doc, body = doc.body, nativeRng, ctrlElm;
-
- function setEndPoint(start) {
- var container, offset, marker, tmpRng, nodes;
-
- marker = dom.create('a');
- container = start ? startContainer : endContainer;
- offset = start ? startOffset : endOffset;
- tmpRng = ieRng.duplicate();
-
- if (container == doc || container == doc.documentElement) {
- container = body;
- offset = 0;
- }
-
- if (container.nodeType == 3) {
- container.parentNode.insertBefore(marker, container);
- tmpRng.moveToElementText(marker);
- tmpRng.moveStart('character', offset);
- dom.remove(marker);
- ieRng.setEndPoint(start ? 'StartToStart' : 'EndToEnd', tmpRng);
- } else {
- nodes = container.childNodes;
-
- if (nodes.length) {
- if (offset >= nodes.length) {
- dom.insertAfter(marker, nodes[nodes.length - 1]);
- } else {
- container.insertBefore(marker, nodes[offset]);
- }
-
- tmpRng.moveToElementText(marker);
- } else if (container.canHaveHTML) {
- // Empty node selection for example <div>|</div>
- // Setting innerHTML with a span marker then remove that marker seems to keep empty block elements open
- container.innerHTML = '<span></span>';
- marker = container.firstChild;
- tmpRng.moveToElementText(marker);
- tmpRng.collapse(FALSE); // Collapse false works better than true for some odd reason
- }
-
- ieRng.setEndPoint(start ? 'StartToStart' : 'EndToEnd', tmpRng);
- dom.remove(marker);
- }
- }
-
- // Setup some shorter versions
- startContainer = rng.startContainer;
- startOffset = rng.startOffset;
- endContainer = rng.endContainer;
- endOffset = rng.endOffset;
- ieRng = body.createTextRange();
-
- // If single element selection then try making a control selection out of it
- if (startContainer == endContainer && startContainer.nodeType == 1) {
- // Trick to place the caret inside an empty block element like <p></p>
- if (startOffset == endOffset && !startContainer.hasChildNodes()) {
- if (startContainer.canHaveHTML) {
- // Check if previous sibling is an empty block if it is then we need to render it
- // IE would otherwise move the caret into the sibling instead of the empty startContainer see: #5236
- // Example this: <p></p><p>|</p> would become this: <p>|</p><p></p>
- sibling = startContainer.previousSibling;
- if (sibling && !sibling.hasChildNodes() && dom.isBlock(sibling)) {
- sibling.innerHTML = '';
- } else {
- sibling = null;
- }
-
- startContainer.innerHTML = '<span></span><span></span>';
- ieRng.moveToElementText(startContainer.lastChild);
- ieRng.select();
- dom.doc.selection.clear();
- startContainer.innerHTML = '';
-
- if (sibling) {
- sibling.innerHTML = '';
- }
- return;
- }
-
- startOffset = dom.nodeIndex(startContainer);
- startContainer = startContainer.parentNode;
- }
-
- if (startOffset == endOffset - 1) {
- try {
- ctrlElm = startContainer.childNodes[startOffset];
- ctrlRng = body.createControlRange();
- ctrlRng.addElement(ctrlElm);
- ctrlRng.select();
-
- // Check if the range produced is on the correct element and is a control range
- // On IE 8 it will select the parent contentEditable container if you select an inner element see: #5398
- nativeRng = selection.getRng();
- if (nativeRng.item && ctrlElm === nativeRng.item(0)) {
- return;
- }
- } catch (ex) {
- // Ignore
- }
- }
- }
-
- // Set start/end point of selection
- setEndPoint(true);
- setEndPoint();
-
- // Select the new range and scroll it into view
- ieRng.select();
- };
-
- // Expose range method
- this.getRangeAt = getRange;
- }
-
- return Selection;
-});
-
-// Included from: js/tinymce/classes/util/VK.js
-
-/**
</del><span class="cx" style="display: block; padding: 0 10px"> * VK.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -15436,38 +15853,40 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * This file exposes a set of the common KeyCodes for use. Please grow it as needed.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/util/VK", [
- "tinymce/Env"
-], function(Env) {
- return {
- BACKSPACE: 8,
- DELETE: 46,
- DOWN: 40,
- ENTER: 13,
- LEFT: 37,
- RIGHT: 39,
- SPACEBAR: 32,
- TAB: 9,
- UP: 38,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.VK',
+ [
+ "tinymce.core.Env"
+ ],
+ function (Env) {
+ return {
+ BACKSPACE: 8,
+ DELETE: 46,
+ DOWN: 40,
+ ENTER: 13,
+ LEFT: 37,
+ RIGHT: 39,
+ SPACEBAR: 32,
+ TAB: 9,
+ UP: 38,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- modifierPressed: function(e) {
- return e.shiftKey || e.ctrlKey || e.altKey || this.metaKeyPressed(e);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ modifierPressed: function (e) {
+ return e.shiftKey || e.ctrlKey || e.altKey || this.metaKeyPressed(e);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- metaKeyPressed: function(e) {
- // Check if ctrl or meta key is pressed. Edge case for AltGr on Windows where it produces ctrlKey+altKey states
- return (Env.mac ? e.metaKey : e.ctrlKey && !e.altKey);
- }
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ metaKeyPressed: function (e) {
+ // Check if ctrl or meta key is pressed. Edge case for AltGr on Windows where it produces ctrlKey+altKey states
+ return (Env.mac ? e.metaKey : e.ctrlKey && !e.altKey);
+ }
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/dom/ControlSelection.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * ControlSelection.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -15480,649 +15899,651 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.dom.ControlSelection
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/dom/ControlSelection", [
- "tinymce/util/VK",
- "tinymce/util/Tools",
- "tinymce/util/Delay",
- "tinymce/Env",
- "tinymce/dom/NodeType"
-], function(VK, Tools, Delay, Env, NodeType) {
- var isContentEditableFalse = NodeType.isContentEditableFalse;
- var isContentEditableTrue = NodeType.isContentEditableTrue;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.ControlSelection',
+ [
+ "tinymce.core.util.VK",
+ "tinymce.core.util.Tools",
+ "tinymce.core.util.Delay",
+ "tinymce.core.Env",
+ "tinymce.core.dom.NodeType"
+ ],
+ function (VK, Tools, Delay, Env, NodeType) {
+ var isContentEditableFalse = NodeType.isContentEditableFalse;
+ var isContentEditableTrue = NodeType.isContentEditableTrue;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getContentEditableRoot(root, node) {
- while (node && node != root) {
- if (isContentEditableTrue(node) || isContentEditableFalse(node)) {
- return node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getContentEditableRoot(root, node) {
+ while (node && node != root) {
+ if (isContentEditableTrue(node) || isContentEditableFalse(node)) {
+ return node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function(selection, editor) {
- var dom = editor.dom, each = Tools.each;
- var selectedElm, selectedElmGhost, resizeHelper, resizeHandles, selectedHandle, lastMouseDownEvent;
- var startX, startY, selectedElmX, selectedElmY, startW, startH, ratio, resizeStarted;
- var width, height, editableDoc = editor.getDoc(), rootDocument = document, isIE = Env.ie && Env.ie < 11;
- var abs = Math.abs, round = Math.round, rootElement = editor.getBody(), startScrollWidth, startScrollHeight;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function (selection, editor) {
+ var dom = editor.dom, each = Tools.each;
+ var selectedElm, selectedElmGhost, resizeHelper, resizeHandles, selectedHandle, lastMouseDownEvent;
+ var startX, startY, selectedElmX, selectedElmY, startW, startH, ratio, resizeStarted;
+ var width, height, editableDoc = editor.getDoc(), rootDocument = document, isIE = Env.ie && Env.ie < 11;
+ var abs = Math.abs, round = Math.round, rootElement = editor.getBody(), startScrollWidth, startScrollHeight;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Details about each resize handle how to scale etc
- resizeHandles = {
- // Name: x multiplier, y multiplier, delta size x, delta size y
- /*n: [0.5, 0, 0, -1],
- e: [1, 0.5, 1, 0],
- s: [0.5, 1, 0, 1],
- w: [0, 0.5, -1, 0],*/
- nw: [0, 0, -1, -1],
- ne: [1, 0, 1, -1],
- se: [1, 1, 1, 1],
- sw: [0, 1, -1, 1]
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Details about each resize handle how to scale etc
+ resizeHandles = {
+ // Name: x multiplier, y multiplier, delta size x, delta size y
+ /*n: [0.5, 0, 0, -1],
+ e: [1, 0.5, 1, 0],
+ s: [0.5, 1, 0, 1],
+ w: [0, 0.5, -1, 0],*/
+ nw: [0, 0, -1, -1],
+ ne: [1, 0, 1, -1],
+ se: [1, 1, 1, 1],
+ sw: [0, 1, -1, 1]
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add CSS for resize handles, cloned element and selected
- var rootClass = '.mce-content-body';
- editor.contentStyles.push(
- rootClass + ' div.mce-resizehandle {' +
- 'position: absolute;' +
- 'border: 1px solid black;' +
- 'box-sizing: box-sizing;' +
- 'background: #FFF;' +
- 'width: 7px;' +
- 'height: 7px;' +
- 'z-index: 10000' +
- '}' +
- rootClass + ' .mce-resizehandle:hover {' +
- 'background: #000' +
- '}' +
- rootClass + ' img[data-mce-selected],' + rootClass + ' hr[data-mce-selected] {' +
- 'outline: 1px solid black;' +
- 'resize: none' + // Have been talks about implementing this in browsers
- '}' +
- rootClass + ' .mce-clonedresizable {' +
- 'position: absolute;' +
- (Env.gecko ? '' : 'outline: 1px dashed black;') + // Gecko produces trails while resizing
- 'opacity: .5;' +
- 'filter: alpha(opacity=50);' +
- 'z-index: 10000' +
- '}' +
- rootClass + ' .mce-resize-helper {' +
- 'background: #555;' +
- 'background: rgba(0,0,0,0.75);' +
- 'border-radius: 3px;' +
- 'border: 1px;' +
- 'color: white;' +
- 'display: none;' +
- 'font-family: sans-serif;' +
- 'font-size: 12px;' +
- 'white-space: nowrap;' +
- 'line-height: 14px;' +
- 'margin: 5px 10px;' +
- 'padding: 5px;' +
- 'position: absolute;' +
- 'z-index: 10001' +
- '}'
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add CSS for resize handles, cloned element and selected
+ var rootClass = '.mce-content-body';
+ editor.contentStyles.push(
+ rootClass + ' div.mce-resizehandle {' +
+ 'position: absolute;' +
+ 'border: 1px solid black;' +
+ 'box-sizing: box-sizing;' +
+ 'background: #FFF;' +
+ 'width: 7px;' +
+ 'height: 7px;' +
+ 'z-index: 10000' +
+ '}' +
+ rootClass + ' .mce-resizehandle:hover {' +
+ 'background: #000' +
+ '}' +
+ rootClass + ' img[data-mce-selected],' + rootClass + ' hr[data-mce-selected] {' +
+ 'outline: 1px solid black;' +
+ 'resize: none' + // Have been talks about implementing this in browsers
+ '}' +
+ rootClass + ' .mce-clonedresizable {' +
+ 'position: absolute;' +
+ (Env.gecko ? '' : 'outline: 1px dashed black;') + // Gecko produces trails while resizing
+ 'opacity: .5;' +
+ 'filter: alpha(opacity=50);' +
+ 'z-index: 10000' +
+ '}' +
+ rootClass + ' .mce-resize-helper {' +
+ 'background: #555;' +
+ 'background: rgba(0,0,0,0.75);' +
+ 'border-radius: 3px;' +
+ 'border: 1px;' +
+ 'color: white;' +
+ 'display: none;' +
+ 'font-family: sans-serif;' +
+ 'font-size: 12px;' +
+ 'white-space: nowrap;' +
+ 'line-height: 14px;' +
+ 'margin: 5px 10px;' +
+ 'padding: 5px;' +
+ 'position: absolute;' +
+ 'z-index: 10001' +
+ '}'
+ );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isResizable(elm) {
- var selector = editor.settings.object_resizing;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isResizable(elm) {
+ var selector = editor.settings.object_resizing;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (selector === false || Env.iOS) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (selector === false || Env.iOS) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof selector != 'string') {
- selector = 'table,img,div';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof selector != 'string') {
+ selector = 'table,img,div';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elm.getAttribute('data-mce-resize') === 'false') {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (elm.getAttribute('data-mce-resize') === 'false') {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elm == editor.getBody()) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (elm == editor.getBody()) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return editor.dom.is(elm, selector);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return editor.dom.is(elm, selector);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function resizeGhostElement(e) {
- var deltaX, deltaY, proportional;
- var resizeHelperX, resizeHelperY;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function resizeGhostElement(e) {
+ var deltaX, deltaY, proportional;
+ var resizeHelperX, resizeHelperY;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Calc new width/height
- deltaX = e.screenX - startX;
- deltaY = e.screenY - startY;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Calc new width/height
+ deltaX = e.screenX - startX;
+ deltaY = e.screenY - startY;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Calc new size
- width = deltaX * selectedHandle[2] + startW;
- height = deltaY * selectedHandle[3] + startH;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Calc new size
+ width = deltaX * selectedHandle[2] + startW;
+ height = deltaY * selectedHandle[3] + startH;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Never scale down lower than 5 pixels
- width = width < 5 ? 5 : width;
- height = height < 5 ? 5 : height;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Never scale down lower than 5 pixels
+ width = width < 5 ? 5 : width;
+ height = height < 5 ? 5 : height;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (selectedElm.nodeName == "IMG" && editor.settings.resize_img_proportional !== false) {
- proportional = !VK.modifierPressed(e);
- } else {
- proportional = VK.modifierPressed(e) || (selectedElm.nodeName == "IMG" && selectedHandle[2] * selectedHandle[3] !== 0);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (selectedElm.nodeName == "IMG" && editor.settings.resize_img_proportional !== false) {
+ proportional = !VK.modifierPressed(e);
+ } else {
+ proportional = VK.modifierPressed(e) || (selectedElm.nodeName == "IMG" && selectedHandle[2] * selectedHandle[3] !== 0);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Constrain proportions
- if (proportional) {
- if (abs(deltaX) > abs(deltaY)) {
- height = round(width * ratio);
- width = round(height / ratio);
- } else {
- width = round(height / ratio);
- height = round(width * ratio);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Constrain proportions
+ if (proportional) {
+ if (abs(deltaX) > abs(deltaY)) {
+ height = round(width * ratio);
+ width = round(height / ratio);
+ } else {
+ width = round(height / ratio);
+ height = round(width * ratio);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Update ghost size
- dom.setStyles(selectedElmGhost, {
- width: width,
- height: height
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Update ghost size
+ dom.setStyles(selectedElmGhost, {
+ width: width,
+ height: height
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Update resize helper position
- resizeHelperX = selectedHandle.startPos.x + deltaX;
- resizeHelperY = selectedHandle.startPos.y + deltaY;
- resizeHelperX = resizeHelperX > 0 ? resizeHelperX : 0;
- resizeHelperY = resizeHelperY > 0 ? resizeHelperY : 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Update resize helper position
+ resizeHelperX = selectedHandle.startPos.x + deltaX;
+ resizeHelperY = selectedHandle.startPos.y + deltaY;
+ resizeHelperX = resizeHelperX > 0 ? resizeHelperX : 0;
+ resizeHelperY = resizeHelperY > 0 ? resizeHelperY : 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.setStyles(resizeHelper, {
- left: resizeHelperX,
- top: resizeHelperY,
- display: 'block'
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.setStyles(resizeHelper, {
+ left: resizeHelperX,
+ top: resizeHelperY,
+ display: 'block'
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- resizeHelper.innerHTML = width + ' × ' + height;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ resizeHelper.innerHTML = width + ' × ' + height;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Update ghost X position if needed
- if (selectedHandle[2] < 0 && selectedElmGhost.clientWidth <= width) {
- dom.setStyle(selectedElmGhost, 'left', selectedElmX + (startW - width));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Update ghost X position if needed
+ if (selectedHandle[2] < 0 && selectedElmGhost.clientWidth <= width) {
+ dom.setStyle(selectedElmGhost, 'left', selectedElmX + (startW - width));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Update ghost Y position if needed
- if (selectedHandle[3] < 0 && selectedElmGhost.clientHeight <= height) {
- dom.setStyle(selectedElmGhost, 'top', selectedElmY + (startH - height));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Update ghost Y position if needed
+ if (selectedHandle[3] < 0 && selectedElmGhost.clientHeight <= height) {
+ dom.setStyle(selectedElmGhost, 'top', selectedElmY + (startH - height));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Calculate how must overflow we got
- deltaX = rootElement.scrollWidth - startScrollWidth;
- deltaY = rootElement.scrollHeight - startScrollHeight;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Calculate how must overflow we got
+ deltaX = rootElement.scrollWidth - startScrollWidth;
+ deltaY = rootElement.scrollHeight - startScrollHeight;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Re-position the resize helper based on the overflow
- if (deltaX + deltaY !== 0) {
- dom.setStyles(resizeHelper, {
- left: resizeHelperX - deltaX,
- top: resizeHelperY - deltaY
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Re-position the resize helper based on the overflow
+ if (deltaX + deltaY !== 0) {
+ dom.setStyles(resizeHelper, {
+ left: resizeHelperX - deltaX,
+ top: resizeHelperY - deltaY
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!resizeStarted) {
- editor.fire('ObjectResizeStart', {target: selectedElm, width: startW, height: startH});
- resizeStarted = true;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!resizeStarted) {
+ editor.fire('ObjectResizeStart', { target: selectedElm, width: startW, height: startH });
+ resizeStarted = true;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function endGhostResize() {
- resizeStarted = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function endGhostResize() {
+ resizeStarted = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setSizeProp(name, value) {
- if (value) {
- // Resize by using style or attribute
- if (selectedElm.style[name] || !editor.schema.isValid(selectedElm.nodeName.toLowerCase(), name)) {
- dom.setStyle(selectedElm, name, value);
- } else {
- dom.setAttrib(selectedElm, name, value);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setSizeProp(name, value) {
+ if (value) {
+ // Resize by using style or attribute
+ if (selectedElm.style[name] || !editor.schema.isValid(selectedElm.nodeName.toLowerCase(), name)) {
+ dom.setStyle(selectedElm, name, value);
+ } else {
+ dom.setAttrib(selectedElm, name, value);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set width/height properties
- setSizeProp('width', width);
- setSizeProp('height', height);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set width/height properties
+ setSizeProp('width', width);
+ setSizeProp('height', height);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.unbind(editableDoc, 'mousemove', resizeGhostElement);
- dom.unbind(editableDoc, 'mouseup', endGhostResize);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.unbind(editableDoc, 'mousemove', resizeGhostElement);
+ dom.unbind(editableDoc, 'mouseup', endGhostResize);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rootDocument != editableDoc) {
- dom.unbind(rootDocument, 'mousemove', resizeGhostElement);
- dom.unbind(rootDocument, 'mouseup', endGhostResize);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rootDocument != editableDoc) {
+ dom.unbind(rootDocument, 'mousemove', resizeGhostElement);
+ dom.unbind(rootDocument, 'mouseup', endGhostResize);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove ghost/helper and update resize handle positions
- dom.remove(selectedElmGhost);
- dom.remove(resizeHelper);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove ghost/helper and update resize handle positions
+ dom.remove(selectedElmGhost);
+ dom.remove(resizeHelper);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isIE || selectedElm.nodeName == "TABLE") {
- showResizeRect(selectedElm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isIE || selectedElm.nodeName == "TABLE") {
+ showResizeRect(selectedElm);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.fire('ObjectResized', {target: selectedElm, width: width, height: height});
- dom.setAttrib(selectedElm, 'style', dom.getAttrib(selectedElm, 'style'));
- editor.nodeChanged();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.fire('ObjectResized', { target: selectedElm, width: width, height: height });
+ dom.setAttrib(selectedElm, 'style', dom.getAttrib(selectedElm, 'style'));
+ editor.nodeChanged();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function showResizeRect(targetElm, mouseDownHandleName, mouseDownEvent) {
- var position, targetWidth, targetHeight, e, rect;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function showResizeRect(targetElm, mouseDownHandleName, mouseDownEvent) {
+ var position, targetWidth, targetHeight, e, rect;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- hideResizeRect();
- unbindResizeHandleEvents();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ hideResizeRect();
+ unbindResizeHandleEvents();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Get position and size of target
- position = dom.getPos(targetElm, rootElement);
- selectedElmX = position.x;
- selectedElmY = position.y;
- rect = targetElm.getBoundingClientRect(); // Fix for Gecko offsetHeight for table with caption
- targetWidth = rect.width || (rect.right - rect.left);
- targetHeight = rect.height || (rect.bottom - rect.top);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get position and size of target
+ position = dom.getPos(targetElm, rootElement);
+ selectedElmX = position.x;
+ selectedElmY = position.y;
+ rect = targetElm.getBoundingClientRect(); // Fix for Gecko offsetHeight for table with caption
+ targetWidth = rect.width || (rect.right - rect.left);
+ targetHeight = rect.height || (rect.bottom - rect.top);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Reset width/height if user selects a new image/table
- if (selectedElm != targetElm) {
- detachResizeStartListener();
- selectedElm = targetElm;
- width = height = 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Reset width/height if user selects a new image/table
+ if (selectedElm != targetElm) {
+ detachResizeStartListener();
+ selectedElm = targetElm;
+ width = height = 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Makes it possible to disable resizing
- e = editor.fire('ObjectSelected', {target: targetElm});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Makes it possible to disable resizing
+ e = editor.fire('ObjectSelected', { target: targetElm });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isResizable(targetElm) && !e.isDefaultPrevented()) {
- each(resizeHandles, function(handle, name) {
- var handleElm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isResizable(targetElm) && !e.isDefaultPrevented()) {
+ each(resizeHandles, function (handle, name) {
+ var handleElm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function startDrag(e) {
- startX = e.screenX;
- startY = e.screenY;
- startW = selectedElm.clientWidth;
- startH = selectedElm.clientHeight;
- ratio = startH / startW;
- selectedHandle = handle;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function startDrag(e) {
+ startX = e.screenX;
+ startY = e.screenY;
+ startW = selectedElm.clientWidth;
+ startH = selectedElm.clientHeight;
+ ratio = startH / startW;
+ selectedHandle = handle;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- handle.startPos = {
- x: targetWidth * handle[0] + selectedElmX,
- y: targetHeight * handle[1] + selectedElmY
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ handle.startPos = {
+ x: targetWidth * handle[0] + selectedElmX,
+ y: targetHeight * handle[1] + selectedElmY
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- startScrollWidth = rootElement.scrollWidth;
- startScrollHeight = rootElement.scrollHeight;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ startScrollWidth = rootElement.scrollWidth;
+ startScrollHeight = rootElement.scrollHeight;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- selectedElmGhost = selectedElm.cloneNode(true);
- dom.addClass(selectedElmGhost, 'mce-clonedresizable');
- dom.setAttrib(selectedElmGhost, 'data-mce-bogus', 'all');
- selectedElmGhost.contentEditable = false; // Hides IE move layer cursor
- selectedElmGhost.unSelectabe = true;
- dom.setStyles(selectedElmGhost, {
- left: selectedElmX,
- top: selectedElmY,
- margin: 0
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ selectedElmGhost = selectedElm.cloneNode(true);
+ dom.addClass(selectedElmGhost, 'mce-clonedresizable');
+ dom.setAttrib(selectedElmGhost, 'data-mce-bogus', 'all');
+ selectedElmGhost.contentEditable = false; // Hides IE move layer cursor
+ selectedElmGhost.unSelectabe = true;
+ dom.setStyles(selectedElmGhost, {
+ left: selectedElmX,
+ top: selectedElmY,
+ margin: 0
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- selectedElmGhost.removeAttribute('data-mce-selected');
- rootElement.appendChild(selectedElmGhost);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ selectedElmGhost.removeAttribute('data-mce-selected');
+ rootElement.appendChild(selectedElmGhost);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.bind(editableDoc, 'mousemove', resizeGhostElement);
- dom.bind(editableDoc, 'mouseup', endGhostResize);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.bind(editableDoc, 'mousemove', resizeGhostElement);
+ dom.bind(editableDoc, 'mouseup', endGhostResize);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rootDocument != editableDoc) {
- dom.bind(rootDocument, 'mousemove', resizeGhostElement);
- dom.bind(rootDocument, 'mouseup', endGhostResize);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rootDocument != editableDoc) {
+ dom.bind(rootDocument, 'mousemove', resizeGhostElement);
+ dom.bind(rootDocument, 'mouseup', endGhostResize);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- resizeHelper = dom.add(rootElement, 'div', {
- 'class': 'mce-resize-helper',
- 'data-mce-bogus': 'all'
- }, startW + ' × ' + startH);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ resizeHelper = dom.add(rootElement, 'div', {
+ 'class': 'mce-resize-helper',
+ 'data-mce-bogus': 'all'
+ }, startW + ' × ' + startH);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (mouseDownHandleName) {
- // Drag started by IE native resizestart
- if (name == mouseDownHandleName) {
- startDrag(mouseDownEvent);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (mouseDownHandleName) {
+ // Drag started by IE native resizestart
+ if (name == mouseDownHandleName) {
+ startDrag(mouseDownEvent);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Get existing or render resize handle
- handleElm = dom.get('mceResizeHandle' + name);
- if (handleElm) {
- dom.remove(handleElm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get existing or render resize handle
+ handleElm = dom.get('mceResizeHandle' + name);
+ if (handleElm) {
+ dom.remove(handleElm);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- handleElm = dom.add(rootElement, 'div', {
- id: 'mceResizeHandle' + name,
- 'data-mce-bogus': 'all',
- 'class': 'mce-resizehandle',
- unselectable: true,
- style: 'cursor:' + name + '-resize; margin:0; padding:0'
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ handleElm = dom.add(rootElement, 'div', {
+ id: 'mceResizeHandle' + name,
+ 'data-mce-bogus': 'all',
+ 'class': 'mce-resizehandle',
+ unselectable: true,
+ style: 'cursor:' + name + '-resize; margin:0; padding:0'
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Hides IE move layer cursor
- // If we set it on Chrome we get this wounderful bug: #6725
- if (Env.ie) {
- handleElm.contentEditable = false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Hides IE move layer cursor
+ // If we set it on Chrome we get this wounderful bug: #6725
+ if (Env.ie) {
+ handleElm.contentEditable = false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.bind(handleElm, 'mousedown', function(e) {
- e.stopImmediatePropagation();
- e.preventDefault();
- startDrag(e);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.bind(handleElm, 'mousedown', function (e) {
+ e.stopImmediatePropagation();
+ e.preventDefault();
+ startDrag(e);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- handle.elm = handleElm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ handle.elm = handleElm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Position element
- dom.setStyles(handleElm, {
- left: (targetWidth * handle[0] + selectedElmX) - (handleElm.offsetWidth / 2),
- top: (targetHeight * handle[1] + selectedElmY) - (handleElm.offsetHeight / 2)
- });
- });
- } else {
- hideResizeRect();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Position element
+ dom.setStyles(handleElm, {
+ left: (targetWidth * handle[0] + selectedElmX) - (handleElm.offsetWidth / 2),
+ top: (targetHeight * handle[1] + selectedElmY) - (handleElm.offsetHeight / 2)
+ });
+ });
+ } else {
+ hideResizeRect();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- selectedElm.setAttribute('data-mce-selected', '1');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ selectedElm.setAttribute('data-mce-selected', '1');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hideResizeRect() {
- var name, handleElm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hideResizeRect() {
+ var name, handleElm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- unbindResizeHandleEvents();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ unbindResizeHandleEvents();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (selectedElm) {
- selectedElm.removeAttribute('data-mce-selected');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (selectedElm) {
+ selectedElm.removeAttribute('data-mce-selected');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (name in resizeHandles) {
- handleElm = dom.get('mceResizeHandle' + name);
- if (handleElm) {
- dom.unbind(handleElm);
- dom.remove(handleElm);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (name in resizeHandles) {
+ handleElm = dom.get('mceResizeHandle' + name);
+ if (handleElm) {
+ dom.unbind(handleElm);
+ dom.remove(handleElm);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function updateResizeRect(e) {
- var startElm, controlElm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function updateResizeRect(e) {
+ var startElm, controlElm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isChildOrEqual(node, parent) {
- if (node) {
- do {
- if (node === parent) {
- return true;
- }
- } while ((node = node.parentNode));
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isChildOrEqual(node, parent) {
+ if (node) {
+ do {
+ if (node === parent) {
+ return true;
+ }
+ } while ((node = node.parentNode));
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Ignore all events while resizing or if the editor instance was removed
- if (resizeStarted || editor.removed) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Ignore all events while resizing or if the editor instance was removed
+ if (resizeStarted || editor.removed) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove data-mce-selected from all elements since they might have been copied using Ctrl+c/v
- each(dom.select('img[data-mce-selected],hr[data-mce-selected]'), function(img) {
- img.removeAttribute('data-mce-selected');
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove data-mce-selected from all elements since they might have been copied using Ctrl+c/v
+ each(dom.select('img[data-mce-selected],hr[data-mce-selected]'), function (img) {
+ img.removeAttribute('data-mce-selected');
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- controlElm = e.type == 'mousedown' ? e.target : selection.getNode();
- controlElm = dom.$(controlElm).closest(isIE ? 'table' : 'table,img,hr')[0];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ controlElm = e.type == 'mousedown' ? e.target : selection.getNode();
+ controlElm = dom.$(controlElm).closest(isIE ? 'table' : 'table,img,hr')[0];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isChildOrEqual(controlElm, rootElement)) {
- disableGeckoResize();
- startElm = selection.getStart(true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isChildOrEqual(controlElm, rootElement)) {
+ disableGeckoResize();
+ startElm = selection.getStart(true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isChildOrEqual(startElm, controlElm) && isChildOrEqual(selection.getEnd(true), controlElm)) {
- if (!isIE || (controlElm != startElm && startElm.nodeName !== 'IMG')) {
- showResizeRect(controlElm);
- return;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isChildOrEqual(startElm, controlElm) && isChildOrEqual(selection.getEnd(true), controlElm)) {
+ if (!isIE || (controlElm != startElm && startElm.nodeName !== 'IMG')) {
+ showResizeRect(controlElm);
+ return;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- hideResizeRect();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ hideResizeRect();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function attachEvent(elm, name, func) {
- if (elm && elm.attachEvent) {
- elm.attachEvent('on' + name, func);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function attachEvent(elm, name, func) {
+ if (elm && elm.attachEvent) {
+ elm.attachEvent('on' + name, func);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function detachEvent(elm, name, func) {
- if (elm && elm.detachEvent) {
- elm.detachEvent('on' + name, func);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function detachEvent(elm, name, func) {
+ if (elm && elm.detachEvent) {
+ elm.detachEvent('on' + name, func);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function resizeNativeStart(e) {
- var target = e.srcElement, pos, name, corner, cornerX, cornerY, relativeX, relativeY;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function resizeNativeStart(e) {
+ var target = e.srcElement, pos, name, corner, cornerX, cornerY, relativeX, relativeY;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- pos = target.getBoundingClientRect();
- relativeX = lastMouseDownEvent.clientX - pos.left;
- relativeY = lastMouseDownEvent.clientY - pos.top;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ pos = target.getBoundingClientRect();
+ relativeX = lastMouseDownEvent.clientX - pos.left;
+ relativeY = lastMouseDownEvent.clientY - pos.top;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Figure out what corner we are draging on
- for (name in resizeHandles) {
- corner = resizeHandles[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Figure out what corner we are draging on
+ for (name in resizeHandles) {
+ corner = resizeHandles[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- cornerX = target.offsetWidth * corner[0];
- cornerY = target.offsetHeight * corner[1];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ cornerX = target.offsetWidth * corner[0];
+ cornerY = target.offsetHeight * corner[1];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (abs(cornerX - relativeX) < 8 && abs(cornerY - relativeY) < 8) {
- selectedHandle = corner;
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (abs(cornerX - relativeX) < 8 && abs(cornerY - relativeY) < 8) {
+ selectedHandle = corner;
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove native selection and let the magic begin
- resizeStarted = true;
- editor.fire('ObjectResizeStart', {
- target: selectedElm,
- width: selectedElm.clientWidth,
- height: selectedElm.clientHeight
- });
- editor.getDoc().selection.empty();
- showResizeRect(target, name, lastMouseDownEvent);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove native selection and let the magic begin
+ resizeStarted = true;
+ editor.fire('ObjectResizeStart', {
+ target: selectedElm,
+ width: selectedElm.clientWidth,
+ height: selectedElm.clientHeight
+ });
+ editor.getDoc().selection.empty();
+ showResizeRect(target, name, lastMouseDownEvent);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function preventDefault(e) {
- if (e.preventDefault) {
- e.preventDefault();
- } else {
- e.returnValue = false; // IE
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function preventDefault(e) {
+ if (e.preventDefault) {
+ e.preventDefault();
+ } else {
+ e.returnValue = false; // IE
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isWithinContentEditableFalse(elm) {
- return isContentEditableFalse(getContentEditableRoot(editor.getBody(), elm));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isWithinContentEditableFalse(elm) {
+ return isContentEditableFalse(getContentEditableRoot(editor.getBody(), elm));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function nativeControlSelect(e) {
- var target = e.srcElement;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function nativeControlSelect(e) {
+ var target = e.srcElement;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isWithinContentEditableFalse(target)) {
- preventDefault(e);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isWithinContentEditableFalse(target)) {
+ preventDefault(e);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (target != selectedElm) {
- editor.fire('ObjectSelected', {target: target});
- detachResizeStartListener();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (target != selectedElm) {
+ editor.fire('ObjectSelected', { target: target });
+ detachResizeStartListener();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (target.id.indexOf('mceResizeHandle') === 0) {
- e.returnValue = false;
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (target.id.indexOf('mceResizeHandle') === 0) {
+ e.returnValue = false;
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (target.nodeName == 'IMG' || target.nodeName == 'TABLE') {
- hideResizeRect();
- selectedElm = target;
- attachEvent(target, 'resizestart', resizeNativeStart);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (target.nodeName == 'IMG' || target.nodeName == 'TABLE') {
+ hideResizeRect();
+ selectedElm = target;
+ attachEvent(target, 'resizestart', resizeNativeStart);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function detachResizeStartListener() {
- detachEvent(selectedElm, 'resizestart', resizeNativeStart);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function detachResizeStartListener() {
+ detachEvent(selectedElm, 'resizestart', resizeNativeStart);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function unbindResizeHandleEvents() {
- for (var name in resizeHandles) {
- var handle = resizeHandles[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function unbindResizeHandleEvents() {
+ for (var name in resizeHandles) {
+ var handle = resizeHandles[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (handle.elm) {
- dom.unbind(handle.elm);
- delete handle.elm;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (handle.elm) {
+ dom.unbind(handle.elm);
+ delete handle.elm;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function disableGeckoResize() {
- try {
- // Disable object resizing on Gecko
- editor.getDoc().execCommand('enableObjectResizing', false, false);
- } catch (ex) {
- // Ignore
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function disableGeckoResize() {
+ try {
+ // Disable object resizing on Gecko
+ editor.getDoc().execCommand('enableObjectResizing', false, false);
+ } catch (ex) {
+ // Ignore
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function controlSelect(elm) {
- var ctrlRng;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function controlSelect(elm) {
+ var ctrlRng;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isIE) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isIE) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ctrlRng = editableDoc.body.createControlRange();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ctrlRng = editableDoc.body.createControlRange();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- try {
- ctrlRng.addElement(elm);
- ctrlRng.select();
- return true;
- } catch (ex) {
- // Ignore since the element can't be control selected for example a P tag
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ try {
+ ctrlRng.addElement(elm);
+ ctrlRng.select();
+ return true;
+ } catch (ex) {
+ // Ignore since the element can't be control selected for example a P tag
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('init', function() {
- if (isIE) {
- // Hide the resize rect on resize and reselect the image
- editor.on('ObjectResized', function(e) {
- if (e.target.nodeName != 'TABLE') {
- hideResizeRect();
- controlSelect(e.target);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('init', function () {
+ if (isIE) {
+ // Hide the resize rect on resize and reselect the image
+ editor.on('ObjectResized', function (e) {
+ if (e.target.nodeName != 'TABLE') {
+ hideResizeRect();
+ controlSelect(e.target);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- attachEvent(rootElement, 'controlselect', nativeControlSelect);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ attachEvent(rootElement, 'controlselect', nativeControlSelect);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('mousedown', function(e) {
- lastMouseDownEvent = e;
- });
- } else {
- disableGeckoResize();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('mousedown', function (e) {
+ lastMouseDownEvent = e;
+ });
+ } else {
+ disableGeckoResize();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Sniff sniff, hard to feature detect this stuff
- if (Env.ie >= 11) {
- // Needs to be mousedown for drag/drop to work on IE 11
- // Needs to be click on Edge to properly select images
- editor.on('mousedown click', function(e) {
- var target = e.target, nodeName = target.nodeName;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Sniff sniff, hard to feature detect this stuff
+ if (Env.ie >= 11) {
+ // Needs to be mousedown for drag/drop to work on IE 11
+ // Needs to be click on Edge to properly select images
+ editor.on('mousedown click', function (e) {
+ var target = e.target, nodeName = target.nodeName;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!resizeStarted && /^(TABLE|IMG|HR)$/.test(nodeName) && !isWithinContentEditableFalse(target)) {
- editor.selection.select(target, nodeName == 'TABLE');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!resizeStarted && /^(TABLE|IMG|HR)$/.test(nodeName) && !isWithinContentEditableFalse(target)) {
+ editor.selection.select(target, nodeName == 'TABLE');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Only fire once since nodeChange is expensive
- if (e.type == 'mousedown') {
- editor.nodeChanged();
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Only fire once since nodeChange is expensive
+ if (e.type == 'mousedown') {
+ editor.nodeChanged();
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.dom.bind(rootElement, 'mscontrolselect', function(e) {
- function delayedSelect(node) {
- Delay.setEditorTimeout(editor, function() {
- editor.selection.select(node);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.dom.bind(rootElement, 'mscontrolselect', function (e) {
+ function delayedSelect(node) {
+ Delay.setEditorTimeout(editor, function () {
+ editor.selection.select(node);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isWithinContentEditableFalse(e.target)) {
- e.preventDefault();
- delayedSelect(e.target);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isWithinContentEditableFalse(e.target)) {
+ e.preventDefault();
+ delayedSelect(e.target);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (/^(TABLE|IMG|HR)$/.test(e.target.nodeName)) {
- e.preventDefault();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (/^(TABLE|IMG|HR)$/.test(e.target.nodeName)) {
+ e.preventDefault();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // This moves the selection from being a control selection to a text like selection like in WebKit #6753
- // TODO: Fix this the day IE works like other browsers without this nasty native ugly control selections.
- if (e.target.tagName == 'IMG') {
- delayedSelect(e.target);
- }
- }
- });
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // This moves the selection from being a control selection to a text like selection like in WebKit #6753
+ // TODO: Fix this the day IE works like other browsers without this nasty native ugly control selections.
+ if (e.target.tagName == 'IMG') {
+ delayedSelect(e.target);
+ }
+ }
+ });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var throttledUpdateResizeRect = Delay.throttle(function(e) {
- if (!editor.composing) {
- updateResizeRect(e);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var throttledUpdateResizeRect = Delay.throttle(function (e) {
+ if (!editor.composing) {
+ updateResizeRect(e);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('nodechange ResizeEditor ResizeWindow drop', throttledUpdateResizeRect);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('nodechange ResizeEditor ResizeWindow drop', throttledUpdateResizeRect);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Update resize rect while typing in a table
- editor.on('keyup compositionend', function(e) {
- // Don't update the resize rect while composing since it blows away the IME see: #2710
- if (selectedElm && selectedElm.nodeName == "TABLE") {
- throttledUpdateResizeRect(e);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Update resize rect while typing in a table
+ editor.on('keyup compositionend', function (e) {
+ // Don't update the resize rect while composing since it blows away the IME see: #2710
+ if (selectedElm && selectedElm.nodeName == "TABLE") {
+ throttledUpdateResizeRect(e);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('hide blur', hideResizeRect);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('hide blur', hideResizeRect);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Hide rect on focusout since it would float on top of windows otherwise
- //editor.on('focusout', hideResizeRect);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Hide rect on focusout since it would float on top of windows otherwise
+ //editor.on('focusout', hideResizeRect);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('remove', unbindResizeHandleEvents);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('remove', unbindResizeHandleEvents);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function destroy() {
- selectedElm = selectedElmGhost = null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function destroy() {
+ selectedElm = selectedElmGhost = null;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isIE) {
- detachResizeStartListener();
- detachEvent(rootElement, 'controlselect', nativeControlSelect);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isIE) {
+ detachResizeStartListener();
+ detachEvent(rootElement, 'controlselect', nativeControlSelect);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- isResizable: isResizable,
- showResizeRect: showResizeRect,
- hideResizeRect: hideResizeRect,
- updateResizeRect: updateResizeRect,
- controlSelect: controlSelect,
- destroy: destroy
- };
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ isResizable: isResizable,
+ showResizeRect: showResizeRect,
+ hideResizeRect: hideResizeRect,
+ updateResizeRect: updateResizeRect,
+ controlSelect: controlSelect,
+ destroy: destroy
+ };
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/util/Fun.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Fun.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -16134,89 +16555,91 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.util.Fun
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/util/Fun", [], function() {
- var slice = [].slice;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.Fun',
+ [
+ ],
+ function () {
+ var slice = [].slice;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function constant(value) {
- return function() {
- return value;
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function constant(value) {
+ return function () {
+ return value;
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function negate(predicate) {
- return function(x) {
- return !predicate(x);
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function negate(predicate) {
+ return function (x) {
+ return !predicate(x);
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function compose(f, g) {
- return function(x) {
- return f(g(x));
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function compose(f, g) {
+ return function (x) {
+ return f(g(x));
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function or() {
- var args = slice.call(arguments);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function or() {
+ var args = slice.call(arguments);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function(x) {
- for (var i = 0; i < args.length; i++) {
- if (args[i](x)) {
- return true;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function (x) {
+ for (var i = 0; i < args.length; i++) {
+ if (args[i](x)) {
+ return true;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function and() {
- var args = slice.call(arguments);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function and() {
+ var args = slice.call(arguments);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function(x) {
- for (var i = 0; i < args.length; i++) {
- if (!args[i](x)) {
- return false;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function (x) {
+ for (var i = 0; i < args.length; i++) {
+ if (!args[i](x)) {
+ return false;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function curry(fn) {
- var args = slice.call(arguments);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function curry(fn) {
+ var args = slice.call(arguments);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (args.length - 1 >= fn.length) {
- return fn.apply(this, args.slice(1));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (args.length - 1 >= fn.length) {
+ return fn.apply(this, args.slice(1));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function() {
- var tempArgs = args.concat([].slice.call(arguments));
- return curry.apply(this, tempArgs);
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function () {
+ var tempArgs = args.concat([].slice.call(arguments));
+ return curry.apply(this, tempArgs);
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function noop() {
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function noop() {
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- constant: constant,
- negate: negate,
- and: and,
- or: or,
- curry: curry,
- compose: compose,
- noop: noop
- };
-});
-
-// Included from: js/tinymce/classes/caret/CaretCandidate.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ constant: constant,
+ negate: negate,
+ and: and,
+ or: or,
+ curry: curry,
+ compose: compose,
+ noop: noop
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * CaretCandidate.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -16229,83 +16652,84 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.caret.CaretCandidate
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/caret/CaretCandidate", [
- "tinymce/dom/NodeType",
- "tinymce/util/Arr",
- "tinymce/caret/CaretContainer"
-], function(NodeType, Arr, CaretContainer) {
- var isContentEditableTrue = NodeType.isContentEditableTrue,
- isContentEditableFalse = NodeType.isContentEditableFalse,
- isBr = NodeType.isBr,
- isText = NodeType.isText,
- isInvalidTextElement = NodeType.matchNodeNames('script style textarea'),
- isAtomicInline = NodeType.matchNodeNames('img input textarea hr iframe video audio object'),
- isTable = NodeType.matchNodeNames('table'),
- isCaretContainer = CaretContainer.isCaretContainer;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.caret.CaretCandidate',
+ [
+ "tinymce.core.dom.NodeType",
+ "tinymce.core.util.Arr",
+ "tinymce.core.caret.CaretContainer"
+ ],
+ function (NodeType, Arr, CaretContainer) {
+ var isContentEditableTrue = NodeType.isContentEditableTrue,
+ isContentEditableFalse = NodeType.isContentEditableFalse,
+ isBr = NodeType.isBr,
+ isText = NodeType.isText,
+ isInvalidTextElement = NodeType.matchNodeNames('script style textarea'),
+ isAtomicInline = NodeType.matchNodeNames('img input textarea hr iframe video audio object'),
+ isTable = NodeType.matchNodeNames('table'),
+ isCaretContainer = CaretContainer.isCaretContainer;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isCaretCandidate(node) {
- if (isCaretContainer(node)) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isCaretCandidate(node) {
+ if (isCaretContainer(node)) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isText(node)) {
- if (isInvalidTextElement(node.parentNode)) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isText(node)) {
+ if (isInvalidTextElement(node.parentNode)) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return isAtomicInline(node) || isBr(node) || isTable(node) || isContentEditableFalse(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return isAtomicInline(node) || isBr(node) || isTable(node) || isContentEditableFalse(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isInEditable(node, rootNode) {
- for (node = node.parentNode; node && node != rootNode; node = node.parentNode) {
- if (isContentEditableFalse(node)) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isInEditable(node, rootNode) {
+ for (node = node.parentNode; node && node != rootNode; node = node.parentNode) {
+ if (isContentEditableFalse(node)) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isContentEditableTrue(node)) {
- return true;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isContentEditableTrue(node)) {
+ return true;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isAtomicContentEditableFalse(node) {
- if (!isContentEditableFalse(node)) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isAtomicContentEditableFalse(node) {
+ if (!isContentEditableFalse(node)) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Arr.reduce(node.getElementsByTagName('*'), function(result, elm) {
- return result || isContentEditableTrue(elm);
- }, false) !== true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Arr.reduce(node.getElementsByTagName('*'), function (result, elm) {
+ return result || isContentEditableTrue(elm);
+ }, false) !== true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isAtomic(node) {
- return isAtomicInline(node) || isAtomicContentEditableFalse(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isAtomic(node) {
+ return isAtomicInline(node) || isAtomicContentEditableFalse(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isEditableCaretCandidate(node, rootNode) {
- return isCaretCandidate(node) && isInEditable(node, rootNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isEditableCaretCandidate(node, rootNode) {
+ return isCaretCandidate(node) && isInEditable(node, rootNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- isCaretCandidate: isCaretCandidate,
- isInEditable: isInEditable,
- isAtomic: isAtomic,
- isEditableCaretCandidate: isEditableCaretCandidate
- };
-});
-
-// Included from: js/tinymce/classes/geom/ClientRect.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ isCaretCandidate: isCaretCandidate,
+ isInEditable: isInEditable,
+ isAtomic: isAtomic,
+ isEditableCaretCandidate: isEditableCaretCandidate
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * ClientRect.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -16317,134 +16741,137 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.geom.ClientRect
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/geom/ClientRect", [], function() {
- var round = Math.round;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.geom.ClientRect',
+ [
+ ],
+ function () {
+ var round = Math.round;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function clone(rect) {
- if (!rect) {
- return {left: 0, top: 0, bottom: 0, right: 0, width: 0, height: 0};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function clone(rect) {
+ if (!rect) {
+ return { left: 0, top: 0, bottom: 0, right: 0, width: 0, height: 0 };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- left: round(rect.left),
- top: round(rect.top),
- bottom: round(rect.bottom),
- right: round(rect.right),
- width: round(rect.width),
- height: round(rect.height)
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ left: round(rect.left),
+ top: round(rect.top),
+ bottom: round(rect.bottom),
+ right: round(rect.right),
+ width: round(rect.width),
+ height: round(rect.height)
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function collapse(clientRect, toStart) {
- clientRect = clone(clientRect);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function collapse(clientRect, toStart) {
+ clientRect = clone(clientRect);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (toStart) {
- clientRect.right = clientRect.left;
- } else {
- clientRect.left = clientRect.left + clientRect.width;
- clientRect.right = clientRect.left;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (toStart) {
+ clientRect.right = clientRect.left;
+ } else {
+ clientRect.left = clientRect.left + clientRect.width;
+ clientRect.right = clientRect.left;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- clientRect.width = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ clientRect.width = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return clientRect;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return clientRect;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isEqual(rect1, rect2) {
- return (
- rect1.left === rect2.left &&
- rect1.top === rect2.top &&
- rect1.bottom === rect2.bottom &&
- rect1.right === rect2.right
- );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isEqual(rect1, rect2) {
+ return (
+ rect1.left === rect2.left &&
+ rect1.top === rect2.top &&
+ rect1.bottom === rect2.bottom &&
+ rect1.right === rect2.right
+ );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isValidOverflow(overflowY, clientRect1, clientRect2) {
- return overflowY >= 0 && overflowY <= Math.min(clientRect1.height, clientRect2.height) / 2;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isValidOverflow(overflowY, clientRect1, clientRect2) {
+ return overflowY >= 0 && overflowY <= Math.min(clientRect1.height, clientRect2.height) / 2;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isAbove(clientRect1, clientRect2) {
- if (clientRect1.bottom < clientRect2.top) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isAbove(clientRect1, clientRect2) {
+ if ((clientRect1.bottom - clientRect1.height / 2) < clientRect2.top) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (clientRect1.top > clientRect2.bottom) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (clientRect1.top > clientRect2.bottom) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return isValidOverflow(clientRect2.top - clientRect1.bottom, clientRect1, clientRect2);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return isValidOverflow(clientRect2.top - clientRect1.bottom, clientRect1, clientRect2);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isBelow(clientRect1, clientRect2) {
- if (clientRect1.top > clientRect2.bottom) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isBelow(clientRect1, clientRect2) {
+ if (clientRect1.top > clientRect2.bottom) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (clientRect1.bottom < clientRect2.top) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (clientRect1.bottom < clientRect2.top) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return isValidOverflow(clientRect2.bottom - clientRect1.top, clientRect1, clientRect2);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return isValidOverflow(clientRect2.bottom - clientRect1.top, clientRect1, clientRect2);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isLeft(clientRect1, clientRect2) {
- return clientRect1.left < clientRect2.left;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isLeft(clientRect1, clientRect2) {
+ return clientRect1.left < clientRect2.left;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isRight(clientRect1, clientRect2) {
- return clientRect1.right > clientRect2.right;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isRight(clientRect1, clientRect2) {
+ return clientRect1.right > clientRect2.right;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function compare(clientRect1, clientRect2) {
- if (isAbove(clientRect1, clientRect2)) {
- return -1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function compare(clientRect1, clientRect2) {
+ if (isAbove(clientRect1, clientRect2)) {
+ return -1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isBelow(clientRect1, clientRect2)) {
- return 1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isBelow(clientRect1, clientRect2)) {
+ return 1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isLeft(clientRect1, clientRect2)) {
- return -1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isLeft(clientRect1, clientRect2)) {
+ return -1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isRight(clientRect1, clientRect2)) {
- return 1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isRight(clientRect1, clientRect2)) {
+ return 1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function containsXY(clientRect, clientX, clientY) {
- return (
- clientX >= clientRect.left &&
- clientX <= clientRect.right &&
- clientY >= clientRect.top &&
- clientY <= clientRect.bottom
- );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function containsXY(clientRect, clientX, clientY) {
+ return (
+ clientX >= clientRect.left &&
+ clientX <= clientRect.right &&
+ clientY >= clientRect.top &&
+ clientY <= clientRect.bottom
+ );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- clone: clone,
- collapse: collapse,
- isEqual: isEqual,
- isAbove: isAbove,
- isBelow: isBelow,
- isLeft: isLeft,
- isRight: isRight,
- compare: compare,
- containsXY: containsXY
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ clone: clone,
+ collapse: collapse,
+ isEqual: isEqual,
+ isAbove: isAbove,
+ isBelow: isBelow,
+ isLeft: isLeft,
+ isRight: isRight,
+ compare: compare,
+ containsXY: containsXY
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/text/ExtendingChar.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * ExtendingChar.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -16458,49 +16885,51 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @example
</span><span class="cx" style="display: block; padding: 0 10px"> * var isExtending = ExtendingChar.isExtendingChar('a');
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/text/ExtendingChar", [], function() {
- // Generated from: http://www.unicode.org/Public/UNIDATA/DerivedCoreProperties.txt
- // Only includes the characters in that fit into UCS-2 16 bit
- var extendingChars = new RegExp(
- "[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A" +
- "\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0" +
- "\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08E3-\u0902\u093A\u093C" +
- "\u0941-\u0948\u094D\u0951-\u0957\u0962-\u0963\u0981\u09BC\u09BE\u09C1-\u09C4\u09CD\u09D7\u09E2-\u09E3" +
- "\u0A01-\u0A02\u0A3C\u0A41-\u0A42\u0A47-\u0A48\u0A4B-\u0A4D\u0A51\u0A70-\u0A71\u0A75\u0A81-\u0A82\u0ABC" +
- "\u0AC1-\u0AC5\u0AC7-\u0AC8\u0ACD\u0AE2-\u0AE3\u0B01\u0B3C\u0B3E\u0B3F\u0B41-\u0B44\u0B4D\u0B56\u0B57" +
- "\u0B62-\u0B63\u0B82\u0BBE\u0BC0\u0BCD\u0BD7\u0C00\u0C3E-\u0C40\u0C46-\u0C48\u0C4A-\u0C4D\u0C55-\u0C56" +
- "\u0C62-\u0C63\u0C81\u0CBC\u0CBF\u0CC2\u0CC6\u0CCC-\u0CCD\u0CD5-\u0CD6\u0CE2-\u0CE3\u0D01\u0D3E\u0D41-\u0D44" +
- "\u0D4D\u0D57\u0D62-\u0D63\u0DCA\u0DCF\u0DD2-\u0DD4\u0DD6\u0DDF\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9" +
- "\u0EBB-\u0EBC\u0EC8-\u0ECD\u0F18-\u0F19\u0F35\u0F37\u0F39\u0F71-\u0F7E\u0F80-\u0F84\u0F86-\u0F87\u0F8D-\u0F97" +
- "\u0F99-\u0FBC\u0FC6\u102D-\u1030\u1032-\u1037\u1039-\u103A\u103D-\u103E\u1058-\u1059\u105E-\u1060\u1071-\u1074" +
- "\u1082\u1085-\u1086\u108D\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17B4-\u17B5" +
- "\u17B7-\u17BD\u17C6\u17C9-\u17D3\u17DD\u180B-\u180D\u18A9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193B\u1A17-\u1A18" +
- "\u1A1B\u1A56\u1A58-\u1A5E\u1A60\u1A62\u1A65-\u1A6C\u1A73-\u1A7C\u1A7F\u1AB0-\u1ABD\u1ABE\u1B00-\u1B03\u1B34" +
- "\u1B36-\u1B3A\u1B3C\u1B42\u1B6B-\u1B73\u1B80-\u1B81\u1BA2-\u1BA5\u1BA8-\u1BA9\u1BAB-\u1BAD\u1BE6\u1BE8-\u1BE9" +
- "\u1BED\u1BEF-\u1BF1\u1C2C-\u1C33\u1C36-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE0\u1CE2-\u1CE8\u1CED\u1CF4\u1CF8-\u1CF9" +
- "\u1DC0-\u1DF5\u1DFC-\u1DFF\u200C-\u200D\u20D0-\u20DC\u20DD-\u20E0\u20E1\u20E2-\u20E4\u20E5-\u20F0\u2CEF-\u2CF1" +
- "\u2D7F\u2DE0-\u2DFF\u302A-\u302D\u302E-\u302F\u3099-\u309A\uA66F\uA670-\uA672\uA674-\uA67D\uA69E-\uA69F\uA6F0-\uA6F1" +
- "\uA802\uA806\uA80B\uA825-\uA826\uA8C4\uA8E0-\uA8F1\uA926-\uA92D\uA947-\uA951\uA980-\uA982\uA9B3\uA9B6-\uA9B9\uA9BC" +
- "\uA9E5\uAA29-\uAA2E\uAA31-\uAA32\uAA35-\uAA36\uAA43\uAA4C\uAA7C\uAAB0\uAAB2-\uAAB4\uAAB7-\uAAB8\uAABE-\uAABF\uAAC1" +
- "\uAAEC-\uAAED\uAAF6\uABE5\uABE8\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F\uFF9E-\uFF9F]"
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.text.ExtendingChar',
+ [
+ ],
+ function () {
+ // Generated from: http://www.unicode.org/Public/UNIDATA/DerivedCoreProperties.txt
+ // Only includes the characters in that fit into UCS-2 16 bit
+ var extendingChars = new RegExp(
+ "[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A" +
+ "\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0" +
+ "\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08E3-\u0902\u093A\u093C" +
+ "\u0941-\u0948\u094D\u0951-\u0957\u0962-\u0963\u0981\u09BC\u09BE\u09C1-\u09C4\u09CD\u09D7\u09E2-\u09E3" +
+ "\u0A01-\u0A02\u0A3C\u0A41-\u0A42\u0A47-\u0A48\u0A4B-\u0A4D\u0A51\u0A70-\u0A71\u0A75\u0A81-\u0A82\u0ABC" +
+ "\u0AC1-\u0AC5\u0AC7-\u0AC8\u0ACD\u0AE2-\u0AE3\u0B01\u0B3C\u0B3E\u0B3F\u0B41-\u0B44\u0B4D\u0B56\u0B57" +
+ "\u0B62-\u0B63\u0B82\u0BBE\u0BC0\u0BCD\u0BD7\u0C00\u0C3E-\u0C40\u0C46-\u0C48\u0C4A-\u0C4D\u0C55-\u0C56" +
+ "\u0C62-\u0C63\u0C81\u0CBC\u0CBF\u0CC2\u0CC6\u0CCC-\u0CCD\u0CD5-\u0CD6\u0CE2-\u0CE3\u0D01\u0D3E\u0D41-\u0D44" +
+ "\u0D4D\u0D57\u0D62-\u0D63\u0DCA\u0DCF\u0DD2-\u0DD4\u0DD6\u0DDF\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9" +
+ "\u0EBB-\u0EBC\u0EC8-\u0ECD\u0F18-\u0F19\u0F35\u0F37\u0F39\u0F71-\u0F7E\u0F80-\u0F84\u0F86-\u0F87\u0F8D-\u0F97" +
+ "\u0F99-\u0FBC\u0FC6\u102D-\u1030\u1032-\u1037\u1039-\u103A\u103D-\u103E\u1058-\u1059\u105E-\u1060\u1071-\u1074" +
+ "\u1082\u1085-\u1086\u108D\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17B4-\u17B5" +
+ "\u17B7-\u17BD\u17C6\u17C9-\u17D3\u17DD\u180B-\u180D\u18A9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193B\u1A17-\u1A18" +
+ "\u1A1B\u1A56\u1A58-\u1A5E\u1A60\u1A62\u1A65-\u1A6C\u1A73-\u1A7C\u1A7F\u1AB0-\u1ABD\u1ABE\u1B00-\u1B03\u1B34" +
+ "\u1B36-\u1B3A\u1B3C\u1B42\u1B6B-\u1B73\u1B80-\u1B81\u1BA2-\u1BA5\u1BA8-\u1BA9\u1BAB-\u1BAD\u1BE6\u1BE8-\u1BE9" +
+ "\u1BED\u1BEF-\u1BF1\u1C2C-\u1C33\u1C36-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE0\u1CE2-\u1CE8\u1CED\u1CF4\u1CF8-\u1CF9" +
+ "\u1DC0-\u1DF5\u1DFC-\u1DFF\u200C-\u200D\u20D0-\u20DC\u20DD-\u20E0\u20E1\u20E2-\u20E4\u20E5-\u20F0\u2CEF-\u2CF1" +
+ "\u2D7F\u2DE0-\u2DFF\u302A-\u302D\u302E-\u302F\u3099-\u309A\uA66F\uA670-\uA672\uA674-\uA67D\uA69E-\uA69F\uA6F0-\uA6F1" +
+ "\uA802\uA806\uA80B\uA825-\uA826\uA8C4\uA8E0-\uA8F1\uA926-\uA92D\uA947-\uA951\uA980-\uA982\uA9B3\uA9B6-\uA9B9\uA9BC" +
+ "\uA9E5\uAA29-\uAA2E\uAA31-\uAA32\uAA35-\uAA36\uAA43\uAA4C\uAA7C\uAAB0\uAAB2-\uAAB4\uAAB7-\uAAB8\uAABE-\uAABF\uAAC1" +
+ "\uAAEC-\uAAED\uAAF6\uABE5\uABE8\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F\uFF9E-\uFF9F]"
+ );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isExtendingChar(ch) {
- return typeof ch == "string" && ch.charCodeAt(0) >= 768 && extendingChars.test(ch);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isExtendingChar(ch) {
+ return typeof ch == "string" && ch.charCodeAt(0) >= 768 && extendingChars.test(ch);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- isExtendingChar: isExtendingChar
- };
-});
-
-// Included from: js/tinymce/classes/caret/CaretPosition.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ isExtendingChar: isExtendingChar
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * CaretPosition.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -16517,380 +16946,393 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * var caretPos1 = new CaretPosition(container, offset);
</span><span class="cx" style="display: block; padding: 0 10px"> * var caretPos2 = CaretPosition.fromRangeStart(someRange);
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/caret/CaretPosition", [
- "tinymce/util/Fun",
- "tinymce/dom/NodeType",
- "tinymce/dom/DOMUtils",
- "tinymce/dom/RangeUtils",
- "tinymce/caret/CaretCandidate",
- "tinymce/geom/ClientRect",
- "tinymce/text/ExtendingChar"
-], function(Fun, NodeType, DOMUtils, RangeUtils, CaretCandidate, ClientRect, ExtendingChar) {
- var isElement = NodeType.isElement,
- isCaretCandidate = CaretCandidate.isCaretCandidate,
- isBlock = NodeType.matchStyleValues('display', 'block table'),
- isFloated = NodeType.matchStyleValues('float', 'left right'),
- isValidElementCaretCandidate = Fun.and(isElement, isCaretCandidate, Fun.negate(isFloated)),
- isNotPre = Fun.negate(NodeType.matchStyleValues('white-space', 'pre pre-line pre-wrap')),
- isText = NodeType.isText,
- isBr = NodeType.isBr,
- nodeIndex = DOMUtils.nodeIndex,
- resolveIndex = RangeUtils.getNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.caret.CaretPosition',
+ [
+ "tinymce.core.util.Fun",
+ "tinymce.core.dom.NodeType",
+ "tinymce.core.dom.DOMUtils",
+ "tinymce.core.dom.RangeUtils",
+ "tinymce.core.caret.CaretCandidate",
+ "tinymce.core.geom.ClientRect",
+ "tinymce.core.text.ExtendingChar"
+ ],
+ function (Fun, NodeType, DOMUtils, RangeUtils, CaretCandidate, ClientRect, ExtendingChar) {
+ var isElement = NodeType.isElement,
+ isCaretCandidate = CaretCandidate.isCaretCandidate,
+ isBlock = NodeType.matchStyleValues('display', 'block table'),
+ isFloated = NodeType.matchStyleValues('float', 'left right'),
+ isValidElementCaretCandidate = Fun.and(isElement, isCaretCandidate, Fun.negate(isFloated)),
+ isNotPre = Fun.negate(NodeType.matchStyleValues('white-space', 'pre pre-line pre-wrap')),
+ isText = NodeType.isText,
+ isBr = NodeType.isBr,
+ nodeIndex = DOMUtils.nodeIndex,
+ resolveIndex = RangeUtils.getNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function createRange(doc) {
- return "createRange" in doc ? doc.createRange() : DOMUtils.DOM.createRng();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function createRange(doc) {
+ return "createRange" in doc ? doc.createRange() : DOMUtils.DOM.createRng();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isWhiteSpace(chr) {
- return chr && /[\r\n\t ]/.test(chr);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isWhiteSpace(chr) {
+ return chr && /[\r\n\t ]/.test(chr);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isHiddenWhiteSpaceRange(range) {
- var container = range.startContainer,
- offset = range.startOffset,
- text;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isHiddenWhiteSpaceRange(range) {
+ var container = range.startContainer,
+ offset = range.startOffset,
+ text;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isWhiteSpace(range.toString()) && isNotPre(container.parentNode)) {
- text = container.data;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isWhiteSpace(range.toString()) && isNotPre(container.parentNode)) {
+ text = container.data;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isWhiteSpace(text[offset - 1]) || isWhiteSpace(text[offset + 1])) {
- return true;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isWhiteSpace(text[offset - 1]) || isWhiteSpace(text[offset + 1])) {
+ return true;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getCaretPositionClientRects(caretPosition) {
- var clientRects = [], beforeNode, node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getCaretPositionClientRects(caretPosition) {
+ var clientRects = [], beforeNode, node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Hack for older WebKit versions that doesn't
- // support getBoundingClientRect on BR elements
- function getBrClientRect(brNode) {
- var doc = brNode.ownerDocument,
- rng = createRange(doc),
- nbsp = doc.createTextNode('\u00a0'),
- parentNode = brNode.parentNode,
- clientRect;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Hack for older WebKit versions that doesn't
+ // support getBoundingClientRect on BR elements
+ function getBrClientRect(brNode) {
+ var doc = brNode.ownerDocument,
+ rng = createRange(doc),
+ nbsp = doc.createTextNode('\u00a0'),
+ parentNode = brNode.parentNode,
+ clientRect;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parentNode.insertBefore(nbsp, brNode);
- rng.setStart(nbsp, 0);
- rng.setEnd(nbsp, 1);
- clientRect = ClientRect.clone(rng.getBoundingClientRect());
- parentNode.removeChild(nbsp);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parentNode.insertBefore(nbsp, brNode);
+ rng.setStart(nbsp, 0);
+ rng.setEnd(nbsp, 1);
+ clientRect = ClientRect.clone(rng.getBoundingClientRect());
+ parentNode.removeChild(nbsp);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return clientRect;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return clientRect;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getBoundingClientRect(item) {
- var clientRect, clientRects;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getBoundingClientRect(item) {
+ var clientRect, clientRects;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- clientRects = item.getClientRects();
- if (clientRects.length > 0) {
- clientRect = ClientRect.clone(clientRects[0]);
- } else {
- clientRect = ClientRect.clone(item.getBoundingClientRect());
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ clientRects = item.getClientRects();
+ if (clientRects.length > 0) {
+ clientRect = ClientRect.clone(clientRects[0]);
+ } else {
+ clientRect = ClientRect.clone(item.getBoundingClientRect());
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isBr(item) && clientRect.left === 0) {
- return getBrClientRect(item);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isBr(item) && clientRect.left === 0) {
+ return getBrClientRect(item);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return clientRect;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return clientRect;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function collapseAndInflateWidth(clientRect, toStart) {
- clientRect = ClientRect.collapse(clientRect, toStart);
- clientRect.width = 1;
- clientRect.right = clientRect.left + 1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function collapseAndInflateWidth(clientRect, toStart) {
+ clientRect = ClientRect.collapse(clientRect, toStart);
+ clientRect.width = 1;
+ clientRect.right = clientRect.left + 1;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return clientRect;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return clientRect;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function addUniqueAndValidRect(clientRect) {
- if (clientRect.height === 0) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function addUniqueAndValidRect(clientRect) {
+ if (clientRect.height === 0) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (clientRects.length > 0) {
- if (ClientRect.isEqual(clientRect, clientRects[clientRects.length - 1])) {
- return;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (clientRects.length > 0) {
+ if (ClientRect.isEqual(clientRect, clientRects[clientRects.length - 1])) {
+ return;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- clientRects.push(clientRect);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ clientRects.push(clientRect);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function addCharacterOffset(container, offset) {
- var range = createRange(container.ownerDocument);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function addCharacterOffset(container, offset) {
+ var range = createRange(container.ownerDocument);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (offset < container.data.length) {
- if (ExtendingChar.isExtendingChar(container.data[offset])) {
- return clientRects;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (offset < container.data.length) {
+ if (ExtendingChar.isExtendingChar(container.data[offset])) {
+ return clientRects;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // WebKit returns two client rects for a position after an extending
- // character a\uxxx|b so expand on "b" and collapse to start of "b" box
- if (ExtendingChar.isExtendingChar(container.data[offset - 1])) {
- range.setStart(container, offset);
- range.setEnd(container, offset + 1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // WebKit returns two client rects for a position after an extending
+ // character a\uxxx|b so expand on "b" and collapse to start of "b" box
+ if (ExtendingChar.isExtendingChar(container.data[offset - 1])) {
+ range.setStart(container, offset);
+ range.setEnd(container, offset + 1);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isHiddenWhiteSpaceRange(range)) {
- addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(range), false));
- return clientRects;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isHiddenWhiteSpaceRange(range)) {
+ addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(range), false));
+ return clientRects;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (offset > 0) {
- range.setStart(container, offset - 1);
- range.setEnd(container, offset);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (offset > 0) {
+ range.setStart(container, offset - 1);
+ range.setEnd(container, offset);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isHiddenWhiteSpaceRange(range)) {
- addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(range), false));
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isHiddenWhiteSpaceRange(range)) {
+ addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(range), false));
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (offset < container.data.length) {
- range.setStart(container, offset);
- range.setEnd(container, offset + 1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (offset < container.data.length) {
+ range.setStart(container, offset);
+ range.setEnd(container, offset + 1);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isHiddenWhiteSpaceRange(range)) {
- addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(range), true));
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isHiddenWhiteSpaceRange(range)) {
+ addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(range), true));
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isText(caretPosition.container())) {
- addCharacterOffset(caretPosition.container(), caretPosition.offset());
- return clientRects;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isText(caretPosition.container())) {
+ addCharacterOffset(caretPosition.container(), caretPosition.offset());
+ return clientRects;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isElement(caretPosition.container())) {
- if (caretPosition.isAtEnd()) {
- node = resolveIndex(caretPosition.container(), caretPosition.offset());
- if (isText(node)) {
- addCharacterOffset(node, node.data.length);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isElement(caretPosition.container())) {
+ if (caretPosition.isAtEnd()) {
+ node = resolveIndex(caretPosition.container(), caretPosition.offset());
+ if (isText(node)) {
+ addCharacterOffset(node, node.data.length);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isValidElementCaretCandidate(node) && !isBr(node)) {
- addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(node), false));
- }
- } else {
- node = resolveIndex(caretPosition.container(), caretPosition.offset());
- if (isText(node)) {
- addCharacterOffset(node, 0);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isValidElementCaretCandidate(node) && !isBr(node)) {
+ addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(node), false));
+ }
+ } else {
+ node = resolveIndex(caretPosition.container(), caretPosition.offset());
+ if (isText(node)) {
+ addCharacterOffset(node, 0);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isValidElementCaretCandidate(node) && caretPosition.isAtEnd()) {
- addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(node), false));
- return clientRects;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isValidElementCaretCandidate(node) && caretPosition.isAtEnd()) {
+ addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(node), false));
+ return clientRects;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- beforeNode = resolveIndex(caretPosition.container(), caretPosition.offset() - 1);
- if (isValidElementCaretCandidate(beforeNode) && !isBr(beforeNode)) {
- if (isBlock(beforeNode) || isBlock(node) || !isValidElementCaretCandidate(node)) {
- addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(beforeNode), false));
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ beforeNode = resolveIndex(caretPosition.container(), caretPosition.offset() - 1);
+ if (isValidElementCaretCandidate(beforeNode) && !isBr(beforeNode)) {
+ if (isBlock(beforeNode) || isBlock(node) || !isValidElementCaretCandidate(node)) {
+ addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(beforeNode), false));
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isValidElementCaretCandidate(node)) {
- addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(node), true));
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isValidElementCaretCandidate(node)) {
+ addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(node), true));
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return clientRects;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return clientRects;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Represents a location within the document by a container and an offset.
- *
- * @constructor
- * @param {Node} container Container node.
- * @param {Number} offset Offset within that container node.
- * @param {Array} clientRects Optional client rects array for the position.
- */
- function CaretPosition(container, offset, clientRects) {
- function isAtStart() {
- if (isText(container)) {
- return offset === 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Represents a location within the document by a container and an offset.
+ *
+ * @constructor
+ * @param {Node} container Container node.
+ * @param {Number} offset Offset within that container node.
+ * @param {Array} clientRects Optional client rects array for the position.
+ */
+ function CaretPosition(container, offset, clientRects) {
+ function isAtStart() {
+ if (isText(container)) {
+ return offset === 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return offset === 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return offset === 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isAtEnd() {
- if (isText(container)) {
- return offset >= container.data.length;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isAtEnd() {
+ if (isText(container)) {
+ return offset >= container.data.length;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return offset >= container.childNodes.length;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return offset >= container.childNodes.length;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function toRange() {
- var range;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function toRange() {
+ var range;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- range = createRange(container.ownerDocument);
- range.setStart(container, offset);
- range.setEnd(container, offset);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ range = createRange(container.ownerDocument);
+ range.setStart(container, offset);
+ range.setEnd(container, offset);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return range;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return range;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getClientRects() {
- if (!clientRects) {
- clientRects = getCaretPositionClientRects(new CaretPosition(container, offset));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getClientRects() {
+ if (!clientRects) {
+ clientRects = getCaretPositionClientRects(new CaretPosition(container, offset));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return clientRects;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return clientRects;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isVisible() {
- return getClientRects().length > 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isVisible() {
+ return getClientRects().length > 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isEqual(caretPosition) {
- return caretPosition && container === caretPosition.container() && offset === caretPosition.offset();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isEqual(caretPosition) {
+ return caretPosition && container === caretPosition.container() && offset === caretPosition.offset();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getNode(before) {
- return resolveIndex(container, before ? offset - 1 : offset);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getNode(before) {
+ return resolveIndex(container, before ? offset - 1 : offset);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- /**
- * Returns the container node.
- *
- * @method container
- * @return {Node} Container node.
- */
- container: Fun.constant(container),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ /**
+ * Returns the container node.
+ *
+ * @method container
+ * @return {Node} Container node.
+ */
+ container: Fun.constant(container),
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the offset within the container node.
- *
- * @method offset
- * @return {Number} Offset within the container node.
- */
- offset: Fun.constant(offset),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the offset within the container node.
+ *
+ * @method offset
+ * @return {Number} Offset within the container node.
+ */
+ offset: Fun.constant(offset),
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a range out of a the caret position.
- *
- * @method toRange
- * @return {DOMRange} range for the caret position.
- */
- toRange: toRange,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a range out of a the caret position.
+ *
+ * @method toRange
+ * @return {DOMRange} range for the caret position.
+ */
+ toRange: toRange,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the client rects for the caret position. Might be multiple rects between
- * block elements.
- *
- * @method getClientRects
- * @return {Array} Array of client rects.
- */
- getClientRects: getClientRects,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the client rects for the caret position. Might be multiple rects between
+ * block elements.
+ *
+ * @method getClientRects
+ * @return {Array} Array of client rects.
+ */
+ getClientRects: getClientRects,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true if the caret location is visible/displayed on screen.
- *
- * @method isVisible
- * @return {Boolean} true/false if the position is visible or not.
- */
- isVisible: isVisible,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true if the caret location is visible/displayed on screen.
+ *
+ * @method isVisible
+ * @return {Boolean} true/false if the position is visible or not.
+ */
+ isVisible: isVisible,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true if the caret location is at the beginning of text node or container.
- *
- * @method isVisible
- * @return {Boolean} true/false if the position is at the beginning.
- */
- isAtStart: isAtStart,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true if the caret location is at the beginning of text node or container.
+ *
+ * @method isVisible
+ * @return {Boolean} true/false if the position is at the beginning.
+ */
+ isAtStart: isAtStart,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true if the caret location is at the end of text node or container.
- *
- * @method isVisible
- * @return {Boolean} true/false if the position is at the end.
- */
- isAtEnd: isAtEnd,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true if the caret location is at the end of text node or container.
+ *
+ * @method isVisible
+ * @return {Boolean} true/false if the position is at the end.
+ */
+ isAtEnd: isAtEnd,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Compares the caret position to another caret position. This will only compare the
- * container and offset not it's visual position.
- *
- * @method isEqual
- * @param {tinymce.caret.CaretPosition} caretPosition Caret position to compare with.
- * @return {Boolean} true if the caret positions are equal.
- */
- isEqual: isEqual,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Compares the caret position to another caret position. This will only compare the
+ * container and offset not it's visual position.
+ *
+ * @method isEqual
+ * @param {tinymce.caret.CaretPosition} caretPosition Caret position to compare with.
+ * @return {Boolean} true if the caret positions are equal.
+ */
+ isEqual: isEqual,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the closest resolved node from a node index. That means if you have an offset after the
- * last node in a container it will return that last node.
- *
- * @method getNode
- * @return {Node} Node that is closest to the index.
- */
- getNode: getNode
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the closest resolved node from a node index. That means if you have an offset after the
+ * last node in a container it will return that last node.
+ *
+ * @method getNode
+ * @return {Node} Node that is closest to the index.
+ */
+ getNode: getNode
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates a caret position from the start of a range.
- *
- * @method fromRangeStart
- * @param {DOMRange} range DOM Range to create caret position from.
- * @return {tinymce.caret.CaretPosition} Caret position from the start of DOM range.
- */
- CaretPosition.fromRangeStart = function(range) {
- return new CaretPosition(range.startContainer, range.startOffset);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates a caret position from the start of a range.
+ *
+ * @method fromRangeStart
+ * @param {DOMRange} range DOM Range to create caret position from.
+ * @return {tinymce.caret.CaretPosition} Caret position from the start of DOM range.
+ */
+ CaretPosition.fromRangeStart = function (range) {
+ return new CaretPosition(range.startContainer, range.startOffset);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates a caret position from the end of a range.
- *
- * @method fromRangeEnd
- * @param {DOMRange} range DOM Range to create caret position from.
- * @return {tinymce.caret.CaretPosition} Caret position from the end of DOM range.
- */
- CaretPosition.fromRangeEnd = function(range) {
- return new CaretPosition(range.endContainer, range.endOffset);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates a caret position from the end of a range.
+ *
+ * @method fromRangeEnd
+ * @param {DOMRange} range DOM Range to create caret position from.
+ * @return {tinymce.caret.CaretPosition} Caret position from the end of DOM range.
+ */
+ CaretPosition.fromRangeEnd = function (range) {
+ return new CaretPosition(range.endContainer, range.endOffset);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates a caret position from a node and places the offset after it.
- *
- * @method after
- * @param {Node} node Node to get caret position from.
- * @return {tinymce.caret.CaretPosition} Caret position from the node.
- */
- CaretPosition.after = function(node) {
- return new CaretPosition(node.parentNode, nodeIndex(node) + 1);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates a caret position from a node and places the offset after it.
+ *
+ * @method after
+ * @param {Node} node Node to get caret position from.
+ * @return {tinymce.caret.CaretPosition} Caret position from the node.
+ */
+ CaretPosition.after = function (node) {
+ return new CaretPosition(node.parentNode, nodeIndex(node) + 1);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates a caret position from a node and places the offset before it.
- *
- * @method before
- * @param {Node} node Node to get caret position from.
- * @return {tinymce.caret.CaretPosition} Caret position from the node.
- */
- CaretPosition.before = function(node) {
- return new CaretPosition(node.parentNode, nodeIndex(node));
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates a caret position from a node and places the offset before it.
+ *
+ * @method before
+ * @param {Node} node Node to get caret position from.
+ * @return {tinymce.caret.CaretPosition} Caret position from the node.
+ */
+ CaretPosition.before = function (node) {
+ return new CaretPosition(node.parentNode, nodeIndex(node));
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return CaretPosition;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ CaretPosition.isAtStart = function (pos) {
+ return pos ? pos.isAtStart() : false;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/caret/CaretBookmark.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ CaretPosition.isAtEnd = function (pos) {
+ return pos ? pos.isAtEnd() : false;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ CaretPosition.isTextPosition = function (pos) {
+ return pos ? NodeType.isText(pos.container()) : false;
+ };
+
+ return CaretPosition;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * CaretBookmark.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -16914,249 +17356,250 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * var bookmark = CaretBookmark.create(rootElm, CaretPosition.before(rootElm.firstChild));
</span><span class="cx" style="display: block; padding: 0 10px"> * var caretPosition = CaretBookmark.resolve(bookmark);
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce/caret/CaretBookmark', [
- 'tinymce/dom/NodeType',
- 'tinymce/dom/DOMUtils',
- 'tinymce/util/Fun',
- 'tinymce/util/Arr',
- 'tinymce/caret/CaretPosition'
-], function(NodeType, DomUtils, Fun, Arr, CaretPosition) {
- var isText = NodeType.isText,
- isBogus = NodeType.isBogus,
- nodeIndex = DomUtils.nodeIndex;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.caret.CaretBookmark',
+ [
+ 'tinymce.core.dom.NodeType',
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.core.util.Fun',
+ 'tinymce.core.util.Arr',
+ 'tinymce.core.caret.CaretPosition'
+ ],
+ function (NodeType, DomUtils, Fun, Arr, CaretPosition) {
+ var isText = NodeType.isText,
+ isBogus = NodeType.isBogus,
+ nodeIndex = DomUtils.nodeIndex;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function normalizedParent(node) {
- var parentNode = node.parentNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function normalizedParent(node) {
+ var parentNode = node.parentNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isBogus(parentNode)) {
- return normalizedParent(parentNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isBogus(parentNode)) {
+ return normalizedParent(parentNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getChildNodes(node) {
- if (!node) {
- return [];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getChildNodes(node) {
+ if (!node) {
+ return [];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Arr.reduce(node.childNodes, function(result, node) {
- if (isBogus(node) && node.nodeName != 'BR') {
- result = result.concat(getChildNodes(node));
- } else {
- result.push(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Arr.reduce(node.childNodes, function (result, node) {
+ if (isBogus(node) && node.nodeName != 'BR') {
+ result = result.concat(getChildNodes(node));
+ } else {
+ result.push(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return result;
- }, []);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return result;
+ }, []);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function normalizedTextOffset(textNode, offset) {
- while ((textNode = textNode.previousSibling)) {
- if (!isText(textNode)) {
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function normalizedTextOffset(textNode, offset) {
+ while ((textNode = textNode.previousSibling)) {
+ if (!isText(textNode)) {
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- offset += textNode.data.length;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ offset += textNode.data.length;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return offset;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return offset;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function equal(targetValue) {
- return function(value) {
- return targetValue === value;
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function equal(targetValue) {
+ return function (value) {
+ return targetValue === value;
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function normalizedNodeIndex(node) {
- var nodes, index, numTextFragments;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function normalizedNodeIndex(node) {
+ var nodes, index, numTextFragments;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- nodes = getChildNodes(normalizedParent(node));
- index = Arr.findIndex(nodes, equal(node), node);
- nodes = nodes.slice(0, index + 1);
- numTextFragments = Arr.reduce(nodes, function(result, node, i) {
- if (isText(node) && isText(nodes[i - 1])) {
- result++;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ nodes = getChildNodes(normalizedParent(node));
+ index = Arr.findIndex(nodes, equal(node), node);
+ nodes = nodes.slice(0, index + 1);
+ numTextFragments = Arr.reduce(nodes, function (result, node, i) {
+ if (isText(node) && isText(nodes[i - 1])) {
+ result++;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return result;
- }, 0);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return result;
+ }, 0);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- nodes = Arr.filter(nodes, NodeType.matchNodeNames(node.nodeName));
- index = Arr.findIndex(nodes, equal(node), node);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ nodes = Arr.filter(nodes, NodeType.matchNodeNames(node.nodeName));
+ index = Arr.findIndex(nodes, equal(node), node);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return index - numTextFragments;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return index - numTextFragments;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function createPathItem(node) {
- var name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function createPathItem(node) {
+ var name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isText(node)) {
- name = 'text()';
- } else {
- name = node.nodeName.toLowerCase();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isText(node)) {
+ name = 'text()';
+ } else {
+ name = node.nodeName.toLowerCase();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return name + '[' + normalizedNodeIndex(node) + ']';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return name + '[' + normalizedNodeIndex(node) + ']';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function parentsUntil(rootNode, node, predicate) {
- var parents = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function parentsUntil(rootNode, node, predicate) {
+ var parents = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (node = node.parentNode; node != rootNode; node = node.parentNode) {
- if (predicate && predicate(node)) {
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (node = node.parentNode; node != rootNode; node = node.parentNode) {
+ if (predicate && predicate(node)) {
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parents.push(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parents.push(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return parents;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return parents;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function create(rootNode, caretPosition) {
- var container, offset, path = [],
- outputOffset, childNodes, parents;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function create(rootNode, caretPosition) {
+ var container, offset, path = [],
+ outputOffset, childNodes, parents;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = caretPosition.container();
- offset = caretPosition.offset();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = caretPosition.container();
+ offset = caretPosition.offset();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isText(container)) {
- outputOffset = normalizedTextOffset(container, offset);
- } else {
- childNodes = container.childNodes;
- if (offset >= childNodes.length) {
- outputOffset = 'after';
- offset = childNodes.length - 1;
- } else {
- outputOffset = 'before';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isText(container)) {
+ outputOffset = normalizedTextOffset(container, offset);
+ } else {
+ childNodes = container.childNodes;
+ if (offset >= childNodes.length) {
+ outputOffset = 'after';
+ offset = childNodes.length - 1;
+ } else {
+ outputOffset = 'before';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = childNodes[offset];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = childNodes[offset];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- path.push(createPathItem(container));
- parents = parentsUntil(rootNode, container);
- parents = Arr.filter(parents, Fun.negate(NodeType.isBogus));
- path = path.concat(Arr.map(parents, function(node) {
- return createPathItem(node);
- }));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ path.push(createPathItem(container));
+ parents = parentsUntil(rootNode, container);
+ parents = Arr.filter(parents, Fun.negate(NodeType.isBogus));
+ path = path.concat(Arr.map(parents, function (node) {
+ return createPathItem(node);
+ }));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return path.reverse().join('/') + ',' + outputOffset;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return path.reverse().join('/') + ',' + outputOffset;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function resolvePathItem(node, name, index) {
- var nodes = getChildNodes(node);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function resolvePathItem(node, name, index) {
+ var nodes = getChildNodes(node);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- nodes = Arr.filter(nodes, function(node, index) {
- return !isText(node) || !isText(nodes[index - 1]);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ nodes = Arr.filter(nodes, function (node, index) {
+ return !isText(node) || !isText(nodes[index - 1]);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- nodes = Arr.filter(nodes, NodeType.matchNodeNames(name));
- return nodes[index];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ nodes = Arr.filter(nodes, NodeType.matchNodeNames(name));
+ return nodes[index];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function findTextPosition(container, offset) {
- var node = container, targetOffset = 0, dataLen;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function findTextPosition(container, offset) {
+ var node = container, targetOffset = 0, dataLen;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (isText(node)) {
- dataLen = node.data.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (isText(node)) {
+ dataLen = node.data.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (offset >= targetOffset && offset <= targetOffset + dataLen) {
- container = node;
- offset = offset - targetOffset;
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (offset >= targetOffset && offset <= targetOffset + dataLen) {
+ container = node;
+ offset = offset - targetOffset;
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isText(node.nextSibling)) {
- container = node;
- offset = dataLen;
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isText(node.nextSibling)) {
+ container = node;
+ offset = dataLen;
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- targetOffset += dataLen;
- node = node.nextSibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ targetOffset += dataLen;
+ node = node.nextSibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (offset > container.data.length) {
- offset = container.data.length;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (offset > container.data.length) {
+ offset = container.data.length;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return new CaretPosition(container, offset);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return new CaretPosition(container, offset);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function resolve(rootNode, path) {
- var parts, container, offset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function resolve(rootNode, path) {
+ var parts, container, offset;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!path) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!path) {
+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parts = path.split(',');
- path = parts[0].split('/');
- offset = parts.length > 1 ? parts[1] : 'before';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parts = path.split(',');
+ path = parts[0].split('/');
+ offset = parts.length > 1 ? parts[1] : 'before';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = Arr.reduce(path, function(result, value) {
- value = /([\w\-\(\)]+)\[([0-9]+)\]/.exec(value);
- if (!value) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = Arr.reduce(path, function (result, value) {
+ value = /([\w\-\(\)]+)\[([0-9]+)\]/.exec(value);
+ if (!value) {
+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value[1] === 'text()') {
- value[1] = '#text';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value[1] === 'text()') {
+ value[1] = '#text';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return resolvePathItem(result, value[1], parseInt(value[2], 10));
- }, rootNode);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return resolvePathItem(result, value[1], parseInt(value[2], 10));
+ }, rootNode);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!container) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!container) {
+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isText(container)) {
- if (offset === 'after') {
- offset = nodeIndex(container) + 1;
- } else {
- offset = nodeIndex(container);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isText(container)) {
+ if (offset === 'after') {
+ offset = nodeIndex(container) + 1;
+ } else {
+ offset = nodeIndex(container);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return new CaretPosition(container.parentNode, offset);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return new CaretPosition(container.parentNode, offset);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return findTextPosition(container, parseInt(offset, 10));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return findTextPosition(container, parseInt(offset, 10));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- /**
- * Create a xpath bookmark location for the specified caret position.
- *
- * @method create
- * @param {Node} rootNode Root node to create bookmark within.
- * @param {tinymce.caret.CaretPosition} caretPosition Caret position within the root node.
- * @return {String} String xpath like location of caret position.
- */
- create: create,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ /**
+ * Create a xpath bookmark location for the specified caret position.
+ *
+ * @method create
+ * @param {Node} rootNode Root node to create bookmark within.
+ * @param {tinymce.caret.CaretPosition} caretPosition Caret position within the root node.
+ * @return {String} String xpath like location of caret position.
+ */
+ create: create,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Resolves a xpath like bookmark location to the a caret position.
- *
- * @method resolve
- * @param {Node} rootNode Root node to resolve xpath bookmark within.
- * @param {String} bookmark Bookmark string to resolve.
- * @return {tinymce.caret.CaretPosition} Caret position resolved from xpath like bookmark.
- */
- resolve: resolve
- };
-});
-
-// Included from: js/tinymce/classes/dom/BookmarkManager.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Resolves a xpath like bookmark location to the a caret position.
+ *
+ * @method resolve
+ * @param {Node} rootNode Root node to resolve xpath bookmark within.
+ * @param {String} bookmark Bookmark string to resolve.
+ * @return {tinymce.caret.CaretPosition} Caret position resolved from xpath like bookmark.
+ */
+ resolve: resolve
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * BookmarkManager.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -17167,1503 +17610,2064 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.dom.BookmarkManager
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/dom/BookmarkManager", [
- "tinymce/Env",
- "tinymce/util/Tools",
- "tinymce/caret/CaretContainer",
- "tinymce/caret/CaretBookmark",
- "tinymce/caret/CaretPosition",
- "tinymce/dom/NodeType",
- "tinymce/dom/RangeUtils"
-], function(Env, Tools, CaretContainer, CaretBookmark, CaretPosition, NodeType, RangeUtils) {
- var isContentEditableFalse = NodeType.isContentEditableFalse;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.BookmarkManager',
+ [
+ 'tinymce.core.caret.CaretBookmark',
+ 'tinymce.core.caret.CaretContainer',
+ 'tinymce.core.caret.CaretPosition',
+ 'tinymce.core.dom.NodeType',
+ 'tinymce.core.dom.RangeUtils',
+ 'tinymce.core.Env',
+ 'tinymce.core.text.Zwsp',
+ 'tinymce.core.util.Tools'
+ ],
+ function (CaretBookmark, CaretContainer, CaretPosition, NodeType, RangeUtils, Env, Zwsp, Tools) {
+ var isContentEditableFalse = NodeType.isContentEditableFalse;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a new BookmarkManager instance for a specific selection instance.
- *
- * @constructor
- * @method BookmarkManager
- * @param {tinymce.dom.Selection} selection Selection instance to handle bookmarks for.
- */
- function BookmarkManager(selection) {
- var dom = selection.dom;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getNormalizedTextOffset = function (container, offset) {
+ var node, trimmedOffset;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a bookmark location for the current selection. This bookmark object
- * can then be used to restore the selection after some content modification to the document.
- *
- * @method getBookmark
- * @param {Number} type Optional state if the bookmark should be simple or not. Default is complex.
- * @param {Boolean} normalized Optional state that enables you to get a position that it would be after normalization.
- * @return {Object} Bookmark object, use moveToBookmark with this object to restore the selection.
- * @example
- * // Stores a bookmark of the current selection
- * var bm = tinymce.activeEditor.selection.getBookmark();
- *
- * tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
- *
- * // Restore the selection bookmark
- * tinymce.activeEditor.selection.moveToBookmark(bm);
- */
- this.getBookmark = function(type, normalized) {
- var rng, rng2, id, collapsed, name, element, chr = '', styles;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ trimmedOffset = Zwsp.trim(container.data.slice(0, offset)).length;
+ for (node = container.previousSibling; node && node.nodeType === 3; node = node.previousSibling) {
+ trimmedOffset += Zwsp.trim(node.data).length;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function findIndex(name, element) {
- var count = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return trimmedOffset;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(dom.select(name), function(node) {
- if (node.getAttribute('data-mce-bogus') === 'all') {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a new BookmarkManager instance for a specific selection instance.
+ *
+ * @constructor
+ * @method BookmarkManager
+ * @param {tinymce.dom.Selection} selection Selection instance to handle bookmarks for.
+ */
+ function BookmarkManager(selection) {
+ var dom = selection.dom;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node == element) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a bookmark location for the current selection. This bookmark object
+ * can then be used to restore the selection after some content modification to the document.
+ *
+ * @method getBookmark
+ * @param {Number} type Optional state if the bookmark should be simple or not. Default is complex.
+ * @param {Boolean} normalized Optional state that enables you to get a position that it would be after normalization.
+ * @return {Object} Bookmark object, use moveToBookmark with this object to restore the selection.
+ * @example
+ * // Stores a bookmark of the current selection
+ * var bm = tinymce.activeEditor.selection.getBookmark();
+ *
+ * tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
+ *
+ * // Restore the selection bookmark
+ * tinymce.activeEditor.selection.moveToBookmark(bm);
+ */
+ this.getBookmark = function (type, normalized) {
+ var rng, rng2, id, collapsed, name, element, chr = '', styles;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- count++;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function findIndex(name, element) {
+ var count = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return count;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(dom.select(name), function (node) {
+ if (node.getAttribute('data-mce-bogus') === 'all') {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function normalizeTableCellSelection(rng) {
- function moveEndPoint(start) {
- var container, offset, childNodes, prefix = start ? 'start' : 'end';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node == element) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = rng[prefix + 'Container'];
- offset = rng[prefix + 'Offset'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ count++;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (container.nodeType == 1 && container.nodeName == "TR") {
- childNodes = container.childNodes;
- container = childNodes[Math.min(start ? offset : offset - 1, childNodes.length - 1)];
- if (container) {
- offset = start ? 0 : container.childNodes.length;
- rng['set' + (start ? 'Start' : 'End')](container, offset);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return count;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- moveEndPoint(true);
- moveEndPoint();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function normalizeTableCellSelection(rng) {
+ function moveEndPoint(start) {
+ var container, offset, childNodes, prefix = start ? 'start' : 'end';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return rng;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = rng[prefix + 'Container'];
+ offset = rng[prefix + 'Offset'];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getLocation(rng) {
- var root = dom.getRoot(), bookmark = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (container.nodeType == 1 && container.nodeName == "TR") {
+ childNodes = container.childNodes;
+ container = childNodes[Math.min(start ? offset : offset - 1, childNodes.length - 1)];
+ if (container) {
+ offset = start ? 0 : container.childNodes.length;
+ rng['set' + (start ? 'Start' : 'End')](container, offset);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getPoint(rng, start) {
- var container = rng[start ? 'startContainer' : 'endContainer'],
- offset = rng[start ? 'startOffset' : 'endOffset'], point = [], node, childNodes, after = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ moveEndPoint(true);
+ moveEndPoint();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (container.nodeType == 3) {
- if (normalized) {
- for (node = container.previousSibling; node && node.nodeType == 3; node = node.previousSibling) {
- offset += node.nodeValue.length;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return rng;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- point.push(offset);
- } else {
- childNodes = container.childNodes;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getLocation(rng) {
+ var root = dom.getRoot(), bookmark = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (offset >= childNodes.length && childNodes.length) {
- after = 1;
- offset = Math.max(0, childNodes.length - 1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getPoint(rng, start) {
+ var container = rng[start ? 'startContainer' : 'endContainer'],
+ offset = rng[start ? 'startOffset' : 'endOffset'], point = [], childNodes, after = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- point.push(dom.nodeIndex(childNodes[offset], normalized) + after);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (container.nodeType === 3) {
+ point.push(normalized ? getNormalizedTextOffset(container, offset) : offset);
+ } else {
+ childNodes = container.childNodes;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (; container && container != root; container = container.parentNode) {
- point.push(dom.nodeIndex(container, normalized));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (offset >= childNodes.length && childNodes.length) {
+ after = 1;
+ offset = Math.max(0, childNodes.length - 1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return point;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ point.push(dom.nodeIndex(childNodes[offset], normalized) + after);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bookmark.start = getPoint(rng, true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (; container && container != root; container = container.parentNode) {
+ point.push(dom.nodeIndex(container, normalized));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!selection.isCollapsed()) {
- bookmark.end = getPoint(rng);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return point;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return bookmark;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bookmark.start = getPoint(rng, true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function findAdjacentContentEditableFalseElm(rng) {
- function findSibling(node, offset) {
- var sibling;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!selection.isCollapsed()) {
+ bookmark.end = getPoint(rng);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (NodeType.isElement(node)) {
- node = RangeUtils.getNode(node, offset);
- if (isContentEditableFalse(node)) {
- return node;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return bookmark;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (CaretContainer.isCaretContainer(node)) {
- if (NodeType.isText(node) && CaretContainer.isCaretContainerBlock(node)) {
- node = node.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function findAdjacentContentEditableFalseElm(rng) {
+ function findSibling(node, offset) {
+ var sibling;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- sibling = node.previousSibling;
- if (isContentEditableFalse(sibling)) {
- return sibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (NodeType.isElement(node)) {
+ node = RangeUtils.getNode(node, offset);
+ if (isContentEditableFalse(node)) {
+ return node;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- sibling = node.nextSibling;
- if (isContentEditableFalse(sibling)) {
- return sibling;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (CaretContainer.isCaretContainer(node)) {
+ if (NodeType.isText(node) && CaretContainer.isCaretContainerBlock(node)) {
+ node = node.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return findSibling(rng.startContainer, rng.startOffset) || findSibling(rng.endContainer, rng.endOffset);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ sibling = node.previousSibling;
+ if (isContentEditableFalse(sibling)) {
+ return sibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (type == 2) {
- element = selection.getNode();
- name = element ? element.nodeName : null;
- rng = selection.getRng();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ sibling = node.nextSibling;
+ if (isContentEditableFalse(sibling)) {
+ return sibling;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isContentEditableFalse(element) || name == 'IMG') {
- return {name: name, index: findIndex(name, element)};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return findSibling(rng.startContainer, rng.startOffset) || findSibling(rng.endContainer, rng.endOffset);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (selection.tridentSel) {
- return selection.tridentSel.getBookmark(type);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (type == 2) {
+ element = selection.getNode();
+ name = element ? element.nodeName : null;
+ rng = selection.getRng();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- element = findAdjacentContentEditableFalseElm(rng);
- if (element) {
- name = element.tagName;
- return {name: name, index: findIndex(name, element)};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isContentEditableFalse(element) || name == 'IMG') {
+ return { name: name, index: findIndex(name, element) };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return getLocation(rng);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (selection.tridentSel) {
+ return selection.tridentSel.getBookmark(type);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (type == 3) {
- rng = selection.getRng();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ element = findAdjacentContentEditableFalseElm(rng);
+ if (element) {
+ name = element.tagName;
+ return { name: name, index: findIndex(name, element) };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- start: CaretBookmark.create(dom.getRoot(), CaretPosition.fromRangeStart(rng)),
- end: CaretBookmark.create(dom.getRoot(), CaretPosition.fromRangeEnd(rng))
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return getLocation(rng);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle simple range
- if (type) {
- return {rng: selection.getRng()};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (type == 3) {
+ rng = selection.getRng();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng = selection.getRng();
- id = dom.uniqueId();
- collapsed = selection.isCollapsed();
- styles = 'overflow:hidden;line-height:0px';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ start: CaretBookmark.create(dom.getRoot(), CaretPosition.fromRangeStart(rng)),
+ end: CaretBookmark.create(dom.getRoot(), CaretPosition.fromRangeEnd(rng))
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Explorer method
- if (rng.duplicate || rng.item) {
- // Text selection
- if (!rng.item) {
- rng2 = rng.duplicate();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handle simple range
+ if (type) {
+ return { rng: selection.getRng() };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- try {
- // Insert start marker
- rng.collapse();
- rng.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_start" style="' + styles + '">' + chr + '</span>');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng = selection.getRng();
+ id = dom.uniqueId();
+ collapsed = selection.isCollapsed();
+ styles = 'overflow:hidden;line-height:0px';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Insert end marker
- if (!collapsed) {
- rng2.collapse(false);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Explorer method
+ if (rng.duplicate || rng.item) {
+ // Text selection
+ if (!rng.item) {
+ rng2 = rng.duplicate();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Detect the empty space after block elements in IE and move the
- // end back one character <p></p>] becomes <p>]</p>
- rng.moveToElementText(rng2.parentElement());
- if (rng.compareEndPoints('StartToEnd', rng2) === 0) {
- rng2.move('character', -1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ try {
+ // Insert start marker
+ rng.collapse();
+ rng.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_start" style="' + styles + '">' + chr + '</span>');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng2.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_end" style="' + styles + '">' + chr + '</span>');
- }
- } catch (ex) {
- // IE might throw unspecified error so lets ignore it
- return null;
- }
- } else {
- // Control selection
- element = rng.item(0);
- name = element.nodeName;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Insert end marker
+ if (!collapsed) {
+ rng2.collapse(false);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {name: name, index: findIndex(name, element)};
- }
- } else {
- element = selection.getNode();
- name = element.nodeName;
- if (name == 'IMG') {
- return {name: name, index: findIndex(name, element)};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Detect the empty space after block elements in IE and move the
+ // end back one character <p></p>] becomes <p>]</p>
+ rng.moveToElementText(rng2.parentElement());
+ if (rng.compareEndPoints('StartToEnd', rng2) === 0) {
+ rng2.move('character', -1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // W3C method
- rng2 = normalizeTableCellSelection(rng.cloneRange());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng2.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_end" style="' + styles + '">' + chr + '</span>');
+ }
+ } catch (ex) {
+ // IE might throw unspecified error so lets ignore it
+ return null;
+ }
+ } else {
+ // Control selection
+ element = rng.item(0);
+ name = element.nodeName;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Insert end marker
- if (!collapsed) {
- rng2.collapse(false);
- rng2.insertNode(dom.create('span', {'data-mce-type': "bookmark", id: id + '_end', style: styles}, chr));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return { name: name, index: findIndex(name, element) };
+ }
+ } else {
+ element = selection.getNode();
+ name = element.nodeName;
+ if (name == 'IMG') {
+ return { name: name, index: findIndex(name, element) };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng = normalizeTableCellSelection(rng);
- rng.collapse(true);
- rng.insertNode(dom.create('span', {'data-mce-type': "bookmark", id: id + '_start', style: styles}, chr));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // W3C method
+ rng2 = normalizeTableCellSelection(rng.cloneRange());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- selection.moveToBookmark({id: id, keep: 1});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Insert end marker
+ if (!collapsed) {
+ rng2.collapse(false);
+ rng2.insertNode(dom.create('span', { 'data-mce-type': "bookmark", id: id + '_end', style: styles }, chr));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {id: id};
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng = normalizeTableCellSelection(rng);
+ rng.collapse(true);
+ rng.insertNode(dom.create('span', { 'data-mce-type': "bookmark", id: id + '_start', style: styles }, chr));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Restores the selection to the specified bookmark.
- *
- * @method moveToBookmark
- * @param {Object} bookmark Bookmark to restore selection from.
- * @return {Boolean} true/false if it was successful or not.
- * @example
- * // Stores a bookmark of the current selection
- * var bm = tinymce.activeEditor.selection.getBookmark();
- *
- * tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
- *
- * // Restore the selection bookmark
- * tinymce.activeEditor.selection.moveToBookmark(bm);
- */
- this.moveToBookmark = function(bookmark) {
- var rng, root, startContainer, endContainer, startOffset, endOffset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ selection.moveToBookmark({ id: id, keep: 1 });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setEndPoint(start) {
- var point = bookmark[start ? 'start' : 'end'], i, node, offset, children;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return { id: id };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (point) {
- offset = point[0];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Restores the selection to the specified bookmark.
+ *
+ * @method moveToBookmark
+ * @param {Object} bookmark Bookmark to restore selection from.
+ * @return {Boolean} true/false if it was successful or not.
+ * @example
+ * // Stores a bookmark of the current selection
+ * var bm = tinymce.activeEditor.selection.getBookmark();
+ *
+ * tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
+ *
+ * // Restore the selection bookmark
+ * tinymce.activeEditor.selection.moveToBookmark(bm);
+ */
+ this.moveToBookmark = function (bookmark) {
+ var rng, root, startContainer, endContainer, startOffset, endOffset;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Find container node
- for (node = root, i = point.length - 1; i >= 1; i--) {
- children = node.childNodes;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setEndPoint(start) {
+ var point = bookmark[start ? 'start' : 'end'], i, node, offset, children;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (point[i] > children.length - 1) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (point) {
+ offset = point[0];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = children[point[i]];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find container node
+ for (node = root, i = point.length - 1; i >= 1; i--) {
+ children = node.childNodes;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move text offset to best suitable location
- if (node.nodeType === 3) {
- offset = Math.min(point[0], node.nodeValue.length);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (point[i] > children.length - 1) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move element offset to best suitable location
- if (node.nodeType === 1) {
- offset = Math.min(point[0], node.childNodes.length);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = children[point[i]];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set offset within container node
- if (start) {
- rng.setStart(node, offset);
- } else {
- rng.setEnd(node, offset);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move text offset to best suitable location
+ if (node.nodeType === 3) {
+ offset = Math.min(point[0], node.nodeValue.length);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move element offset to best suitable location
+ if (node.nodeType === 1) {
+ offset = Math.min(point[0], node.childNodes.length);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function restoreEndPoint(suffix) {
- var marker = dom.get(bookmark.id + '_' + suffix), node, idx, next, prev, keep = bookmark.keep;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set offset within container node
+ if (start) {
+ rng.setStart(node, offset);
+ } else {
+ rng.setEnd(node, offset);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (marker) {
- node = marker.parentNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (suffix == 'start') {
- if (!keep) {
- idx = dom.nodeIndex(marker);
- } else {
- node = marker.firstChild;
- idx = 1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function restoreEndPoint(suffix) {
+ var marker = dom.get(bookmark.id + '_' + suffix), node, idx, next, prev, keep = bookmark.keep;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- startContainer = endContainer = node;
- startOffset = endOffset = idx;
- } else {
- if (!keep) {
- idx = dom.nodeIndex(marker);
- } else {
- node = marker.firstChild;
- idx = 1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (marker) {
+ node = marker.parentNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- endContainer = node;
- endOffset = idx;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (suffix == 'start') {
+ if (!keep) {
+ idx = dom.nodeIndex(marker);
+ } else {
+ node = marker.firstChild;
+ idx = 1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!keep) {
- prev = marker.previousSibling;
- next = marker.nextSibling;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ startContainer = endContainer = node;
+ startOffset = endOffset = idx;
+ } else {
+ if (!keep) {
+ idx = dom.nodeIndex(marker);
+ } else {
+ node = marker.firstChild;
+ idx = 1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove all marker text nodes
- Tools.each(Tools.grep(marker.childNodes), function(node) {
- if (node.nodeType == 3) {
- node.nodeValue = node.nodeValue.replace(/\uFEFF/g, '');
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ endContainer = node;
+ endOffset = idx;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove marker but keep children if for example contents where inserted into the marker
- // Also remove duplicated instances of the marker for example by a
- // split operation or by WebKit auto split on paste feature
- while ((marker = dom.get(bookmark.id + '_' + suffix))) {
- dom.remove(marker, 1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!keep) {
+ prev = marker.previousSibling;
+ next = marker.nextSibling;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If siblings are text nodes then merge them unless it's Opera since it some how removes the node
- // and we are sniffing since adding a lot of detection code for a browser with 3% of the market
- // isn't worth the effort. Sorry, Opera but it's just a fact
- if (prev && next && prev.nodeType == next.nodeType && prev.nodeType == 3 && !Env.opera) {
- idx = prev.nodeValue.length;
- prev.appendData(next.nodeValue);
- dom.remove(next);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove all marker text nodes
+ Tools.each(Tools.grep(marker.childNodes), function (node) {
+ if (node.nodeType == 3) {
+ node.nodeValue = node.nodeValue.replace(/\uFEFF/g, '');
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (suffix == 'start') {
- startContainer = endContainer = prev;
- startOffset = endOffset = idx;
- } else {
- endContainer = prev;
- endOffset = idx;
- }
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove marker but keep children if for example contents where inserted into the marker
+ // Also remove duplicated instances of the marker for example by a
+ // split operation or by WebKit auto split on paste feature
+ while ((marker = dom.get(bookmark.id + '_' + suffix))) {
+ dom.remove(marker, 1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function addBogus(node) {
- // Adds a bogus BR element for empty block elements
- if (dom.isBlock(node) && !node.innerHTML && !Env.ie) {
- node.innerHTML = '<br data-mce-bogus="1" />';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If siblings are text nodes then merge them unless it's Opera since it some how removes the node
+ // and we are sniffing since adding a lot of detection code for a browser with 3% of the market
+ // isn't worth the effort. Sorry, Opera but it's just a fact
+ if (prev && next && prev.nodeType == next.nodeType && prev.nodeType == 3 && !Env.opera) {
+ idx = prev.nodeValue.length;
+ prev.appendData(next.nodeValue);
+ dom.remove(next);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (suffix == 'start') {
+ startContainer = endContainer = prev;
+ startOffset = endOffset = idx;
+ } else {
+ endContainer = prev;
+ endOffset = idx;
+ }
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function resolveCaretPositionBookmark() {
- var rng, pos;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function addBogus(node) {
+ // Adds a bogus BR element for empty block elements
+ if (dom.isBlock(node) && !node.innerHTML && !Env.ie) {
+ node.innerHTML = '<br data-mce-bogus="1" />';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng = dom.createRng();
- pos = CaretBookmark.resolve(dom.getRoot(), bookmark.start);
- rng.setStart(pos.container(), pos.offset());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- pos = CaretBookmark.resolve(dom.getRoot(), bookmark.end);
- rng.setEnd(pos.container(), pos.offset());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function resolveCaretPositionBookmark() {
+ var rng, pos;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return rng;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng = dom.createRng();
+ pos = CaretBookmark.resolve(dom.getRoot(), bookmark.start);
+ rng.setStart(pos.container(), pos.offset());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (bookmark) {
- if (Tools.isArray(bookmark.start)) {
- rng = dom.createRng();
- root = dom.getRoot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ pos = CaretBookmark.resolve(dom.getRoot(), bookmark.end);
+ rng.setEnd(pos.container(), pos.offset());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (selection.tridentSel) {
- return selection.tridentSel.moveToBookmark(bookmark);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return rng;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (setEndPoint(true) && setEndPoint()) {
- selection.setRng(rng);
- }
- } else if (typeof bookmark.start == 'string') {
- selection.setRng(resolveCaretPositionBookmark(bookmark));
- } else if (bookmark.id) {
- // Restore start/end points
- restoreEndPoint('start');
- restoreEndPoint('end');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (bookmark) {
+ if (Tools.isArray(bookmark.start)) {
+ rng = dom.createRng();
+ root = dom.getRoot();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (startContainer) {
- rng = dom.createRng();
- rng.setStart(addBogus(startContainer), startOffset);
- rng.setEnd(addBogus(endContainer), endOffset);
- selection.setRng(rng);
- }
- } else if (bookmark.name) {
- selection.select(dom.select(bookmark.name)[bookmark.index]);
- } else if (bookmark.rng) {
- selection.setRng(bookmark.rng);
- }
- }
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (selection.tridentSel) {
+ return selection.tridentSel.moveToBookmark(bookmark);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the specified node is a bookmark node or not.
- *
- * @static
- * @method isBookmarkNode
- * @param {DOMNode} node DOM Node to check if it's a bookmark node or not.
- * @return {Boolean} true/false if the node is a bookmark node or not.
- */
- BookmarkManager.isBookmarkNode = function(node) {
- return node && node.tagName === 'SPAN' && node.getAttribute('data-mce-type') === 'bookmark';
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (setEndPoint(true) && setEndPoint()) {
+ selection.setRng(rng);
+ }
+ } else if (typeof bookmark.start == 'string') {
+ selection.setRng(resolveCaretPositionBookmark(bookmark));
+ } else if (bookmark.id) {
+ // Restore start/end points
+ restoreEndPoint('start');
+ restoreEndPoint('end');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return BookmarkManager;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (startContainer) {
+ rng = dom.createRng();
+ rng.setStart(addBogus(startContainer), startOffset);
+ rng.setEnd(addBogus(endContainer), endOffset);
+ selection.setRng(rng);
+ }
+ } else if (bookmark.name) {
+ selection.select(dom.select(bookmark.name)[bookmark.index]);
+ } else if (bookmark.rng) {
+ selection.setRng(bookmark.rng);
+ }
+ }
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/dom/Selection.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the specified node is a bookmark node or not.
+ *
+ * @static
+ * @method isBookmarkNode
+ * @param {DOMNode} node DOM Node to check if it's a bookmark node or not.
+ * @return {Boolean} true/false if the node is a bookmark node or not.
+ */
+ BookmarkManager.isBookmarkNode = function (node) {
+ return node && node.tagName === 'SPAN' && node.getAttribute('data-mce-type') === 'bookmark';
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return BookmarkManager;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Selection.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ScrollIntoView.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.ScrollIntoView',
+ [
+ 'tinymce.core.dom.NodeType'
+ ],
+ function (NodeType) {
+ var getPos = function (elm) {
+ var x = 0, y = 0;
+
+ var offsetParent = elm;
+ while (offsetParent && offsetParent.nodeType) {
+ x += offsetParent.offsetLeft || 0;
+ y += offsetParent.offsetTop || 0;
+ offsetParent = offsetParent.offsetParent;
+ }
+
+ return { x: x, y: y };
+ };
+
+ var fireScrollIntoViewEvent = function (editor, elm, alignToTop) {
+ var scrollEvent = { elm: elm, alignToTop: alignToTop };
+ editor.fire('scrollIntoView', scrollEvent);
+ return scrollEvent.isDefaultPrevented();
+ };
+
+ var scrollIntoView = function (editor, elm, alignToTop) {
+ var y, viewPort, dom = editor.dom, root = dom.getRoot(), viewPortY, viewPortH, offsetY = 0;
+
+ if (fireScrollIntoViewEvent(editor, elm, alignToTop)) {
+ return;
+ }
+
+ if (!NodeType.isElement(elm)) {
+ return;
+ }
+
+ if (alignToTop === false) {
+ offsetY = elm.offsetHeight;
+ }
+
+ if (root.nodeName !== 'BODY') {
+ var scrollContainer = editor.selection.getScrollContainer();
+ if (scrollContainer) {
+ y = getPos(elm).y - getPos(scrollContainer).y + offsetY;
+ viewPortH = scrollContainer.clientHeight;
+ viewPortY = scrollContainer.scrollTop;
+ if (y < viewPortY || y + 25 > viewPortY + viewPortH) {
+ scrollContainer.scrollTop = y < viewPortY ? y : y - viewPortH + 25;
+ }
+
+ return;
+ }
+ }
+
+ viewPort = dom.getViewPort(editor.getWin());
+ y = dom.getPos(elm).y + offsetY;
+ viewPortY = viewPort.y;
+ viewPortH = viewPort.h;
+ if (y < viewPort.y || y + 25 > viewPortY + viewPortH) {
+ editor.getWin().scrollTo(0, y < viewPortY ? y : y - viewPortH + 25);
+ }
+ };
+
+ return {
+ scrollIntoView: scrollIntoView
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * This class handles text and control selection it's an crossbrowser utility class.
- * Consult the TinyMCE Wiki API for more details and examples on how to use this class.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * TridentSelection.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @class tinymce.dom.Selection
- * @example
- * // Getting the currently selected node for the active editor
- * alert(tinymce.activeEditor.selection.getNode().nodeName);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/dom/Selection", [
- "tinymce/dom/TreeWalker",
- "tinymce/dom/TridentSelection",
- "tinymce/dom/ControlSelection",
- "tinymce/dom/RangeUtils",
- "tinymce/dom/BookmarkManager",
- "tinymce/dom/NodeType",
- "tinymce/Env",
- "tinymce/util/Tools",
- "tinymce/caret/CaretPosition"
-], function(TreeWalker, TridentSelection, ControlSelection, RangeUtils, BookmarkManager, NodeType, Env, Tools, CaretPosition) {
- var each = Tools.each, trim = Tools.trim;
- var isIE = Env.ie;
</del><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a new selection instance.
- *
- * @constructor
- * @method Selection
- * @param {tinymce.dom.DOMUtils} dom DOMUtils object reference.
- * @param {Window} win Window to bind the selection object to.
- * @param {tinymce.Editor} editor Editor instance of the selection.
- * @param {tinymce.dom.Serializer} serializer DOM serialization class to use for getContent.
- */
- function Selection(dom, win, serializer, editor) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Selection class for old explorer versions. This one fakes the
+ * native selection object available on modern browsers.
+ *
+ * @private
+ * @class tinymce.dom.TridentSelection
+ */
+define(
+ 'tinymce.core.dom.TridentSelection',
+ [
+ ],
+ function () {
+ function Selection(selection) {
+ var self = this, dom = selection.dom, FALSE = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.dom = dom;
- self.win = win;
- self.serializer = serializer;
- self.editor = editor;
- self.bookmarkManager = new BookmarkManager(self);
- self.controlSelection = new ControlSelection(self, editor);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getPosition(rng, start) {
+ var checkRng, startIndex = 0, endIndex, inside,
+ children, child, offset, index, position = -1, parent;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // No W3C Range support
- if (!self.win.getSelection) {
- self.tridentSel = new TridentSelection(self);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup test range, collapse it and get the parent
+ checkRng = rng.duplicate();
+ checkRng.collapse(start);
+ parent = checkRng.parentElement();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Selection.prototype = {
- /**
- * Move the selection cursor range to the specified node and offset.
- * If there is no node specified it will move it to the first suitable location within the body.
- *
- * @method setCursorLocation
- * @param {Node} node Optional node to put the cursor in.
- * @param {Number} offset Optional offset from the start of the node to put the cursor at.
- */
- setCursorLocation: function(node, offset) {
- var self = this, rng = self.dom.createRng();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if the selection is within the right document
+ if (parent.ownerDocument !== selection.dom.doc) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!node) {
- self._moveEndPoint(rng, self.editor.getBody(), true);
- self.setRng(rng);
- } else {
- rng.setStart(node, offset);
- rng.setEnd(node, offset);
- self.setRng(rng);
- self.collapse(false);
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // IE will report non editable elements as it's parent so look for an editable one
+ while (parent.contentEditable === "false") {
+ parent = parent.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the selected contents using the DOM serializer passed in to this class.
- *
- * @method getContent
- * @param {Object} args Optional settings class with for example output format text or html.
- * @return {String} Selected contents in for example HTML format.
- * @example
- * // Alerts the currently selected contents
- * alert(tinymce.activeEditor.selection.getContent());
- *
- * // Alerts the currently selected contents as plain text
- * alert(tinymce.activeEditor.selection.getContent({format: 'text'}));
- */
- getContent: function(args) {
- var self = this, rng = self.getRng(), tmpElm = self.dom.create("body");
- var se = self.getSel(), whiteSpaceBefore, whiteSpaceAfter, fragment;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If parent doesn't have any children then return that we are inside the element
+ if (!parent.hasChildNodes()) {
+ return { node: parent, inside: 1 };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args = args || {};
- whiteSpaceBefore = whiteSpaceAfter = '';
- args.get = true;
- args.format = args.format || 'html';
- args.selection = true;
- self.editor.fire('BeforeGetContent', args);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup node list and endIndex
+ children = parent.children;
+ endIndex = children.length - 1;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (args.format == 'text') {
- return self.isCollapsed() ? '' : (rng.text || (se.toString ? se.toString() : ''));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Perform a binary search for the position
+ while (startIndex <= endIndex) {
+ index = Math.floor((startIndex + endIndex) / 2);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rng.cloneContents) {
- fragment = rng.cloneContents();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move selection to node and compare the ranges
+ child = children[index];
+ checkRng.moveToElementText(child);
+ position = checkRng.compareEndPoints(start ? 'StartToStart' : 'EndToEnd', rng);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (fragment) {
- tmpElm.appendChild(fragment);
- }
- } else if (rng.item !== undefined || rng.htmlText !== undefined) {
- // IE will produce invalid markup if elements are present that
- // it doesn't understand like custom elements or HTML5 elements.
- // Adding a BR in front of the contents and then remoiving it seems to fix it though.
- tmpElm.innerHTML = '<br>' + (rng.item ? rng.item(0).outerHTML : rng.htmlText);
- tmpElm.removeChild(tmpElm.firstChild);
- } else {
- tmpElm.innerHTML = rng.toString();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Before/after or an exact match
+ if (position > 0) {
+ endIndex = index - 1;
+ } else if (position < 0) {
+ startIndex = index + 1;
+ } else {
+ return { node: child };
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Keep whitespace before and after
- if (/^\s/.test(tmpElm.innerHTML)) {
- whiteSpaceBefore = ' ';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if child position is before or we didn't find a position
+ if (position < 0) {
+ // No element child was found use the parent element and the offset inside that
+ if (!child) {
+ checkRng.moveToElementText(parent);
+ checkRng.collapse(true);
+ child = parent;
+ inside = true;
+ } else {
+ checkRng.collapse(false);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (/\s+$/.test(tmpElm.innerHTML)) {
- whiteSpaceAfter = ' ';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Walk character by character in text node until we hit the selected range endpoint,
+ // hit the end of document or parent isn't the right one
+ // We need to walk char by char since rng.text or rng.htmlText will trim line endings
+ offset = 0;
+ while (checkRng.compareEndPoints(start ? 'StartToStart' : 'StartToEnd', rng) !== 0) {
+ if (checkRng.move('character', 1) === 0 || parent != checkRng.parentElement()) {
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args.getInner = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ offset++;
+ }
+ } else {
+ // Child position is after the selection endpoint
+ checkRng.collapse(true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args.content = self.isCollapsed() ? '' : whiteSpaceBefore + self.serializer.serialize(tmpElm, args) + whiteSpaceAfter;
- self.editor.fire('GetContent', args);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Walk character by character in text node until we hit the selected range endpoint, hit
+ // the end of document or parent isn't the right one
+ offset = 0;
+ while (checkRng.compareEndPoints(start ? 'StartToStart' : 'StartToEnd', rng) !== 0) {
+ if (checkRng.move('character', -1) === 0 || parent != checkRng.parentElement()) {
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return args.content;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ offset++;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets the current selection to the specified content. If any contents is selected it will be replaced
- * with the contents passed in to this function. If there is no selection the contents will be inserted
- * where the caret is placed in the editor/page.
- *
- * @method setContent
- * @param {String} content HTML contents to set could also be other formats depending on settings.
- * @param {Object} args Optional settings object with for example data format.
- * @example
- * // Inserts some HTML contents at the current selection
- * tinymce.activeEditor.selection.setContent('<strong>Some contents</strong>');
- */
- setContent: function(content, args) {
- var self = this, rng = self.getRng(), caretNode, doc = self.win.document, frag, temp;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return { node: child, position: position, offset: offset, inside: inside };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args = args || {format: 'html'};
- args.set = true;
- args.selection = true;
- args.content = content;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Returns a W3C DOM compatible range object by using the IE Range API
+ function getRange() {
+ var ieRange = selection.getRng(), domRange = dom.createRng(), element, collapsed, tmpRange, element2, bookmark;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Dispatch before set content event
- if (!args.no_events) {
- self.editor.fire('BeforeSetContent', args);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If selection is outside the current document just return an empty range
+ element = ieRange.item ? ieRange.item(0) : ieRange.parentElement();
+ if (element.ownerDocument != dom.doc) {
+ return domRange;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- content = args.content;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ collapsed = selection.isCollapsed();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rng.insertNode) {
- // Make caret marker since insertNode places the caret in the beginning of text after insert
- content += '<span id="__caret">_</span>';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handle control selection
+ if (ieRange.item) {
+ domRange.setStart(element.parentNode, dom.nodeIndex(element));
+ domRange.setEnd(domRange.startContainer, domRange.startOffset + 1);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Delete and insert new node
- if (rng.startContainer == doc && rng.endContainer == doc) {
- // WebKit will fail if the body is empty since the range is then invalid and it can't insert contents
- doc.body.innerHTML = content;
- } else {
- rng.deleteContents();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return domRange;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (doc.body.childNodes.length === 0) {
- doc.body.innerHTML = content;
- } else {
- // createContextualFragment doesn't exists in IE 9 DOMRanges
- if (rng.createContextualFragment) {
- rng.insertNode(rng.createContextualFragment(content));
- } else {
- // Fake createContextualFragment call in IE 9
- frag = doc.createDocumentFragment();
- temp = doc.createElement('div');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function findEndPoint(start) {
+ var endPoint = getPosition(ieRange, start), container, offset, textNodeOffset = 0, sibling, undef, nodeValue;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- frag.appendChild(temp);
- temp.outerHTML = content;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = endPoint.node;
+ offset = endPoint.offset;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng.insertNode(frag);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (endPoint.inside && !container.hasChildNodes()) {
+ domRange[start ? 'setStart' : 'setEnd'](container, 0);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move to caret marker
- caretNode = self.dom.get('__caret');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (offset === undef) {
+ domRange[start ? 'setStartBefore' : 'setEndAfter'](container);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Make sure we wrap it compleatly, Opera fails with a simple select call
- rng = doc.createRange();
- rng.setStartBefore(caretNode);
- rng.setEndBefore(caretNode);
- self.setRng(rng);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (endPoint.position < 0) {
+ sibling = endPoint.inside ? container.firstChild : container.nextSibling;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove the caret position
- self.dom.remove('__caret');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!sibling) {
+ domRange[start ? 'setStartAfter' : 'setEndAfter'](container);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- try {
- self.setRng(rng);
- } catch (ex) {
- // Might fail on Opera for some odd reason
- }
- } else {
- if (rng.item) {
- // Delete content and get caret text selection
- doc.execCommand('Delete', false, null);
- rng = self.getRng();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!offset) {
+ if (sibling.nodeType == 3) {
+ domRange[start ? 'setStart' : 'setEnd'](sibling, 0);
+ } else {
+ domRange[start ? 'setStartBefore' : 'setEndBefore'](sibling);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Explorer removes spaces from the beginning of pasted contents
- if (/^\s+/.test(content)) {
- rng.pasteHTML('<span id="__mce_tmp">_</span>' + content);
- self.dom.remove('__mce_tmp');
- } else {
- rng.pasteHTML(content);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Dispatch set content event
- if (!args.no_events) {
- self.editor.fire('SetContent', args);
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find the text node and offset
+ while (sibling) {
+ if (sibling.nodeType == 3) {
+ nodeValue = sibling.nodeValue;
+ textNodeOffset += nodeValue.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the start element of a selection range. If the start is in a text
- * node the parent element will be returned.
- *
- * @method getStart
- * @param {Boolean} real Optional state to get the real parent when the selection is collapsed not the closest element.
- * @return {Element} Start element of selection range.
- */
- getStart: function(real) {
- var self = this, rng = self.getRng(), startElement, parentElement, checkRng, node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // We are at or passed the position we where looking for
+ if (textNodeOffset >= offset) {
+ container = sibling;
+ textNodeOffset -= offset;
+ textNodeOffset = nodeValue.length - textNodeOffset;
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rng.duplicate || rng.item) {
- // Control selection, return first item
- if (rng.item) {
- return rng.item(0);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ sibling = sibling.nextSibling;
+ }
+ } else {
+ // Find the text node and offset
+ sibling = container.previousSibling;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Get start element
- checkRng = rng.duplicate();
- checkRng.collapse(1);
- startElement = checkRng.parentElement();
- if (startElement.ownerDocument !== self.dom.doc) {
- startElement = self.dom.getRoot();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!sibling) {
+ return domRange[start ? 'setStartBefore' : 'setEndBefore'](container);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if range parent is inside the start element, then return the inner parent element
- // This will fix issues when a single element is selected, IE would otherwise return the wrong start element
- parentElement = node = rng.parentElement();
- while ((node = node.parentNode)) {
- if (node == startElement) {
- startElement = parentElement;
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If there isn't any text to loop then use the first position
+ if (!offset) {
+ if (container.nodeType == 3) {
+ domRange[start ? 'setStart' : 'setEnd'](sibling, container.nodeValue.length);
+ } else {
+ domRange[start ? 'setStartAfter' : 'setEndAfter'](sibling);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return startElement;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- startElement = rng.startContainer;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (sibling) {
+ if (sibling.nodeType == 3) {
+ textNodeOffset += sibling.nodeValue.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (startElement.nodeType == 1 && startElement.hasChildNodes()) {
- if (!real || !rng.collapsed) {
- startElement = startElement.childNodes[Math.min(startElement.childNodes.length - 1, rng.startOffset)];
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // We are at or passed the position we where looking for
+ if (textNodeOffset >= offset) {
+ container = sibling;
+ textNodeOffset -= offset;
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (startElement && startElement.nodeType == 3) {
- return startElement.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ sibling = sibling.previousSibling;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return startElement;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ domRange[start ? 'setStart' : 'setEnd'](container, textNodeOffset);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the end element of a selection range. If the end is in a text
- * node the parent element will be returned.
- *
- * @method getEnd
- * @param {Boolean} real Optional state to get the real parent when the selection is collapsed not the closest element.
- * @return {Element} End element of selection range.
- */
- getEnd: function(real) {
- var self = this, rng = self.getRng(), endElement, endOffset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ try {
+ // Find start point
+ findEndPoint(true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rng.duplicate || rng.item) {
- if (rng.item) {
- return rng.item(0);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find end point if needed
+ if (!collapsed) {
+ findEndPoint();
+ }
+ } catch (ex) {
+ // IE has a nasty bug where text nodes might throw "invalid argument" when you
+ // access the nodeValue or other properties of text nodes. This seems to happen when
+ // text nodes are split into two nodes by a delete/backspace call.
+ // So let us detect and try to fix it.
+ if (ex.number == -2147024809) {
+ // Get the current selection
+ bookmark = self.getBookmark(2);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng = rng.duplicate();
- rng.collapse(0);
- endElement = rng.parentElement();
- if (endElement.ownerDocument !== self.dom.doc) {
- endElement = self.dom.getRoot();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get start element
+ tmpRange = ieRange.duplicate();
+ tmpRange.collapse(true);
+ element = tmpRange.parentElement();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (endElement && endElement.nodeName == 'BODY') {
- return endElement.lastChild || endElement;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get end element
+ if (!collapsed) {
+ tmpRange = ieRange.duplicate();
+ tmpRange.collapse(false);
+ element2 = tmpRange.parentElement();
+ element2.innerHTML = element2.innerHTML;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return endElement;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove the broken elements
+ element.innerHTML = element.innerHTML;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- endElement = rng.endContainer;
- endOffset = rng.endOffset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Restore the selection
+ self.moveToBookmark(bookmark);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (endElement.nodeType == 1 && endElement.hasChildNodes()) {
- if (!real || !rng.collapsed) {
- endElement = endElement.childNodes[endOffset > 0 ? endOffset - 1 : endOffset];
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Since the range has moved we need to re-get it
+ ieRange = selection.getRng();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (endElement && endElement.nodeType == 3) {
- return endElement.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find start point
+ findEndPoint(true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return endElement;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find end point if needed
+ if (!collapsed) {
+ findEndPoint();
+ }
+ } else {
+ throw ex; // Throw other errors
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a bookmark location for the current selection. This bookmark object
- * can then be used to restore the selection after some content modification to the document.
- *
- * @method getBookmark
- * @param {Number} type Optional state if the bookmark should be simple or not. Default is complex.
- * @param {Boolean} normalized Optional state that enables you to get a position that it would be after normalization.
- * @return {Object} Bookmark object, use moveToBookmark with this object to restore the selection.
- * @example
- * // Stores a bookmark of the current selection
- * var bm = tinymce.activeEditor.selection.getBookmark();
- *
- * tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
- *
- * // Restore the selection bookmark
- * tinymce.activeEditor.selection.moveToBookmark(bm);
- */
- getBookmark: function(type, normalized) {
- return this.bookmarkManager.getBookmark(type, normalized);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return domRange;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Restores the selection to the specified bookmark.
- *
- * @method moveToBookmark
- * @param {Object} bookmark Bookmark to restore selection from.
- * @return {Boolean} true/false if it was successful or not.
- * @example
- * // Stores a bookmark of the current selection
- * var bm = tinymce.activeEditor.selection.getBookmark();
- *
- * tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
- *
- * // Restore the selection bookmark
- * tinymce.activeEditor.selection.moveToBookmark(bm);
- */
- moveToBookmark: function(bookmark) {
- return this.bookmarkManager.moveToBookmark(bookmark);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.getBookmark = function (type) {
+ var rng = selection.getRng(), bookmark = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Selects the specified element. This will place the start and end of the selection range around the element.
- *
- * @method select
- * @param {Element} node HTML DOM element to select.
- * @param {Boolean} content Optional bool state if the contents should be selected or not on non IE browser.
- * @return {Element} Selected element the same element as the one that got passed in.
- * @example
- * // Select the first paragraph in the active editor
- * tinymce.activeEditor.selection.select(tinymce.activeEditor.dom.select('p')[0]);
- */
- select: function(node, content) {
- var self = this, dom = self.dom, rng = dom.createRng(), idx;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getIndexes(node) {
+ var parent, root, children, i, indexes = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Clear stored range set by FocusManager
- self.lastFocusBookmark = null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parent = node.parentNode;
+ root = dom.getRoot().parentNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node) {
- if (!content && self.controlSelection.controlSelect(node)) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (parent != root && parent.nodeType !== 9) {
+ children = parent.children;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- idx = dom.nodeIndex(node);
- rng.setStart(node.parentNode, idx);
- rng.setEnd(node.parentNode, idx + 1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ i = children.length;
+ while (i--) {
+ if (node === children[i]) {
+ indexes.push(i);
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Find first/last text node or BR element
- if (content) {
- self._moveEndPoint(rng, node, true);
- self._moveEndPoint(rng, node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = parent;
+ parent = parent.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.setRng(rng);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return indexes;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return node;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getBookmarkEndPoint(start) {
+ var position;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the selection range is collapsed or not. Collapsed means if it's a caret or a larger selection.
- *
- * @method isCollapsed
- * @return {Boolean} true/false state if the selection range is collapsed or not.
- * Collapsed means if it's a caret or a larger selection.
- */
- isCollapsed: function() {
- var self = this, rng = self.getRng(), sel = self.getSel();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ position = getPosition(rng, start);
+ if (position) {
+ return {
+ position: position.position,
+ offset: position.offset,
+ indexes: getIndexes(position.node),
+ inside: position.inside
+ };
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!rng || rng.item) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Non ubstructive bookmark
+ if (type === 2) {
+ // Handle text selection
+ if (!rng.item) {
+ bookmark.start = getBookmarkEndPoint(true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rng.compareEndPoints) {
- return rng.compareEndPoints('StartToEnd', rng) === 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!selection.isCollapsed()) {
+ bookmark.end = getBookmarkEndPoint();
+ }
+ } else {
+ bookmark.start = { ctrl: true, indexes: getIndexes(rng.item(0)) };
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return !sel || rng.collapsed;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return bookmark;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Collapse the selection to start or end of range.
- *
- * @method collapse
- * @param {Boolean} toStart Optional boolean state if to collapse to end or not. Defaults to false.
- */
- collapse: function(toStart) {
- var self = this, rng = self.getRng(), node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.moveToBookmark = function (bookmark) {
+ var rng, body = dom.doc.body;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Control range on IE
- if (rng.item) {
- node = rng.item(0);
- rng = self.win.document.body.createTextRange();
- rng.moveToElementText(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function resolveIndexes(indexes) {
+ var node, i, idx, children;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng.collapse(!!toStart);
- self.setRng(rng);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = dom.getRoot();
+ for (i = indexes.length - 1; i >= 0; i--) {
+ children = node.children;
+ idx = indexes[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the browsers internal selection object.
- *
- * @method getSel
- * @return {Selection} Internal browser selection object.
- */
- getSel: function() {
- var win = this.win;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (idx <= children.length - 1) {
+ node = children[idx];
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return win.getSelection ? win.getSelection() : win.document.selection;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the browsers internal range object.
- *
- * @method getRng
- * @param {Boolean} w3c Forces a compatible W3C range on IE.
- * @return {Range} Internal browser range object.
- * @see http://www.quirksmode.org/dom/range_intro.html
- * @see http://www.dotvoid.com/2001/03/using-the-range-object-in-mozilla/
- */
- getRng: function(w3c) {
- var self = this, selection, rng, elm, doc, ieRng, evt;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setBookmarkEndPoint(start) {
+ var endPoint = bookmark[start ? 'start' : 'end'], moveLeft, moveRng, undef, offset;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function tryCompareBoundaryPoints(how, sourceRange, destinationRange) {
- try {
- return sourceRange.compareBoundaryPoints(how, destinationRange);
- } catch (ex) {
- // Gecko throws wrong document exception if the range points
- // to nodes that where removed from the dom #6690
- // Browsers should mutate existing DOMRange instances so that they always point
- // to something in the document this is not the case in Gecko works fine in IE/WebKit/Blink
- // For performance reasons just return -1
- return -1;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (endPoint) {
+ moveLeft = endPoint.position > 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.win) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ moveRng = body.createTextRange();
+ moveRng.moveToElementText(resolveIndexes(endPoint.indexes));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- doc = self.win.document;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ offset = endPoint.offset;
+ if (offset !== undef) {
+ moveRng.collapse(endPoint.inside || moveLeft);
+ moveRng.moveStart('character', moveLeft ? -offset : offset);
+ } else {
+ moveRng.collapse(start);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof doc === 'undefined' || doc === null) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng.setEndPoint(start ? 'StartToStart' : 'EndToStart', moveRng);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Use last rng passed from FocusManager if it's available this enables
- // calls to editor.selection.getStart() to work when caret focus is lost on IE
- if (!w3c && self.lastFocusBookmark) {
- var bookmark = self.lastFocusBookmark;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (start) {
+ rng.collapse(true);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Convert bookmark to range IE 11 fix
- if (bookmark.startContainer) {
- rng = doc.createRange();
- rng.setStart(bookmark.startContainer, bookmark.startOffset);
- rng.setEnd(bookmark.endContainer, bookmark.endOffset);
- } else {
- rng = bookmark;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (bookmark.start) {
+ if (bookmark.start.ctrl) {
+ rng = body.createControlRange();
+ rng.addElement(resolveIndexes(bookmark.start.indexes));
+ rng.select();
+ } else {
+ rng = body.createTextRange();
+ setBookmarkEndPoint(true);
+ setBookmarkEndPoint();
+ rng.select();
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return rng;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.addRange = function (rng) {
+ var ieRng, ctrlRng, startContainer, startOffset, endContainer, endOffset, sibling,
+ doc = selection.dom.doc, body = doc.body, nativeRng, ctrlElm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Found tridentSel object then we need to use that one
- if (w3c && self.tridentSel) {
- return self.tridentSel.getRangeAt(0);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setEndPoint(start) {
+ var container, offset, marker, tmpRng, nodes;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- try {
- if ((selection = self.getSel())) {
- if (selection.rangeCount > 0) {
- rng = selection.getRangeAt(0);
- } else {
- rng = selection.createRange ? selection.createRange() : doc.createRange();
- }
- }
- } catch (ex) {
- // IE throws unspecified error here if TinyMCE is placed in a frame/iframe
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ marker = dom.create('a');
+ container = start ? startContainer : endContainer;
+ offset = start ? startOffset : endOffset;
+ tmpRng = ieRng.duplicate();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- evt = self.editor.fire('GetSelectionRange', {range: rng});
- if (evt.range !== rng) {
- return evt.range;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (container == doc || container == doc.documentElement) {
+ container = body;
+ offset = 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // We have W3C ranges and it's IE then fake control selection since IE9 doesn't handle that correctly yet
- // IE 11 doesn't support the selection object so we check for that as well
- if (isIE && rng && rng.setStart && doc.selection) {
- try {
- // IE will sometimes throw an exception here
- ieRng = doc.selection.createRange();
- } catch (ex) {
- // Ignore
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (container.nodeType == 3) {
+ container.parentNode.insertBefore(marker, container);
+ tmpRng.moveToElementText(marker);
+ tmpRng.moveStart('character', offset);
+ dom.remove(marker);
+ ieRng.setEndPoint(start ? 'StartToStart' : 'EndToEnd', tmpRng);
+ } else {
+ nodes = container.childNodes;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (ieRng && ieRng.item) {
- elm = ieRng.item(0);
- rng = doc.createRange();
- rng.setStartBefore(elm);
- rng.setEndAfter(elm);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (nodes.length) {
+ if (offset >= nodes.length) {
+ dom.insertAfter(marker, nodes[nodes.length - 1]);
+ } else {
+ container.insertBefore(marker, nodes[offset]);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // No range found then create an empty one
- // This can occur when the editor is placed in a hidden container element on Gecko
- // Or on IE when there was an exception
- if (!rng) {
- rng = doc.createRange ? doc.createRange() : doc.body.createTextRange();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ tmpRng.moveToElementText(marker);
+ } else if (container.canHaveHTML) {
+ // Empty node selection for example <div>|</div>
+ // Setting innerHTML with a span marker then remove that marker seems to keep empty block elements open
+ container.innerHTML = '<span></span>';
+ marker = container.firstChild;
+ tmpRng.moveToElementText(marker);
+ tmpRng.collapse(FALSE); // Collapse false works better than true for some odd reason
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If range is at start of document then move it to start of body
- if (rng.setStart && rng.startContainer.nodeType === 9 && rng.collapsed) {
- elm = self.dom.getRoot();
- rng.setStart(elm, 0);
- rng.setEnd(elm, 0);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ieRng.setEndPoint(start ? 'StartToStart' : 'EndToEnd', tmpRng);
+ dom.remove(marker);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.selectedRange && self.explicitRange) {
- if (tryCompareBoundaryPoints(rng.START_TO_START, rng, self.selectedRange) === 0 &&
- tryCompareBoundaryPoints(rng.END_TO_END, rng, self.selectedRange) === 0) {
- // Safari, Opera and Chrome only ever select text which causes the range to change.
- // This lets us use the originally set range if the selection hasn't been changed by the user.
- rng = self.explicitRange;
- } else {
- self.selectedRange = null;
- self.explicitRange = null;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup some shorter versions
+ startContainer = rng.startContainer;
+ startOffset = rng.startOffset;
+ endContainer = rng.endContainer;
+ endOffset = rng.endOffset;
+ ieRng = body.createTextRange();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return rng;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If single element selection then try making a control selection out of it
+ if (startContainer == endContainer && startContainer.nodeType == 1) {
+ // Trick to place the caret inside an empty block element like <p></p>
+ if (startOffset == endOffset && !startContainer.hasChildNodes()) {
+ if (startContainer.canHaveHTML) {
+ // Check if previous sibling is an empty block if it is then we need to render it
+ // IE would otherwise move the caret into the sibling instead of the empty startContainer see: #5236
+ // Example this: <p></p><p>|</p> would become this: <p>|</p><p></p>
+ sibling = startContainer.previousSibling;
+ if (sibling && !sibling.hasChildNodes() && dom.isBlock(sibling)) {
+ sibling.innerHTML = '';
+ } else {
+ sibling = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Changes the selection to the specified DOM range.
- *
- * @method setRng
- * @param {Range} rng Range to select.
- * @param {Boolean} forward Optional boolean if the selection is forwards or backwards.
- */
- setRng: function(rng, forward) {
- var self = this, sel, node, evt;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ startContainer.innerHTML = '<span></span><span></span>';
+ ieRng.moveToElementText(startContainer.lastChild);
+ ieRng.select();
+ dom.doc.selection.clear();
+ startContainer.innerHTML = '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!rng) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (sibling) {
+ sibling.innerHTML = '';
+ }
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Is IE specific range
- if (rng.select) {
- self.explicitRange = null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ startOffset = dom.nodeIndex(startContainer);
+ startContainer = startContainer.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- try {
- rng.select();
- } catch (ex) {
- // Needed for some odd IE bug #1843306
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (startOffset == endOffset - 1) {
+ try {
+ ctrlElm = startContainer.childNodes[startOffset];
+ ctrlRng = body.createControlRange();
+ ctrlRng.addElement(ctrlElm);
+ ctrlRng.select();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if the range produced is on the correct element and is a control range
+ // On IE 8 it will select the parent contentEditable container if you select an inner element see: #5398
+ nativeRng = selection.getRng();
+ if (nativeRng.item && ctrlElm === nativeRng.item(0)) {
+ return;
+ }
+ } catch (ex) {
+ // Ignore
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.tridentSel) {
- sel = self.getSel();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set start/end point of selection
+ setEndPoint(true);
+ setEndPoint();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- evt = self.editor.fire('SetSelectionRange', {range: rng});
- rng = evt.range;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Select the new range and scroll it into view
+ ieRng.select();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (sel) {
- self.explicitRange = rng;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Expose range method
+ this.getRangeAt = getRange;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- try {
- sel.removeAllRanges();
- sel.addRange(rng);
- } catch (ex) {
- // IE might throw errors here if the editor is within a hidden container and selection is changed
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Selection;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Forward is set to false and we have an extend function
- if (forward === false && sel.extend) {
- sel.collapse(rng.endContainer, rng.endOffset);
- sel.extend(rng.startContainer, rng.startOffset);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Selection.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // adding range isn't always successful so we need to check range count otherwise an exception can occur
- self.selectedRange = sel.rangeCount > 0 ? sel.getRangeAt(0) : null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * This class handles text and control selection it's an crossbrowser utility class.
+ * Consult the TinyMCE Wiki API for more details and examples on how to use this class.
+ *
+ * @class tinymce.dom.Selection
+ * @example
+ * // Getting the currently selected node for the active editor
+ * alert(tinymce.activeEditor.selection.getNode().nodeName);
+ */
+define(
+ 'tinymce.core.dom.Selection',
+ [
+ 'tinymce.core.caret.CaretPosition',
+ 'tinymce.core.dom.BookmarkManager',
+ 'tinymce.core.dom.ControlSelection',
+ 'tinymce.core.dom.NodeType',
+ 'tinymce.core.dom.RangeUtils',
+ 'tinymce.core.dom.ScrollIntoView',
+ 'tinymce.core.dom.TreeWalker',
+ 'tinymce.core.dom.TridentSelection',
+ 'tinymce.core.Env',
+ 'tinymce.core.text.Zwsp',
+ 'tinymce.core.util.Tools'
+ ],
+ function (CaretPosition, BookmarkManager, ControlSelection, NodeType, RangeUtils, ScrollIntoView, TreeWalker, TridentSelection, Env, Zwsp, Tools) {
+ var each = Tools.each, trim = Tools.trim;
+ var isIE = Env.ie;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // WebKit egde case selecting images works better using setBaseAndExtent when the image is floated
- if (!rng.collapsed && rng.startContainer == rng.endContainer && sel.setBaseAndExtent && !Env.ie) {
- if (rng.endOffset - rng.startOffset < 2) {
- if (rng.startContainer.hasChildNodes()) {
- node = rng.startContainer.childNodes[rng.startOffset];
- if (node && node.tagName == 'IMG') {
- sel.setBaseAndExtent(
- rng.startContainer,
- rng.startOffset,
- rng.endContainer,
- rng.endOffset
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a new selection instance.
+ *
+ * @constructor
+ * @method Selection
+ * @param {tinymce.dom.DOMUtils} dom DOMUtils object reference.
+ * @param {Window} win Window to bind the selection object to.
+ * @param {tinymce.Editor} editor Editor instance of the selection.
+ * @param {tinymce.dom.Serializer} serializer DOM serialization class to use for getContent.
+ */
+ function Selection(dom, win, serializer, editor) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Since the setBaseAndExtent is fixed in more recent Blink versions we
- // need to detect if it's doing the wrong thing and falling back to the
- // crazy incorrect behavior api call since that seems to be the only way
- // to get it to work on Safari WebKit as of 2017-02-23
- if (sel.anchorNode !== rng.startContainer || sel.focusNode !== rng.endContainer) {
- sel.setBaseAndExtent(node, 0, node, 1);
- }
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.dom = dom;
+ self.win = win;
+ self.serializer = serializer;
+ self.editor = editor;
+ self.bookmarkManager = new BookmarkManager(self);
+ self.controlSelection = new ControlSelection(self, editor);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.editor.fire('AfterSetSelectionRange', {range: rng});
- } else {
- // Is W3C Range fake range on IE
- if (rng.cloneRange) {
- try {
- self.tridentSel.addRange(rng);
- } catch (ex) {
- //IE9 throws an error here if called before selection is placed in the editor
- }
- }
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // No W3C Range support
+ if (!self.win.getSelection) {
+ self.tridentSel = new TridentSelection(self);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets the current selection to the specified DOM element.
- *
- * @method setNode
- * @param {Element} elm Element to set as the contents of the selection.
- * @return {Element} Returns the element that got passed in.
- * @example
- * // Inserts a DOM node at current selection/caret location
- * tinymce.activeEditor.selection.setNode(tinymce.activeEditor.dom.create('img', {src: 'some.gif', title: 'some title'}));
- */
- setNode: function(elm) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Selection.prototype = {
+ /**
+ * Move the selection cursor range to the specified node and offset.
+ * If there is no node specified it will move it to the first suitable location within the body.
+ *
+ * @method setCursorLocation
+ * @param {Node} node Optional node to put the cursor in.
+ * @param {Number} offset Optional offset from the start of the node to put the cursor at.
+ */
+ setCursorLocation: function (node, offset) {
+ var self = this, rng = self.dom.createRng();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.setContent(self.dom.getOuterHTML(elm));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!node) {
+ self._moveEndPoint(rng, self.editor.getBody(), true);
+ self.setRng(rng);
+ } else {
+ rng.setStart(node, offset);
+ rng.setEnd(node, offset);
+ self.setRng(rng);
+ self.collapse(false);
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return elm;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the selected contents using the DOM serializer passed in to this class.
+ *
+ * @method getContent
+ * @param {Object} args Optional settings class with for example output format text or html.
+ * @return {String} Selected contents in for example HTML format.
+ * @example
+ * // Alerts the currently selected contents
+ * alert(tinymce.activeEditor.selection.getContent());
+ *
+ * // Alerts the currently selected contents as plain text
+ * alert(tinymce.activeEditor.selection.getContent({format: 'text'}));
+ */
+ getContent: function (args) {
+ var self = this, rng = self.getRng(), tmpElm = self.dom.create("body");
+ var se = self.getSel(), whiteSpaceBefore, whiteSpaceAfter, fragment;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the currently selected element or the common ancestor element for both start and end of the selection.
- *
- * @method getNode
- * @return {Element} Currently selected element or common ancestor element.
- * @example
- * // Alerts the currently selected elements node name
- * alert(tinymce.activeEditor.selection.getNode().nodeName);
- */
- getNode: function() {
- var self = this, rng = self.getRng(), elm;
- var startContainer, endContainer, startOffset, endOffset, root = self.dom.getRoot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args = args || {};
+ whiteSpaceBefore = whiteSpaceAfter = '';
+ args.get = true;
+ args.format = args.format || 'html';
+ args.selection = true;
+ self.editor.fire('BeforeGetContent', args);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function skipEmptyTextNodes(node, forwards) {
- var orig = node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (args.format === 'text') {
+ return self.isCollapsed() ? '' : Zwsp.trim(rng.text || (se.toString ? se.toString() : ''));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (node && node.nodeType === 3 && node.length === 0) {
- node = forwards ? node.nextSibling : node.previousSibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rng.cloneContents) {
+ fragment = rng.cloneContents();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return node || orig;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (fragment) {
+ tmpElm.appendChild(fragment);
+ }
+ } else if (rng.item !== undefined || rng.htmlText !== undefined) {
+ // IE will produce invalid markup if elements are present that
+ // it doesn't understand like custom elements or HTML5 elements.
+ // Adding a BR in front of the contents and then remoiving it seems to fix it though.
+ tmpElm.innerHTML = '<br>' + (rng.item ? rng.item(0).outerHTML : rng.htmlText);
+ tmpElm.removeChild(tmpElm.firstChild);
+ } else {
+ tmpElm.innerHTML = rng.toString();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Range maybe lost after the editor is made visible again
- if (!rng) {
- return root;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Keep whitespace before and after
+ if (/^\s/.test(tmpElm.innerHTML)) {
+ whiteSpaceBefore = ' ';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- startContainer = rng.startContainer;
- endContainer = rng.endContainer;
- startOffset = rng.startOffset;
- endOffset = rng.endOffset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (/\s+$/.test(tmpElm.innerHTML)) {
+ whiteSpaceAfter = ' ';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rng.setStart) {
- elm = rng.commonAncestorContainer;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args.getInner = true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle selection a image or other control like element such as anchors
- if (!rng.collapsed) {
- if (startContainer == endContainer) {
- if (endOffset - startOffset < 2) {
- if (startContainer.hasChildNodes()) {
- elm = startContainer.childNodes[startOffset];
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args.content = self.isCollapsed() ? '' : whiteSpaceBefore + self.serializer.serialize(tmpElm, args) + whiteSpaceAfter;
+ self.editor.fire('GetContent', args);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If the anchor node is a element instead of a text node then return this element
- //if (tinymce.isWebKit && sel.anchorNode && sel.anchorNode.nodeType == 1)
- // return sel.anchorNode.childNodes[sel.anchorOffset];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return args.content;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle cases where the selection is immediately wrapped around a node and return that node instead of it's parent.
- // This happens when you double click an underlined word in FireFox.
- if (startContainer.nodeType === 3 && endContainer.nodeType === 3) {
- if (startContainer.length === startOffset) {
- startContainer = skipEmptyTextNodes(startContainer.nextSibling, true);
- } else {
- startContainer = startContainer.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets the current selection to the specified content. If any contents is selected it will be replaced
+ * with the contents passed in to this function. If there is no selection the contents will be inserted
+ * where the caret is placed in the editor/page.
+ *
+ * @method setContent
+ * @param {String} content HTML contents to set could also be other formats depending on settings.
+ * @param {Object} args Optional settings object with for example data format.
+ * @example
+ * // Inserts some HTML contents at the current selection
+ * tinymce.activeEditor.selection.setContent('<strong>Some contents</strong>');
+ */
+ setContent: function (content, args) {
+ var self = this, rng = self.getRng(), caretNode, doc = self.win.document, frag, temp;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (endOffset === 0) {
- endContainer = skipEmptyTextNodes(endContainer.previousSibling, false);
- } else {
- endContainer = endContainer.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args = args || { format: 'html' };
+ args.set = true;
+ args.selection = true;
+ args.content = content;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (startContainer && startContainer === endContainer) {
- return startContainer;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Dispatch before set content event
+ if (!args.no_events) {
+ self.editor.fire('BeforeSetContent', args);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elm && elm.nodeType == 3) {
- return elm.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ content = args.content;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return elm;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rng.insertNode) {
+ // Make caret marker since insertNode places the caret in the beginning of text after insert
+ content += '<span id="__caret">_</span>';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elm = rng.item ? rng.item(0) : rng.parentElement();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Delete and insert new node
+ if (rng.startContainer == doc && rng.endContainer == doc) {
+ // WebKit will fail if the body is empty since the range is then invalid and it can't insert contents
+ doc.body.innerHTML = content;
+ } else {
+ rng.deleteContents();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // IE 7 might return elements outside the iframe
- if (elm.ownerDocument !== self.win.document) {
- elm = root;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (doc.body.childNodes.length === 0) {
+ doc.body.innerHTML = content;
+ } else {
+ // createContextualFragment doesn't exists in IE 9 DOMRanges
+ if (rng.createContextualFragment) {
+ rng.insertNode(rng.createContextualFragment(content));
+ } else {
+ // Fake createContextualFragment call in IE 9
+ frag = doc.createDocumentFragment();
+ temp = doc.createElement('div');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return elm;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ frag.appendChild(temp);
+ temp.outerHTML = content;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- getSelectedBlocks: function(startElm, endElm) {
- var self = this, dom = self.dom, node, root, selectedBlocks = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng.insertNode(frag);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- root = dom.getRoot();
- startElm = dom.getParent(startElm || self.getStart(), dom.isBlock);
- endElm = dom.getParent(endElm || self.getEnd(), dom.isBlock);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move to caret marker
+ caretNode = self.dom.get('__caret');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (startElm && startElm != root) {
- selectedBlocks.push(startElm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Make sure we wrap it compleatly, Opera fails with a simple select call
+ rng = doc.createRange();
+ rng.setStartBefore(caretNode);
+ rng.setEndBefore(caretNode);
+ self.setRng(rng);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (startElm && endElm && startElm != endElm) {
- node = startElm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove the caret position
+ self.dom.remove('__caret');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var walker = new TreeWalker(startElm, root);
- while ((node = walker.next()) && node != endElm) {
- if (dom.isBlock(node)) {
- selectedBlocks.push(node);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ try {
+ self.setRng(rng);
+ } catch (ex) {
+ // Might fail on Opera for some odd reason
+ }
+ } else {
+ if (rng.item) {
+ // Delete content and get caret text selection
+ doc.execCommand('Delete', false, null);
+ rng = self.getRng();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (endElm && startElm != endElm && endElm != root) {
- selectedBlocks.push(endElm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Explorer removes spaces from the beginning of pasted contents
+ if (/^\s+/.test(content)) {
+ rng.pasteHTML('<span id="__mce_tmp">_</span>' + content);
+ self.dom.remove('__mce_tmp');
+ } else {
+ rng.pasteHTML(content);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return selectedBlocks;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Dispatch set content event
+ if (!args.no_events) {
+ self.editor.fire('SetContent', args);
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- isForward: function() {
- var dom = this.dom, sel = this.getSel(), anchorRange, focusRange;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the start element of a selection range. If the start is in a text
+ * node the parent element will be returned.
+ *
+ * @method getStart
+ * @param {Boolean} real Optional state to get the real parent when the selection is collapsed not the closest element.
+ * @return {Element} Start element of selection range.
+ */
+ getStart: function (real) {
+ var self = this, rng = self.getRng(), startElement, parentElement, checkRng, node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // No support for selection direction then always return true
- if (!sel || !sel.anchorNode || !sel.focusNode) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rng.duplicate || rng.item) {
+ // Control selection, return first item
+ if (rng.item) {
+ return rng.item(0);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- anchorRange = dom.createRng();
- anchorRange.setStart(sel.anchorNode, sel.anchorOffset);
- anchorRange.collapse(true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get start element
+ checkRng = rng.duplicate();
+ checkRng.collapse(1);
+ startElement = checkRng.parentElement();
+ if (startElement.ownerDocument !== self.dom.doc) {
+ startElement = self.dom.getRoot();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- focusRange = dom.createRng();
- focusRange.setStart(sel.focusNode, sel.focusOffset);
- focusRange.collapse(true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if range parent is inside the start element, then return the inner parent element
+ // This will fix issues when a single element is selected, IE would otherwise return the wrong start element
+ parentElement = node = rng.parentElement();
+ while ((node = node.parentNode)) {
+ if (node == startElement) {
+ startElement = parentElement;
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return anchorRange.compareBoundaryPoints(anchorRange.START_TO_START, focusRange) <= 0;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return startElement;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- normalize: function() {
- var self = this, rng = self.getRng();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ startElement = rng.startContainer;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (Env.range && new RangeUtils(self.dom).normalize(rng)) {
- self.setRng(rng, self.isForward());
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (startElement.nodeType == 1 && startElement.hasChildNodes()) {
+ if (!real || !rng.collapsed) {
+ startElement = startElement.childNodes[Math.min(startElement.childNodes.length - 1, rng.startOffset)];
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return rng;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (startElement && startElement.nodeType == 3) {
+ return startElement.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Executes callback when the current selection starts/stops matching the specified selector. The current
- * state will be passed to the callback as it's first argument.
- *
- * @method selectorChanged
- * @param {String} selector CSS selector to check for.
- * @param {function} callback Callback with state and args when the selector is matches or not.
- */
- selectorChanged: function(selector, callback) {
- var self = this, currentSelectors;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return startElement;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.selectorChangedData) {
- self.selectorChangedData = {};
- currentSelectors = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the end element of a selection range. If the end is in a text
+ * node the parent element will be returned.
+ *
+ * @method getEnd
+ * @param {Boolean} real Optional state to get the real parent when the selection is collapsed not the closest element.
+ * @return {Element} End element of selection range.
+ */
+ getEnd: function (real) {
+ var self = this, rng = self.getRng(), endElement, endOffset;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.editor.on('NodeChange', function(e) {
- var node = e.element, dom = self.dom, parents = dom.getParents(node, null, dom.getRoot()), matchedSelectors = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rng.duplicate || rng.item) {
+ if (rng.item) {
+ return rng.item(0);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check for new matching selectors
- each(self.selectorChangedData, function(callbacks, selector) {
- each(parents, function(node) {
- if (dom.is(node, selector)) {
- if (!currentSelectors[selector]) {
- // Execute callbacks
- each(callbacks, function(callback) {
- callback(true, {node: node, selector: selector, parents: parents});
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng = rng.duplicate();
+ rng.collapse(0);
+ endElement = rng.parentElement();
+ if (endElement.ownerDocument !== self.dom.doc) {
+ endElement = self.dom.getRoot();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- currentSelectors[selector] = callbacks;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (endElement && endElement.nodeName == 'BODY') {
+ return endElement.lastChild || endElement;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- matchedSelectors[selector] = callbacks;
- return false;
- }
- });
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return endElement;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if current selectors still match
- each(currentSelectors, function(callbacks, selector) {
- if (!matchedSelectors[selector]) {
- delete currentSelectors[selector];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ endElement = rng.endContainer;
+ endOffset = rng.endOffset;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(callbacks, function(callback) {
- callback(false, {node: node, selector: selector, parents: parents});
- });
- }
- });
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (endElement.nodeType == 1 && endElement.hasChildNodes()) {
+ if (!real || !rng.collapsed) {
+ endElement = endElement.childNodes[endOffset > 0 ? endOffset - 1 : endOffset];
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add selector listeners
- if (!self.selectorChangedData[selector]) {
- self.selectorChangedData[selector] = [];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (endElement && endElement.nodeType == 3) {
+ return endElement.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.selectorChangedData[selector].push(callback);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return endElement;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a bookmark location for the current selection. This bookmark object
+ * can then be used to restore the selection after some content modification to the document.
+ *
+ * @method getBookmark
+ * @param {Number} type Optional state if the bookmark should be simple or not. Default is complex.
+ * @param {Boolean} normalized Optional state that enables you to get a position that it would be after normalization.
+ * @return {Object} Bookmark object, use moveToBookmark with this object to restore the selection.
+ * @example
+ * // Stores a bookmark of the current selection
+ * var bm = tinymce.activeEditor.selection.getBookmark();
+ *
+ * tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
+ *
+ * // Restore the selection bookmark
+ * tinymce.activeEditor.selection.moveToBookmark(bm);
+ */
+ getBookmark: function (type, normalized) {
+ return this.bookmarkManager.getBookmark(type, normalized);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- getScrollContainer: function() {
- var scrollContainer, node = this.dom.getRoot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Restores the selection to the specified bookmark.
+ *
+ * @method moveToBookmark
+ * @param {Object} bookmark Bookmark to restore selection from.
+ * @return {Boolean} true/false if it was successful or not.
+ * @example
+ * // Stores a bookmark of the current selection
+ * var bm = tinymce.activeEditor.selection.getBookmark();
+ *
+ * tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
+ *
+ * // Restore the selection bookmark
+ * tinymce.activeEditor.selection.moveToBookmark(bm);
+ */
+ moveToBookmark: function (bookmark) {
+ return this.bookmarkManager.moveToBookmark(bookmark);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (node && node.nodeName != 'BODY') {
- if (node.scrollHeight > node.clientHeight) {
- scrollContainer = node;
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Selects the specified element. This will place the start and end of the selection range around the element.
+ *
+ * @method select
+ * @param {Element} node HTML DOM element to select.
+ * @param {Boolean} content Optional bool state if the contents should be selected or not on non IE browser.
+ * @return {Element} Selected element the same element as the one that got passed in.
+ * @example
+ * // Select the first paragraph in the active editor
+ * tinymce.activeEditor.selection.select(tinymce.activeEditor.dom.select('p')[0]);
+ */
+ select: function (node, content) {
+ var self = this, dom = self.dom, rng = dom.createRng(), idx;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Clear stored range set by FocusManager
+ self.lastFocusBookmark = null;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return scrollContainer;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node) {
+ if (!content && self.controlSelection.controlSelect(node)) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- scrollIntoView: function(elm, alignToTop) {
- var y, viewPort, self = this, dom = self.dom, root = dom.getRoot(), viewPortY, viewPortH, offsetY = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ idx = dom.nodeIndex(node);
+ rng.setStart(node.parentNode, idx);
+ rng.setEnd(node.parentNode, idx + 1);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getPos(elm) {
- var x = 0, y = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find first/last text node or BR element
+ if (content) {
+ self._moveEndPoint(rng, node, true);
+ self._moveEndPoint(rng, node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var offsetParent = elm;
- while (offsetParent && offsetParent.nodeType) {
- x += offsetParent.offsetLeft || 0;
- y += offsetParent.offsetTop || 0;
- offsetParent = offsetParent.offsetParent;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.setRng(rng);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {x: x, y: y};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return node;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!NodeType.isElement(elm)) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the selection range is collapsed or not. Collapsed means if it's a caret or a larger selection.
+ *
+ * @method isCollapsed
+ * @return {Boolean} true/false state if the selection range is collapsed or not.
+ * Collapsed means if it's a caret or a larger selection.
+ */
+ isCollapsed: function () {
+ var self = this, rng = self.getRng(), sel = self.getSel();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (alignToTop === false) {
- offsetY = elm.offsetHeight;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!rng || rng.item) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (root.nodeName != 'BODY') {
- var scrollContainer = self.getScrollContainer();
- if (scrollContainer) {
- y = getPos(elm).y - getPos(scrollContainer).y + offsetY;
- viewPortH = scrollContainer.clientHeight;
- viewPortY = scrollContainer.scrollTop;
- if (y < viewPortY || y + 25 > viewPortY + viewPortH) {
- scrollContainer.scrollTop = y < viewPortY ? y : y - viewPortH + 25;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rng.compareEndPoints) {
+ return rng.compareEndPoints('StartToEnd', rng) === 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return !sel || rng.collapsed;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- viewPort = dom.getViewPort(self.editor.getWin());
- y = dom.getPos(elm).y + offsetY;
- viewPortY = viewPort.y;
- viewPortH = viewPort.h;
- if (y < viewPort.y || y + 25 > viewPortY + viewPortH) {
- self.editor.getWin().scrollTo(0, y < viewPortY ? y : y - viewPortH + 25);
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Collapse the selection to start or end of range.
+ *
+ * @method collapse
+ * @param {Boolean} toStart Optional boolean state if to collapse to end or not. Defaults to false.
+ */
+ collapse: function (toStart) {
+ var self = this, rng = self.getRng(), node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- placeCaretAt: function(clientX, clientY) {
- this.setRng(RangeUtils.getCaretRangeFromPoint(clientX, clientY, this.editor.getDoc()));
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Control range on IE
+ if (rng.item) {
+ node = rng.item(0);
+ rng = self.win.document.body.createTextRange();
+ rng.moveToElementText(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- _moveEndPoint: function(rng, node, start) {
- var root = node, walker = new TreeWalker(node, root);
- var nonEmptyElementsMap = this.dom.schema.getNonEmptyElements();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng.collapse(!!toStart);
+ self.setRng(rng);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- do {
- // Text node
- if (node.nodeType == 3 && trim(node.nodeValue).length !== 0) {
- if (start) {
- rng.setStart(node, 0);
- } else {
- rng.setEnd(node, node.nodeValue.length);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the browsers internal selection object.
+ *
+ * @method getSel
+ * @return {Selection} Internal browser selection object.
+ */
+ getSel: function () {
+ var win = this.win;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return win.getSelection ? win.getSelection() : win.document.selection;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // BR/IMG/INPUT elements but not table cells
- if (nonEmptyElementsMap[node.nodeName] && !/^(TD|TH)$/.test(node.nodeName)) {
- if (start) {
- rng.setStartBefore(node);
- } else {
- if (node.nodeName == 'BR') {
- rng.setEndBefore(node);
- } else {
- rng.setEndAfter(node);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the browsers internal range object.
+ *
+ * @method getRng
+ * @param {Boolean} w3c Forces a compatible W3C range on IE.
+ * @return {Range} Internal browser range object.
+ * @see http://www.quirksmode.org/dom/range_intro.html
+ * @see http://www.dotvoid.com/2001/03/using-the-range-object-in-mozilla/
+ */
+ getRng: function (w3c) {
+ var self = this, selection, rng, elm, doc, ieRng, evt;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function tryCompareBoundaryPoints(how, sourceRange, destinationRange) {
+ try {
+ return sourceRange.compareBoundaryPoints(how, destinationRange);
+ } catch (ex) {
+ // Gecko throws wrong document exception if the range points
+ // to nodes that where removed from the dom #6690
+ // Browsers should mutate existing DOMRange instances so that they always point
+ // to something in the document this is not the case in Gecko works fine in IE/WebKit/Blink
+ // For performance reasons just return -1
+ return -1;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Found empty text block old IE can place the selection inside those
- if (Env.ie && Env.ie < 11 && this.dom.isBlock(node) && this.dom.isEmpty(node)) {
- if (start) {
- rng.setStart(node, 0);
- } else {
- rng.setEnd(node, 0);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.win) {
+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
- } while ((node = (start ? walker.next() : walker.prev())));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ doc = self.win.document;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Failed to find any text node or other suitable location then move to the root of body
- if (root.nodeName == 'BODY') {
- if (start) {
- rng.setStart(root, 0);
- } else {
- rng.setEnd(root, root.childNodes.length);
- }
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof doc === 'undefined' || doc === null) {
+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- getBoundingClientRect: function() {
- var rng = this.getRng();
- return rng.collapsed ? CaretPosition.fromRangeStart(rng).getClientRects()[0] : rng.getBoundingClientRect();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Use last rng passed from FocusManager if it's available this enables
+ // calls to editor.selection.getStart() to work when caret focus is lost on IE
+ if (!w3c && self.lastFocusBookmark) {
+ var bookmark = self.lastFocusBookmark;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- destroy: function() {
- this.win = null;
- this.controlSelection.destroy();
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Convert bookmark to range IE 11 fix
+ if (bookmark.startContainer) {
+ rng = doc.createRange();
+ rng.setStart(bookmark.startContainer, bookmark.startOffset);
+ rng.setEnd(bookmark.endContainer, bookmark.endOffset);
+ } else {
+ rng = bookmark;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Selection;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return rng;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/dom/ElementUtils.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Found tridentSel object then we need to use that one
+ if (w3c && self.tridentSel) {
+ return self.tridentSel.getRangeAt(0);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ try {
+ if ((selection = self.getSel())) {
+ if (selection.rangeCount > 0) {
+ rng = selection.getRangeAt(0);
+ } else {
+ rng = selection.createRange ? selection.createRange() : doc.createRange();
+ }
+ }
+ } catch (ex) {
+ // IE throws unspecified error here if TinyMCE is placed in a frame/iframe
+ }
+
+ evt = self.editor.fire('GetSelectionRange', { range: rng });
+ if (evt.range !== rng) {
+ return evt.range;
+ }
+
+ // We have W3C ranges and it's IE then fake control selection since IE9 doesn't handle that correctly yet
+ // IE 11 doesn't support the selection object so we check for that as well
+ if (isIE && rng && rng.setStart && doc.selection) {
+ try {
+ // IE will sometimes throw an exception here
+ ieRng = doc.selection.createRange();
+ } catch (ex) {
+ // Ignore
+ }
+
+ if (ieRng && ieRng.item) {
+ elm = ieRng.item(0);
+ rng = doc.createRange();
+ rng.setStartBefore(elm);
+ rng.setEndAfter(elm);
+ }
+ }
+
+ // No range found then create an empty one
+ // This can occur when the editor is placed in a hidden container element on Gecko
+ // Or on IE when there was an exception
+ if (!rng) {
+ rng = doc.createRange ? doc.createRange() : doc.body.createTextRange();
+ }
+
+ // If range is at start of document then move it to start of body
+ if (rng.setStart && rng.startContainer.nodeType === 9 && rng.collapsed) {
+ elm = self.dom.getRoot();
+ rng.setStart(elm, 0);
+ rng.setEnd(elm, 0);
+ }
+
+ if (self.selectedRange && self.explicitRange) {
+ if (tryCompareBoundaryPoints(rng.START_TO_START, rng, self.selectedRange) === 0 &&
+ tryCompareBoundaryPoints(rng.END_TO_END, rng, self.selectedRange) === 0) {
+ // Safari, Opera and Chrome only ever select text which causes the range to change.
+ // This lets us use the originally set range if the selection hasn't been changed by the user.
+ rng = self.explicitRange;
+ } else {
+ self.selectedRange = null;
+ self.explicitRange = null;
+ }
+ }
+
+ return rng;
+ },
+
+ /**
+ * Changes the selection to the specified DOM range.
+ *
+ * @method setRng
+ * @param {Range} rng Range to select.
+ * @param {Boolean} forward Optional boolean if the selection is forwards or backwards.
+ */
+ setRng: function (rng, forward) {
+ var self = this, sel, node, evt;
+
+ if (!rng) {
+ return;
+ }
+
+ // Is IE specific range
+ if (rng.select) {
+ self.explicitRange = null;
+
+ try {
+ rng.select();
+ } catch (ex) {
+ // Needed for some odd IE bug #1843306
+ }
+
+ return;
+ }
+
+ if (!self.tridentSel) {
+ sel = self.getSel();
+
+ evt = self.editor.fire('SetSelectionRange', { range: rng });
+ rng = evt.range;
+
+ if (sel) {
+ self.explicitRange = rng;
+
+ try {
+ sel.removeAllRanges();
+ sel.addRange(rng);
+ } catch (ex) {
+ // IE might throw errors here if the editor is within a hidden container and selection is changed
+ }
+
+ // Forward is set to false and we have an extend function
+ if (forward === false && sel.extend) {
+ sel.collapse(rng.endContainer, rng.endOffset);
+ sel.extend(rng.startContainer, rng.startOffset);
+ }
+
+ // adding range isn't always successful so we need to check range count otherwise an exception can occur
+ self.selectedRange = sel.rangeCount > 0 ? sel.getRangeAt(0) : null;
+ }
+
+ // WebKit egde case selecting images works better using setBaseAndExtent when the image is floated
+ if (!rng.collapsed && rng.startContainer === rng.endContainer && sel.setBaseAndExtent && !Env.ie) {
+ if (rng.endOffset - rng.startOffset < 2) {
+ if (rng.startContainer.hasChildNodes()) {
+ node = rng.startContainer.childNodes[rng.startOffset];
+ if (node && node.tagName === 'IMG') {
+ sel.setBaseAndExtent(
+ rng.startContainer,
+ rng.startOffset,
+ rng.endContainer,
+ rng.endOffset
+ );
+
+ // Since the setBaseAndExtent is fixed in more recent Blink versions we
+ // need to detect if it's doing the wrong thing and falling back to the
+ // crazy incorrect behavior api call since that seems to be the only way
+ // to get it to work on Safari WebKit as of 2017-02-23
+ if (sel.anchorNode !== rng.startContainer || sel.focusNode !== rng.endContainer) {
+ sel.setBaseAndExtent(node, 0, node, 1);
+ }
+ }
+ }
+ }
+ }
+
+ self.editor.fire('AfterSetSelectionRange', { range: rng });
+ } else {
+ // Is W3C Range fake range on IE
+ if (rng.cloneRange) {
+ try {
+ self.tridentSel.addRange(rng);
+ } catch (ex) {
+ //IE9 throws an error here if called before selection is placed in the editor
+ }
+ }
+ }
+ },
+
+ /**
+ * Sets the current selection to the specified DOM element.
+ *
+ * @method setNode
+ * @param {Element} elm Element to set as the contents of the selection.
+ * @return {Element} Returns the element that got passed in.
+ * @example
+ * // Inserts a DOM node at current selection/caret location
+ * tinymce.activeEditor.selection.setNode(tinymce.activeEditor.dom.create('img', {src: 'some.gif', title: 'some title'}));
+ */
+ setNode: function (elm) {
+ var self = this;
+
+ self.setContent(self.dom.getOuterHTML(elm));
+
+ return elm;
+ },
+
+ /**
+ * Returns the currently selected element or the common ancestor element for both start and end of the selection.
+ *
+ * @method getNode
+ * @return {Element} Currently selected element or common ancestor element.
+ * @example
+ * // Alerts the currently selected elements node name
+ * alert(tinymce.activeEditor.selection.getNode().nodeName);
+ */
+ getNode: function () {
+ var self = this, rng = self.getRng(), elm;
+ var startContainer, endContainer, startOffset, endOffset, root = self.dom.getRoot();
+
+ function skipEmptyTextNodes(node, forwards) {
+ var orig = node;
+
+ while (node && node.nodeType === 3 && node.length === 0) {
+ node = forwards ? node.nextSibling : node.previousSibling;
+ }
+
+ return node || orig;
+ }
+
+ // Range maybe lost after the editor is made visible again
+ if (!rng) {
+ return root;
+ }
+
+ startContainer = rng.startContainer;
+ endContainer = rng.endContainer;
+ startOffset = rng.startOffset;
+ endOffset = rng.endOffset;
+
+ if (rng.setStart) {
+ elm = rng.commonAncestorContainer;
+
+ // Handle selection a image or other control like element such as anchors
+ if (!rng.collapsed) {
+ if (startContainer == endContainer) {
+ if (endOffset - startOffset < 2) {
+ if (startContainer.hasChildNodes()) {
+ elm = startContainer.childNodes[startOffset];
+ }
+ }
+ }
+
+ // If the anchor node is a element instead of a text node then return this element
+ //if (tinymce.isWebKit && sel.anchorNode && sel.anchorNode.nodeType == 1)
+ // return sel.anchorNode.childNodes[sel.anchorOffset];
+
+ // Handle cases where the selection is immediately wrapped around a node and return that node instead of it's parent.
+ // This happens when you double click an underlined word in FireFox.
+ if (startContainer.nodeType === 3 && endContainer.nodeType === 3) {
+ if (startContainer.length === startOffset) {
+ startContainer = skipEmptyTextNodes(startContainer.nextSibling, true);
+ } else {
+ startContainer = startContainer.parentNode;
+ }
+
+ if (endOffset === 0) {
+ endContainer = skipEmptyTextNodes(endContainer.previousSibling, false);
+ } else {
+ endContainer = endContainer.parentNode;
+ }
+
+ if (startContainer && startContainer === endContainer) {
+ return startContainer;
+ }
+ }
+ }
+
+ if (elm && elm.nodeType == 3) {
+ return elm.parentNode;
+ }
+
+ return elm;
+ }
+
+ elm = rng.item ? rng.item(0) : rng.parentElement();
+
+ // IE 7 might return elements outside the iframe
+ if (elm.ownerDocument !== self.win.document) {
+ elm = root;
+ }
+
+ return elm;
+ },
+
+ getSelectedBlocks: function (startElm, endElm) {
+ var self = this, dom = self.dom, node, root, selectedBlocks = [];
+
+ root = dom.getRoot();
+ startElm = dom.getParent(startElm || self.getStart(), dom.isBlock);
+ endElm = dom.getParent(endElm || self.getEnd(), dom.isBlock);
+
+ if (startElm && startElm != root) {
+ selectedBlocks.push(startElm);
+ }
+
+ if (startElm && endElm && startElm != endElm) {
+ node = startElm;
+
+ var walker = new TreeWalker(startElm, root);
+ while ((node = walker.next()) && node != endElm) {
+ if (dom.isBlock(node)) {
+ selectedBlocks.push(node);
+ }
+ }
+ }
+
+ if (endElm && startElm != endElm && endElm != root) {
+ selectedBlocks.push(endElm);
+ }
+
+ return selectedBlocks;
+ },
+
+ isForward: function () {
+ var dom = this.dom, sel = this.getSel(), anchorRange, focusRange;
+
+ // No support for selection direction then always return true
+ if (!sel || !sel.anchorNode || !sel.focusNode) {
+ return true;
+ }
+
+ anchorRange = dom.createRng();
+ anchorRange.setStart(sel.anchorNode, sel.anchorOffset);
+ anchorRange.collapse(true);
+
+ focusRange = dom.createRng();
+ focusRange.setStart(sel.focusNode, sel.focusOffset);
+ focusRange.collapse(true);
+
+ return anchorRange.compareBoundaryPoints(anchorRange.START_TO_START, focusRange) <= 0;
+ },
+
+ normalize: function () {
+ var self = this, rng = self.getRng();
+
+ if (Env.range && new RangeUtils(self.dom).normalize(rng)) {
+ self.setRng(rng, self.isForward());
+ }
+
+ return rng;
+ },
+
+ /**
+ * Executes callback when the current selection starts/stops matching the specified selector. The current
+ * state will be passed to the callback as it's first argument.
+ *
+ * @method selectorChanged
+ * @param {String} selector CSS selector to check for.
+ * @param {function} callback Callback with state and args when the selector is matches or not.
+ */
+ selectorChanged: function (selector, callback) {
+ var self = this, currentSelectors;
+
+ if (!self.selectorChangedData) {
+ self.selectorChangedData = {};
+ currentSelectors = {};
+
+ self.editor.on('NodeChange', function (e) {
+ var node = e.element, dom = self.dom, parents = dom.getParents(node, null, dom.getRoot()), matchedSelectors = {};
+
+ // Check for new matching selectors
+ each(self.selectorChangedData, function (callbacks, selector) {
+ each(parents, function (node) {
+ if (dom.is(node, selector)) {
+ if (!currentSelectors[selector]) {
+ // Execute callbacks
+ each(callbacks, function (callback) {
+ callback(true, { node: node, selector: selector, parents: parents });
+ });
+
+ currentSelectors[selector] = callbacks;
+ }
+
+ matchedSelectors[selector] = callbacks;
+ return false;
+ }
+ });
+ });
+
+ // Check if current selectors still match
+ each(currentSelectors, function (callbacks, selector) {
+ if (!matchedSelectors[selector]) {
+ delete currentSelectors[selector];
+
+ each(callbacks, function (callback) {
+ callback(false, { node: node, selector: selector, parents: parents });
+ });
+ }
+ });
+ });
+ }
+
+ // Add selector listeners
+ if (!self.selectorChangedData[selector]) {
+ self.selectorChangedData[selector] = [];
+ }
+
+ self.selectorChangedData[selector].push(callback);
+
+ return self;
+ },
+
+ getScrollContainer: function () {
+ var scrollContainer, node = this.dom.getRoot();
+
+ while (node && node.nodeName != 'BODY') {
+ if (node.scrollHeight > node.clientHeight) {
+ scrollContainer = node;
+ break;
+ }
+
+ node = node.parentNode;
+ }
+
+ return scrollContainer;
+ },
+
+ scrollIntoView: function (elm, alignToTop) {
+ ScrollIntoView.scrollIntoView(this.editor, elm, alignToTop);
+ },
+
+ placeCaretAt: function (clientX, clientY) {
+ this.setRng(RangeUtils.getCaretRangeFromPoint(clientX, clientY, this.editor.getDoc()));
+ },
+
+ _moveEndPoint: function (rng, node, start) {
+ var root = node, walker = new TreeWalker(node, root);
+ var nonEmptyElementsMap = this.dom.schema.getNonEmptyElements();
+
+ do {
+ // Text node
+ if (node.nodeType == 3 && trim(node.nodeValue).length !== 0) {
+ if (start) {
+ rng.setStart(node, 0);
+ } else {
+ rng.setEnd(node, node.nodeValue.length);
+ }
+
+ return;
+ }
+
+ // BR/IMG/INPUT elements but not table cells
+ if (nonEmptyElementsMap[node.nodeName] && !/^(TD|TH)$/.test(node.nodeName)) {
+ if (start) {
+ rng.setStartBefore(node);
+ } else {
+ if (node.nodeName == 'BR') {
+ rng.setEndBefore(node);
+ } else {
+ rng.setEndAfter(node);
+ }
+ }
+
+ return;
+ }
+
+ // Found empty text block old IE can place the selection inside those
+ if (Env.ie && Env.ie < 11 && this.dom.isBlock(node) && this.dom.isEmpty(node)) {
+ if (start) {
+ rng.setStart(node, 0);
+ } else {
+ rng.setEnd(node, 0);
+ }
+
+ return;
+ }
+ } while ((node = (start ? walker.next() : walker.prev())));
+
+ // Failed to find any text node or other suitable location then move to the root of body
+ if (root.nodeName == 'BODY') {
+ if (start) {
+ rng.setStart(root, 0);
+ } else {
+ rng.setEnd(root, root.childNodes.length);
+ }
+ }
+ },
+
+ getBoundingClientRect: function () {
+ var rng = this.getRng();
+ return rng.collapsed ? CaretPosition.fromRangeStart(rng).getClientRects()[0] : rng.getBoundingClientRect();
+ },
+
+ destroy: function () {
+ this.win = null;
+ this.controlSelection.destroy();
+ }
+ };
+
+ return Selection;
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * ElementUtils.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -18675,116 +19679,118 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.dom.ElementUtils
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/dom/ElementUtils", [
- "tinymce/dom/BookmarkManager",
- "tinymce/util/Tools"
-], function(BookmarkManager, Tools) {
- var each = Tools.each;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.ElementUtils',
+ [
+ "tinymce.core.dom.BookmarkManager",
+ "tinymce.core.util.Tools"
+ ],
+ function (BookmarkManager, Tools) {
+ var each = Tools.each;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function ElementUtils(dom) {
- /**
- * Compares two nodes and checks if it's attributes and styles matches.
- * This doesn't compare classes as items since their order is significant.
- *
- * @method compare
- * @param {Node} node1 First node to compare with.
- * @param {Node} node2 Second node to compare with.
- * @return {boolean} True/false if the nodes are the same or not.
- */
- this.compare = function(node1, node2) {
- // Not the same name
- if (node1.nodeName != node2.nodeName) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function ElementUtils(dom) {
+ /**
+ * Compares two nodes and checks if it's attributes and styles matches.
+ * This doesn't compare classes as items since their order is significant.
+ *
+ * @method compare
+ * @param {Node} node1 First node to compare with.
+ * @param {Node} node2 Second node to compare with.
+ * @return {boolean} True/false if the nodes are the same or not.
+ */
+ this.compare = function (node1, node2) {
+ // Not the same name
+ if (node1.nodeName != node2.nodeName) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns all the nodes attributes excluding internal ones, styles and classes.
- *
- * @private
- * @param {Node} node Node to get attributes from.
- * @return {Object} Name/value object with attributes and attribute values.
- */
- function getAttribs(node) {
- var attribs = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns all the nodes attributes excluding internal ones, styles and classes.
+ *
+ * @private
+ * @param {Node} node Node to get attributes from.
+ * @return {Object} Name/value object with attributes and attribute values.
+ */
+ function getAttribs(node) {
+ var attribs = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(dom.getAttribs(node), function(attr) {
- var name = attr.nodeName.toLowerCase();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(dom.getAttribs(node), function (attr) {
+ var name = attr.nodeName.toLowerCase();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Don't compare internal attributes or style
- if (name.indexOf('_') !== 0 && name !== 'style' && name.indexOf('data-') !== 0) {
- attribs[name] = dom.getAttrib(node, name);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't compare internal attributes or style
+ if (name.indexOf('_') !== 0 && name !== 'style' && name.indexOf('data-') !== 0) {
+ attribs[name] = dom.getAttrib(node, name);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return attribs;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return attribs;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Compares two objects checks if it's key + value exists in the other one.
- *
- * @private
- * @param {Object} obj1 First object to compare.
- * @param {Object} obj2 Second object to compare.
- * @return {boolean} True/false if the objects matches or not.
- */
- function compareObjects(obj1, obj2) {
- var value, name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Compares two objects checks if it's key + value exists in the other one.
+ *
+ * @private
+ * @param {Object} obj1 First object to compare.
+ * @param {Object} obj2 Second object to compare.
+ * @return {boolean} True/false if the objects matches or not.
+ */
+ function compareObjects(obj1, obj2) {
+ var value, name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (name in obj1) {
- // Obj1 has item obj2 doesn't have
- if (obj1.hasOwnProperty(name)) {
- value = obj2[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (name in obj1) {
+ // Obj1 has item obj2 doesn't have
+ if (obj1.hasOwnProperty(name)) {
+ value = obj2[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Obj2 doesn't have obj1 item
- if (typeof value == "undefined") {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Obj2 doesn't have obj1 item
+ if (typeof value == "undefined") {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Obj2 item has a different value
- if (obj1[name] != value) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Obj2 item has a different value
+ if (obj1[name] != value) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Delete similar value
- delete obj2[name];
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Delete similar value
+ delete obj2[name];
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if obj 2 has something obj 1 doesn't have
- for (name in obj2) {
- // Obj2 has item obj1 doesn't have
- if (obj2.hasOwnProperty(name)) {
- return false;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if obj 2 has something obj 1 doesn't have
+ for (name in obj2) {
+ // Obj2 has item obj1 doesn't have
+ if (obj2.hasOwnProperty(name)) {
+ return false;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Attribs are not the same
- if (!compareObjects(getAttribs(node1), getAttribs(node2))) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Attribs are not the same
+ if (!compareObjects(getAttribs(node1), getAttribs(node2))) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Styles are not the same
- if (!compareObjects(dom.parseStyle(dom.getAttrib(node1, 'style')), dom.parseStyle(dom.getAttrib(node2, 'style')))) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Styles are not the same
+ if (!compareObjects(dom.parseStyle(dom.getAttrib(node1, 'style')), dom.parseStyle(dom.getAttrib(node2, 'style')))) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return !BookmarkManager.isBookmarkNode(node1) && !BookmarkManager.isBookmarkNode(node2);
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return !BookmarkManager.isBookmarkNode(node1) && !BookmarkManager.isBookmarkNode(node2);
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return ElementUtils;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return ElementUtils;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/fmt/Preview.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Preview.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -18799,338 +19805,340 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.fmt.Preview
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/fmt/Preview", [
- "tinymce/dom/DOMUtils",
- "tinymce/util/Tools",
- "tinymce/html/Schema"
-], function(DOMUtils, Tools, Schema) {
- var each = Tools.each;
- var dom = DOMUtils.DOM;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.fmt.Preview',
+ [
+ "tinymce.core.dom.DOMUtils",
+ "tinymce.core.util.Tools",
+ "tinymce.core.html.Schema"
+ ],
+ function (DOMUtils, Tools, Schema) {
+ var each = Tools.each;
+ var dom = DOMUtils.DOM;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function parsedSelectorToHtml(ancestry, editor) {
- var elm, item, fragment;
- var schema = editor && editor.schema || new Schema({});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function parsedSelectorToHtml(ancestry, editor) {
+ var elm, item, fragment;
+ var schema = editor && editor.schema || new Schema({});
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function decorate(elm, item) {
- if (item.classes.length) {
- dom.addClass(elm, item.classes.join(' '));
- }
- dom.setAttribs(elm, item.attrs);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function decorate(elm, item) {
+ if (item.classes.length) {
+ dom.addClass(elm, item.classes.join(' '));
+ }
+ dom.setAttribs(elm, item.attrs);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function createElement(sItem) {
- var elm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function createElement(sItem) {
+ var elm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- item = typeof sItem === 'string' ? {
- name: sItem,
- classes: [],
- attrs: {}
- } : sItem;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ item = typeof sItem === 'string' ? {
+ name: sItem,
+ classes: [],
+ attrs: {}
+ } : sItem;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elm = dom.create(item.name);
- decorate(elm, item);
- return elm;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elm = dom.create(item.name);
+ decorate(elm, item);
+ return elm;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getRequiredParent(elm, candidate) {
- var name = typeof elm !== 'string' ? elm.nodeName.toLowerCase() : elm;
- var elmRule = schema.getElementRule(name);
- var parentsRequired = elmRule.parentsRequired;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getRequiredParent(elm, candidate) {
+ var name = typeof elm !== 'string' ? elm.nodeName.toLowerCase() : elm;
+ var elmRule = schema.getElementRule(name);
+ var parentsRequired = elmRule.parentsRequired;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (parentsRequired && parentsRequired.length) {
- return candidate && Tools.inArray(parentsRequired, candidate) !== -1 ? candidate : parentsRequired[0];
- } else {
- return false;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parentsRequired && parentsRequired.length) {
+ return candidate && Tools.inArray(parentsRequired, candidate) !== -1 ? candidate : parentsRequired[0];
+ } else {
+ return false;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function wrapInHtml(elm, ancestry, siblings) {
- var parent, parentCandidate, parentRequired;
- var ancestor = ancestry.length && ancestry[0];
- var ancestorName = ancestor && ancestor.name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function wrapInHtml(elm, ancestry, siblings) {
+ var parent, parentCandidate, parentRequired;
+ var ancestor = ancestry.length && ancestry[0];
+ var ancestorName = ancestor && ancestor.name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parentRequired = getRequiredParent(elm, ancestorName);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parentRequired = getRequiredParent(elm, ancestorName);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (parentRequired) {
- if (ancestorName == parentRequired) {
- parentCandidate = ancestry[0];
- ancestry = ancestry.slice(1);
- } else {
- parentCandidate = parentRequired;
- }
- } else if (ancestor) {
- parentCandidate = ancestry[0];
- ancestry = ancestry.slice(1);
- } else if (!siblings) {
- return elm;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parentRequired) {
+ if (ancestorName == parentRequired) {
+ parentCandidate = ancestry[0];
+ ancestry = ancestry.slice(1);
+ } else {
+ parentCandidate = parentRequired;
+ }
+ } else if (ancestor) {
+ parentCandidate = ancestry[0];
+ ancestry = ancestry.slice(1);
+ } else if (!siblings) {
+ return elm;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (parentCandidate) {
- parent = createElement(parentCandidate);
- parent.appendChild(elm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parentCandidate) {
+ parent = createElement(parentCandidate);
+ parent.appendChild(elm);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (siblings) {
- if (!parent) {
- // if no more ancestry, wrap in generic div
- parent = dom.create('div');
- parent.appendChild(elm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (siblings) {
+ if (!parent) {
+ // if no more ancestry, wrap in generic div
+ parent = dom.create('div');
+ parent.appendChild(elm);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(siblings, function(sibling) {
- var siblingElm = createElement(sibling);
- parent.insertBefore(siblingElm, elm);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(siblings, function (sibling) {
+ var siblingElm = createElement(sibling);
+ parent.insertBefore(siblingElm, elm);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return wrapInHtml(parent, ancestry, parentCandidate && parentCandidate.siblings);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return wrapInHtml(parent, ancestry, parentCandidate && parentCandidate.siblings);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (ancestry && ancestry.length) {
- item = ancestry[0];
- elm = createElement(item);
- fragment = dom.create('div');
- fragment.appendChild(wrapInHtml(elm, ancestry.slice(1), item.siblings));
- return fragment;
- } else {
- return '';
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (ancestry && ancestry.length) {
+ item = ancestry[0];
+ elm = createElement(item);
+ fragment = dom.create('div');
+ fragment.appendChild(wrapInHtml(elm, ancestry.slice(1), item.siblings));
+ return fragment;
+ } else {
+ return '';
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function selectorToHtml(selector, editor) {
- return parsedSelectorToHtml(parseSelector(selector), editor);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function selectorToHtml(selector, editor) {
+ return parsedSelectorToHtml(parseSelector(selector), editor);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function parseSelectorItem(item) {
- var tagName;
- var obj = {
- classes: [],
- attrs: {}
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function parseSelectorItem(item) {
+ var tagName;
+ var obj = {
+ classes: [],
+ attrs: {}
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- item = obj.selector = Tools.trim(item);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ item = obj.selector = Tools.trim(item);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (item !== '*') {
- // matching IDs, CLASSes, ATTRIBUTES and PSEUDOs
- tagName = item.replace(/(?:([#\.]|::?)([\w\-]+)|(\[)([^\]]+)\]?)/g, function($0, $1, $2, $3, $4) {
- switch ($1) {
- case '#':
- obj.attrs.id = $2;
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (item !== '*') {
+ // matching IDs, CLASSes, ATTRIBUTES and PSEUDOs
+ tagName = item.replace(/(?:([#\.]|::?)([\w\-]+)|(\[)([^\]]+)\]?)/g, function ($0, $1, $2, $3, $4) {
+ switch ($1) {
+ case '#':
+ obj.attrs.id = $2;
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case '.':
- obj.classes.push($2);
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case '.':
+ obj.classes.push($2);
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case ':':
- if (Tools.inArray('checked disabled enabled read-only required'.split(' '), $2) !== -1) {
- obj.attrs[$2] = $2;
- }
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case ':':
+ if (Tools.inArray('checked disabled enabled read-only required'.split(' '), $2) !== -1) {
+ obj.attrs[$2] = $2;
+ }
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // atribute matched
- if ($3 == '[') {
- var m = $4.match(/([\w\-]+)(?:\=\"([^\"]+))?/);
- if (m) {
- obj.attrs[m[1]] = m[2];
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // atribute matched
+ if ($3 == '[') {
+ var m = $4.match(/([\w\-]+)(?:\=\"([^\"]+))?/);
+ if (m) {
+ obj.attrs[m[1]] = m[2];
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return '';
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return '';
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- obj.name = tagName || 'div';
- return obj;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ obj.name = tagName || 'div';
+ return obj;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function parseSelector(selector) {
- if (!selector || typeof selector !== 'string') {
- return [];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function parseSelector(selector) {
+ if (!selector || typeof selector !== 'string') {
+ return [];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // take into account only first one
- selector = selector.split(/\s*,\s*/)[0];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // take into account only first one
+ selector = selector.split(/\s*,\s*/)[0];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // tighten
- selector = selector.replace(/\s*(~\+|~|\+|>)\s*/g, '$1');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // tighten
+ selector = selector.replace(/\s*(~\+|~|\+|>)\s*/g, '$1');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // split either on > or on space, but not the one inside brackets
- return Tools.map(selector.split(/(?:>|\s+(?![^\[\]]+\]))/), function(item) {
- // process each sibling selector separately
- var siblings = Tools.map(item.split(/(?:~\+|~|\+)/), parseSelectorItem);
- var obj = siblings.pop(); // the last one is our real target
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // split either on > or on space, but not the one inside brackets
+ return Tools.map(selector.split(/(?:>|\s+(?![^\[\]]+\]))/), function (item) {
+ // process each sibling selector separately
+ var siblings = Tools.map(item.split(/(?:~\+|~|\+)/), parseSelectorItem);
+ var obj = siblings.pop(); // the last one is our real target
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (siblings.length) {
- obj.siblings = siblings;
- }
- return obj;
- }).reverse();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (siblings.length) {
+ obj.siblings = siblings;
+ }
+ return obj;
+ }).reverse();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getCssText(editor, format) {
- var name, previewFrag, previewElm, items;
- var previewCss = '', parentFontSize, previewStyles;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getCssText(editor, format) {
+ var name, previewFrag, previewElm, items;
+ var previewCss = '', parentFontSize, previewStyles;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- previewStyles = editor.settings.preview_styles;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ previewStyles = editor.settings.preview_styles;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // No preview forced
- if (previewStyles === false) {
- return '';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // No preview forced
+ if (previewStyles === false) {
+ return '';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Default preview
- if (typeof previewStyles !== 'string') {
- previewStyles = 'font-family font-size font-weight font-style text-decoration ' +
- 'text-transform color background-color border border-radius outline text-shadow';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Default preview
+ if (typeof previewStyles !== 'string') {
+ previewStyles = 'font-family font-size font-weight font-style text-decoration ' +
+ 'text-transform color background-color border border-radius outline text-shadow';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Removes any variables since these can't be previewed
- function removeVars(val) {
- return val.replace(/%(\w+)/g, '');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Removes any variables since these can't be previewed
+ function removeVars(val) {
+ return val.replace(/%(\w+)/g, '');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Create block/inline element to use for preview
- if (typeof format == "string") {
- format = editor.formatter.get(format);
- if (!format) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Create block/inline element to use for preview
+ if (typeof format == "string") {
+ format = editor.formatter.get(format);
+ if (!format) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- format = format[0];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ format = format[0];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Format specific preview override
- // TODO: This should probably be further reduced by the previewStyles option
- if ('preview' in format) {
- previewStyles = format.preview;
- if (previewStyles === false) {
- return '';
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Format specific preview override
+ // TODO: This should probably be further reduced by the previewStyles option
+ if ('preview' in format) {
+ previewStyles = format.preview;
+ if (previewStyles === false) {
+ return '';
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- name = format.block || format.inline || 'span';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ name = format.block || format.inline || 'span';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- items = parseSelector(format.selector);
- if (items.length) {
- if (!items[0].name) { // e.g. something like ul > .someClass was provided
- items[0].name = name;
- }
- name = format.selector;
- previewFrag = parsedSelectorToHtml(items, editor);
- } else {
- previewFrag = parsedSelectorToHtml([name], editor);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ items = parseSelector(format.selector);
+ if (items.length) {
+ if (!items[0].name) { // e.g. something like ul > .someClass was provided
+ items[0].name = name;
+ }
+ name = format.selector;
+ previewFrag = parsedSelectorToHtml(items, editor);
+ } else {
+ previewFrag = parsedSelectorToHtml([name], editor);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- previewElm = dom.select(name, previewFrag)[0] || previewFrag.firstChild;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ previewElm = dom.select(name, previewFrag)[0] || previewFrag.firstChild;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add format styles to preview element
- each(format.styles, function(value, name) {
- value = removeVars(value);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add format styles to preview element
+ each(format.styles, function (value, name) {
+ value = removeVars(value);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value) {
- dom.setStyle(previewElm, name, value);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value) {
+ dom.setStyle(previewElm, name, value);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add attributes to preview element
- each(format.attributes, function(value, name) {
- value = removeVars(value);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add attributes to preview element
+ each(format.attributes, function (value, name) {
+ value = removeVars(value);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value) {
- dom.setAttrib(previewElm, name, value);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value) {
+ dom.setAttrib(previewElm, name, value);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add classes to preview element
- each(format.classes, function(value) {
- value = removeVars(value);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add classes to preview element
+ each(format.classes, function (value) {
+ value = removeVars(value);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!dom.hasClass(previewElm, value)) {
- dom.addClass(previewElm, value);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!dom.hasClass(previewElm, value)) {
+ dom.addClass(previewElm, value);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.fire('PreviewFormats');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.fire('PreviewFormats');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add the previewElm outside the visual area
- dom.setStyles(previewFrag, {position: 'absolute', left: -0xFFFF});
- editor.getBody().appendChild(previewFrag);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add the previewElm outside the visual area
+ dom.setStyles(previewFrag, { position: 'absolute', left: -0xFFFF });
+ editor.getBody().appendChild(previewFrag);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Get parent container font size so we can compute px values out of em/% for older IE:s
- parentFontSize = dom.getStyle(editor.getBody(), 'fontSize', true);
- parentFontSize = /px$/.test(parentFontSize) ? parseInt(parentFontSize, 10) : 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get parent container font size so we can compute px values out of em/% for older IE:s
+ parentFontSize = dom.getStyle(editor.getBody(), 'fontSize', true);
+ parentFontSize = /px$/.test(parentFontSize) ? parseInt(parentFontSize, 10) : 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(previewStyles.split(' '), function(name) {
- var value = dom.getStyle(previewElm, name, true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(previewStyles.split(' '), function (name) {
+ var value = dom.getStyle(previewElm, name, true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If background is transparent then check if the body has a background color we can use
- if (name == 'background-color' && /transparent|rgba\s*\([^)]+,\s*0\)/.test(value)) {
- value = dom.getStyle(editor.getBody(), name, true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If background is transparent then check if the body has a background color we can use
+ if (name == 'background-color' && /transparent|rgba\s*\([^)]+,\s*0\)/.test(value)) {
+ value = dom.getStyle(editor.getBody(), name, true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Ignore white since it's the default color, not the nicest fix
- // TODO: Fix this by detecting runtime style
- if (dom.toHex(value).toLowerCase() == '#ffffff') {
- return;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Ignore white since it's the default color, not the nicest fix
+ // TODO: Fix this by detecting runtime style
+ if (dom.toHex(value).toLowerCase() == '#ffffff') {
+ return;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name == 'color') {
- // Ignore black since it's the default color, not the nicest fix
- // TODO: Fix this by detecting runtime style
- if (dom.toHex(value).toLowerCase() == '#000000') {
- return;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name == 'color') {
+ // Ignore black since it's the default color, not the nicest fix
+ // TODO: Fix this by detecting runtime style
+ if (dom.toHex(value).toLowerCase() == '#000000') {
+ return;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Old IE won't calculate the font size so we need to do that manually
- if (name == 'font-size') {
- if (/em|%$/.test(value)) {
- if (parentFontSize === 0) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Old IE won't calculate the font size so we need to do that manually
+ if (name == 'font-size') {
+ if (/em|%$/.test(value)) {
+ if (parentFontSize === 0) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Convert font size from em/% to px
- value = parseFloat(value, 10) / (/%$/.test(value) ? 100 : 1);
- value = (value * parentFontSize) + 'px';
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Convert font size from em/% to px
+ value = parseFloat(value, 10) / (/%$/.test(value) ? 100 : 1);
+ value = (value * parentFontSize) + 'px';
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name == "border" && value) {
- previewCss += 'padding:0 2px;';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name == "border" && value) {
+ previewCss += 'padding:0 2px;';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- previewCss += name + ':' + value + ';';
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ previewCss += name + ':' + value + ';';
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.fire('AfterPreviewFormats');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.fire('AfterPreviewFormats');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- //previewCss += 'line-height:normal';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ //previewCss += 'line-height:normal';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.remove(previewFrag);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.remove(previewFrag);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return previewCss;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return previewCss;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- getCssText: getCssText,
- parseSelector: parseSelector,
- selectorToHtml: selectorToHtml
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ getCssText: getCssText,
+ parseSelector: parseSelector,
+ selectorToHtml: selectorToHtml
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/fmt/Hooks.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Hooks.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -19142,64 +20150,66 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.fmt.Hooks
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/fmt/Hooks", [
- "tinymce/util/Arr",
- "tinymce/dom/NodeType",
- "tinymce/dom/DomQuery"
-], function(Arr, NodeType, $) {
- var postProcessHooks = {}, filter = Arr.filter, each = Arr.each;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.fmt.Hooks',
+ [
+ "tinymce.core.util.Arr",
+ "tinymce.core.dom.NodeType",
+ "tinymce.core.dom.DomQuery"
+ ],
+ function (Arr, NodeType, $) {
+ var postProcessHooks = {}, filter = Arr.filter, each = Arr.each;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function addPostProcessHook(name, hook) {
- var hooks = postProcessHooks[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function addPostProcessHook(name, hook) {
+ var hooks = postProcessHooks[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!hooks) {
- postProcessHooks[name] = hooks = [];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!hooks) {
+ postProcessHooks[name] = hooks = [];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- postProcessHooks[name].push(hook);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ postProcessHooks[name].push(hook);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function postProcess(name, editor) {
- each(postProcessHooks[name], function(hook) {
- hook(editor);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function postProcess(name, editor) {
+ each(postProcessHooks[name], function (hook) {
+ hook(editor);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- addPostProcessHook("pre", function(editor) {
- var rng = editor.selection.getRng(), isPre, blocks;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ addPostProcessHook("pre", function (editor) {
+ var rng = editor.selection.getRng(), isPre, blocks;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hasPreSibling(pre) {
- return isPre(pre.previousSibling) && Arr.indexOf(blocks, pre.previousSibling) != -1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hasPreSibling(pre) {
+ return isPre(pre.previousSibling) && Arr.indexOf(blocks, pre.previousSibling) != -1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function joinPre(pre1, pre2) {
- $(pre2).remove();
- $(pre1).append('<br><br>').append(pre2.childNodes);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function joinPre(pre1, pre2) {
+ $(pre2).remove();
+ $(pre1).append('<br><br>').append(pre2.childNodes);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- isPre = NodeType.matchNodeNames('pre');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ isPre = NodeType.matchNodeNames('pre');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!rng.collapsed) {
- blocks = editor.selection.getSelectedBlocks();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!rng.collapsed) {
+ blocks = editor.selection.getSelectedBlocks();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(filter(filter(blocks, isPre), hasPreSibling), function(pre) {
- joinPre(pre.previousSibling, pre);
- });
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(filter(filter(blocks, isPre), hasPreSibling), function (pre) {
+ joinPre(pre.previousSibling, pre);
+ });
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- postProcess: postProcess
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ postProcess: postProcess
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/Formatter.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Formatter.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -19219,2559 +20229,2563 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * tinymce.activeEditor.formatter.apply('mycustomformat');
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/Formatter", [
- "tinymce/dom/TreeWalker",
- "tinymce/dom/RangeUtils",
- "tinymce/dom/BookmarkManager",
- "tinymce/dom/ElementUtils",
- "tinymce/util/Fun",
- "tinymce/util/Tools",
- "tinymce/fmt/Preview",
- "tinymce/fmt/Hooks"
-], function(TreeWalker, RangeUtils, BookmarkManager, ElementUtils, Fun, Tools, Preview, Hooks) {
- /**
- * Constructs a new formatter instance.
- *
- * @constructor Formatter
- * @param {tinymce.Editor} ed Editor instance to construct the formatter engine to.
- */
- return function(ed) {
- var formats = {},
- dom = ed.dom,
- selection = ed.selection,
- rangeUtils = new RangeUtils(dom),
- isValid = ed.schema.isValidChild,
- isBlock = dom.isBlock,
- forcedRootBlock = ed.settings.forced_root_block,
- nodeIndex = dom.nodeIndex,
- INVISIBLE_CHAR = '\uFEFF',
- MCE_ATTR_RE = /^(src|href|style)$/,
- FALSE = false,
- TRUE = true,
- formatChangeData,
- undef,
- getContentEditable = dom.getContentEditable,
- disableCaretContainer,
- markCaretContainersBogus,
- isBookmarkNode = BookmarkManager.isBookmarkNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.Formatter',
+ [
+ "tinymce.core.dom.TreeWalker",
+ "tinymce.core.dom.RangeUtils",
+ "tinymce.core.dom.BookmarkManager",
+ "tinymce.core.dom.ElementUtils",
+ "tinymce.core.dom.NodeType",
+ "tinymce.core.util.Fun",
+ "tinymce.core.util.Tools",
+ "tinymce.core.fmt.Preview",
+ "tinymce.core.fmt.Hooks"
+ ],
+ function (TreeWalker, RangeUtils, BookmarkManager, ElementUtils, NodeType, Fun, Tools, Preview, Hooks) {
+ /**
+ * Constructs a new formatter instance.
+ *
+ * @constructor Formatter
+ * @param {tinymce.Editor} ed Editor instance to construct the formatter engine to.
+ */
+ return function (ed) {
+ var formats = {},
+ dom = ed.dom,
+ selection = ed.selection,
+ rangeUtils = new RangeUtils(dom),
+ isValid = ed.schema.isValidChild,
+ isBlock = dom.isBlock,
+ forcedRootBlock = ed.settings.forced_root_block,
+ nodeIndex = dom.nodeIndex,
+ INVISIBLE_CHAR = '\uFEFF',
+ MCE_ATTR_RE = /^(src|href|style)$/,
+ FALSE = false,
+ TRUE = true,
+ formatChangeData,
+ undef,
+ getContentEditable = dom.getContentEditable,
+ disableCaretContainer,
+ markCaretContainersBogus,
+ isBookmarkNode = BookmarkManager.isBookmarkNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var each = Tools.each,
- grep = Tools.grep,
- walk = Tools.walk,
- extend = Tools.extend;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var each = Tools.each,
+ grep = Tools.grep,
+ walk = Tools.walk,
+ extend = Tools.extend;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isTextBlock(name) {
- if (name.nodeType) {
- name = name.nodeName;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isTextBlock(name) {
+ if (name.nodeType) {
+ name = name.nodeName;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return !!ed.schema.getTextBlockElements()[name.toLowerCase()];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return !!ed.schema.getTextBlockElements()[name.toLowerCase()];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isTableCell(node) {
- return /^(TH|TD)$/.test(node.nodeName);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isTableCell(node) {
+ return /^(TH|TD)$/.test(node.nodeName);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isInlineBlock(node) {
- return node && /^(IMG)$/.test(node.nodeName);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isInlineBlock(node) {
+ return node && /^(IMG)$/.test(node.nodeName);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getParents(node, selector) {
- return dom.getParents(node, selector, dom.getRoot());
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getParents(node, selector) {
+ return dom.getParents(node, selector, dom.getRoot());
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isCaretNode(node) {
- return node.nodeType === 1 && node.id === '_mce_caret';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isCaretNode(node) {
+ return node.nodeType === 1 && node.id === '_mce_caret';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function defaultFormats() {
- register({
- valigntop: [
- {selector: 'td,th', styles: {'verticalAlign': 'top'}}
- ],
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function defaultFormats() {
+ register({
+ valigntop: [
+ { selector: 'td,th', styles: { 'verticalAlign': 'top' } }
+ ],
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- valignmiddle: [
- {selector: 'td,th', styles: {'verticalAlign': 'middle'}}
- ],
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ valignmiddle: [
+ { selector: 'td,th', styles: { 'verticalAlign': 'middle' } }
+ ],
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- valignbottom: [
- {selector: 'td,th', styles: {'verticalAlign': 'bottom'}}
- ],
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ valignbottom: [
+ { selector: 'td,th', styles: { 'verticalAlign': 'bottom' } }
+ ],
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- alignleft: [
- {
- selector: 'figure.image',
- collapsed: false,
- classes: 'align-left',
- ceFalseOverride: true,
- preview: 'font-family font-size'
- },
- {
- selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li',
- styles: {
- textAlign: 'left'
- },
- inherit: false,
- preview: false,
- defaultBlock: 'div'
- },
- {selector: 'img,table', collapsed: false, styles: {'float': 'left'}, preview: 'font-family font-size'}
- ],
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ alignleft: [
+ {
+ selector: 'figure.image',
+ collapsed: false,
+ classes: 'align-left',
+ ceFalseOverride: true,
+ preview: 'font-family font-size'
+ },
+ {
+ selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li',
+ styles: {
+ textAlign: 'left'
+ },
+ inherit: false,
+ preview: false,
+ defaultBlock: 'div'
+ },
+ { selector: 'img,table', collapsed: false, styles: { 'float': 'left' }, preview: 'font-family font-size' }
+ ],
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- aligncenter: [
- {
- selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li',
- styles: {
- textAlign: 'center'
- },
- inherit: false,
- preview: false,
- defaultBlock: 'div'
- },
- {
- selector: 'figure.image',
- collapsed: false,
- classes: 'align-center',
- ceFalseOverride: true,
- preview: 'font-family font-size'
- },
- {
- selector: 'img',
- collapsed: false,
- styles: {
- display: 'block',
- marginLeft: 'auto',
- marginRight: 'auto'
- },
- preview: false
- },
- {
- selector: 'table',
- collapsed: false,
- styles: {
- marginLeft: 'auto',
- marginRight: 'auto'
- },
- preview: 'font-family font-size'
- }
- ],
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ aligncenter: [
+ {
+ selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li',
+ styles: {
+ textAlign: 'center'
+ },
+ inherit: false,
+ preview: false,
+ defaultBlock: 'div'
+ },
+ {
+ selector: 'figure.image',
+ collapsed: false,
+ classes: 'align-center',
+ ceFalseOverride: true,
+ preview: 'font-family font-size'
+ },
+ {
+ selector: 'img',
+ collapsed: false,
+ styles: {
+ display: 'block',
+ marginLeft: 'auto',
+ marginRight: 'auto'
+ },
+ preview: false
+ },
+ {
+ selector: 'table',
+ collapsed: false,
+ styles: {
+ marginLeft: 'auto',
+ marginRight: 'auto'
+ },
+ preview: 'font-family font-size'
+ }
+ ],
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- alignright: [
- {
- selector: 'figure.image',
- collapsed: false,
- classes: 'align-right',
- ceFalseOverride: true,
- preview: 'font-family font-size'
- },
- {
- selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li',
- styles: {
- textAlign: 'right'
- },
- inherit: false,
- preview: 'font-family font-size',
- defaultBlock: 'div'
- },
- {
- selector: 'img,table',
- collapsed: false,
- styles: {
- 'float': 'right'
- },
- preview: 'font-family font-size'
- }
- ],
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ alignright: [
+ {
+ selector: 'figure.image',
+ collapsed: false,
+ classes: 'align-right',
+ ceFalseOverride: true,
+ preview: 'font-family font-size'
+ },
+ {
+ selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li',
+ styles: {
+ textAlign: 'right'
+ },
+ inherit: false,
+ preview: 'font-family font-size',
+ defaultBlock: 'div'
+ },
+ {
+ selector: 'img,table',
+ collapsed: false,
+ styles: {
+ 'float': 'right'
+ },
+ preview: 'font-family font-size'
+ }
+ ],
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- alignjustify: [
- {
- selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li',
- styles: {
- textAlign: 'justify'
- },
- inherit: false,
- defaultBlock: 'div',
- preview: 'font-family font-size'
- }
- ],
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ alignjustify: [
+ {
+ selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li',
+ styles: {
+ textAlign: 'justify'
+ },
+ inherit: false,
+ defaultBlock: 'div',
+ preview: 'font-family font-size'
+ }
+ ],
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bold: [
- {inline: 'strong', remove: 'all'},
- {inline: 'span', styles: {fontWeight: 'bold'}},
- {inline: 'b', remove: 'all'}
- ],
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bold: [
+ { inline: 'strong', remove: 'all' },
+ { inline: 'span', styles: { fontWeight: 'bold' } },
+ { inline: 'b', remove: 'all' }
+ ],
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- italic: [
- {inline: 'em', remove: 'all'},
- {inline: 'span', styles: {fontStyle: 'italic'}},
- {inline: 'i', remove: 'all'}
- ],
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ italic: [
+ { inline: 'em', remove: 'all' },
+ { inline: 'span', styles: { fontStyle: 'italic' } },
+ { inline: 'i', remove: 'all' }
+ ],
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- underline: [
- {inline: 'span', styles: {textDecoration: 'underline'}, exact: true},
- {inline: 'u', remove: 'all'}
- ],
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ underline: [
+ { inline: 'span', styles: { textDecoration: 'underline' }, exact: true },
+ { inline: 'u', remove: 'all' }
+ ],
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- strikethrough: [
- {inline: 'span', styles: {textDecoration: 'line-through'}, exact: true},
- {inline: 'strike', remove: 'all'}
- ],
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ strikethrough: [
+ { inline: 'span', styles: { textDecoration: 'line-through' }, exact: true },
+ { inline: 'strike', remove: 'all' }
+ ],
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- forecolor: {inline: 'span', styles: {color: '%value'}, links: true, remove_similar: true},
- hilitecolor: {inline: 'span', styles: {backgroundColor: '%value'}, links: true, remove_similar: true},
- fontname: {inline: 'span', styles: {fontFamily: '%value'}},
- fontsize: {inline: 'span', styles: {fontSize: '%value'}},
- fontsize_class: {inline: 'span', attributes: {'class': '%value'}},
- blockquote: {block: 'blockquote', wrapper: 1, remove: 'all'},
- subscript: {inline: 'sub'},
- superscript: {inline: 'sup'},
- code: {inline: 'code'},
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ forecolor: { inline: 'span', styles: { color: '%value' }, links: true, remove_similar: true },
+ hilitecolor: { inline: 'span', styles: { backgroundColor: '%value' }, links: true, remove_similar: true },
+ fontname: { inline: 'span', styles: { fontFamily: '%value' } },
+ fontsize: { inline: 'span', styles: { fontSize: '%value' } },
+ fontsize_class: { inline: 'span', attributes: { 'class': '%value' } },
+ blockquote: { block: 'blockquote', wrapper: 1, remove: 'all' },
+ subscript: { inline: 'sub' },
+ superscript: { inline: 'sup' },
+ code: { inline: 'code' },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- link: {inline: 'a', selector: 'a', remove: 'all', split: true, deep: true,
- onmatch: function() {
- return true;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ link: {
+ inline: 'a', selector: 'a', remove: 'all', split: true, deep: true,
+ onmatch: function () {
+ return true;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- onformat: function(elm, fmt, vars) {
- each(vars, function(value, key) {
- dom.setAttrib(elm, key, value);
- });
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ onformat: function (elm, fmt, vars) {
+ each(vars, function (value, key) {
+ dom.setAttrib(elm, key, value);
+ });
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- removeformat: [
- {
- selector: 'b,strong,em,i,font,u,strike,sub,sup,dfn,code,samp,kbd,var,cite,mark,q,del,ins',
- remove: 'all',
- split: true,
- expand: false,
- block_expand: true,
- deep: true
- },
- {selector: 'span', attributes: ['style', 'class'], remove: 'empty', split: true, expand: false, deep: true},
- {selector: '*', attributes: ['style', 'class'], split: false, expand: false, deep: true}
- ]
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ removeformat: [
+ {
+ selector: 'b,strong,em,i,font,u,strike,sub,sup,dfn,code,samp,kbd,var,cite,mark,q,del,ins',
+ remove: 'all',
+ split: true,
+ expand: false,
+ block_expand: true,
+ deep: true
+ },
+ { selector: 'span', attributes: ['style', 'class'], remove: 'empty', split: true, expand: false, deep: true },
+ { selector: '*', attributes: ['style', 'class'], split: false, expand: false, deep: true }
+ ]
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Register default block formats
- each('p h1 h2 h3 h4 h5 h6 div address pre div dt dd samp'.split(/\s/), function(name) {
- register(name, {block: name, remove: 'all'});
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Register default block formats
+ each('p h1 h2 h3 h4 h5 h6 div address pre div dt dd samp'.split(/\s/), function (name) {
+ register(name, { block: name, remove: 'all' });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Register user defined formats
- register(ed.settings.formats);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Register user defined formats
+ register(ed.settings.formats);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function addKeyboardShortcuts() {
- // Add some inline shortcuts
- ed.addShortcut('meta+b', 'bold_desc', 'Bold');
- ed.addShortcut('meta+i', 'italic_desc', 'Italic');
- ed.addShortcut('meta+u', 'underline_desc', 'Underline');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function addKeyboardShortcuts() {
+ // Add some inline shortcuts
+ ed.addShortcut('meta+b', 'bold_desc', 'Bold');
+ ed.addShortcut('meta+i', 'italic_desc', 'Italic');
+ ed.addShortcut('meta+u', 'underline_desc', 'Underline');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // BlockFormat shortcuts keys
- for (var i = 1; i <= 6; i++) {
- ed.addShortcut('access+' + i, '', ['FormatBlock', false, 'h' + i]);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // BlockFormat shortcuts keys
+ for (var i = 1; i <= 6; i++) {
+ ed.addShortcut('access+' + i, '', ['FormatBlock', false, 'h' + i]);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ed.addShortcut('access+7', '', ['FormatBlock', false, 'p']);
- ed.addShortcut('access+8', '', ['FormatBlock', false, 'div']);
- ed.addShortcut('access+9', '', ['FormatBlock', false, 'address']);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ed.addShortcut('access+7', '', ['FormatBlock', false, 'p']);
+ ed.addShortcut('access+8', '', ['FormatBlock', false, 'div']);
+ ed.addShortcut('access+9', '', ['FormatBlock', false, 'address']);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Public functions
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Public functions
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the format by name or all formats if no name is specified.
- *
- * @method get
- * @param {String} name Optional name to retrieve by.
- * @return {Array/Object} Array/Object with all registered formats or a specific format.
- */
- function get(name) {
- return name ? formats[name] : formats;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the format by name or all formats if no name is specified.
+ *
+ * @method get
+ * @param {String} name Optional name to retrieve by.
+ * @return {Array/Object} Array/Object with all registered formats or a specific format.
+ */
+ function get(name) {
+ return name ? formats[name] : formats;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Registers a specific format by name.
- *
- * @method register
- * @param {Object/String} name Name of the format for example "bold".
- * @param {Object/Array} format Optional format object or array of format variants
- * can only be omitted if the first arg is an object.
- */
- function register(name, format) {
- if (name) {
- if (typeof name !== 'string') {
- each(name, function(format, name) {
- register(name, format);
- });
- } else {
- // Force format into array and add it to internal collection
- format = format.length ? format : [format];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Registers a specific format by name.
+ *
+ * @method register
+ * @param {Object/String} name Name of the format for example "bold".
+ * @param {Object/Array} format Optional format object or array of format variants
+ * can only be omitted if the first arg is an object.
+ */
+ function register(name, format) {
+ if (name) {
+ if (typeof name !== 'string') {
+ each(name, function (format, name) {
+ register(name, format);
+ });
+ } else {
+ // Force format into array and add it to internal collection
+ format = format.length ? format : [format];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(format, function(format) {
- // Set deep to false by default on selector formats this to avoid removing
- // alignment on images inside paragraphs when alignment is changed on paragraphs
- if (format.deep === undef) {
- format.deep = !format.selector;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(format, function (format) {
+ // Set deep to false by default on selector formats this to avoid removing
+ // alignment on images inside paragraphs when alignment is changed on paragraphs
+ if (format.deep === undef) {
+ format.deep = !format.selector;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Default to true
- if (format.split === undef) {
- format.split = !format.selector || format.inline;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Default to true
+ if (format.split === undef) {
+ format.split = !format.selector || format.inline;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Default to true
- if (format.remove === undef && format.selector && !format.inline) {
- format.remove = 'none';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Default to true
+ if (format.remove === undef && format.selector && !format.inline) {
+ format.remove = 'none';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Mark format as a mixed format inline + block level
- if (format.selector && format.inline) {
- format.mixed = true;
- format.block_expand = true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Mark format as a mixed format inline + block level
+ if (format.selector && format.inline) {
+ format.mixed = true;
+ format.block_expand = true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Split classes if needed
- if (typeof format.classes === 'string') {
- format.classes = format.classes.split(/\s+/);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Split classes if needed
+ if (typeof format.classes === 'string') {
+ format.classes = format.classes.split(/\s+/);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- formats[name] = format;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ formats[name] = format;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Unregister a specific format by name.
- *
- * @method unregister
- * @param {String} name Name of the format for example "bold".
- */
- function unregister(name) {
- if (name && formats[name]) {
- delete formats[name];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Unregister a specific format by name.
+ *
+ * @method unregister
+ * @param {String} name Name of the format for example "bold".
+ */
+ function unregister(name) {
+ if (name && formats[name]) {
+ delete formats[name];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return formats;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return formats;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function matchesUnInheritedFormatSelector(node, name) {
- var formatList = get(name);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function matchesUnInheritedFormatSelector(node, name) {
+ var formatList = get(name);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (formatList) {
- for (var i = 0; i < formatList.length; i++) {
- if (formatList[i].inherit === false && dom.is(node, formatList[i].selector)) {
- return true;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (formatList) {
+ for (var i = 0; i < formatList.length; i++) {
+ if (formatList[i].inherit === false && dom.is(node, formatList[i].selector)) {
+ return true;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getTextDecoration(node) {
- var decoration;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getTextDecoration(node) {
+ var decoration;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ed.dom.getParent(node, function(n) {
- decoration = ed.dom.getStyle(n, 'text-decoration');
- return decoration && decoration !== 'none';
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ed.dom.getParent(node, function (n) {
+ decoration = ed.dom.getStyle(n, 'text-decoration');
+ return decoration && decoration !== 'none';
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return decoration;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return decoration;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function processUnderlineAndColor(node) {
- var textDecoration;
- if (node.nodeType === 1 && node.parentNode && node.parentNode.nodeType === 1) {
- textDecoration = getTextDecoration(node.parentNode);
- if (ed.dom.getStyle(node, 'color') && textDecoration) {
- ed.dom.setStyle(node, 'text-decoration', textDecoration);
- } else if (ed.dom.getStyle(node, 'text-decoration') === textDecoration) {
- ed.dom.setStyle(node, 'text-decoration', null);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function processUnderlineAndColor(node) {
+ var textDecoration;
+ if (node.nodeType === 1 && node.parentNode && node.parentNode.nodeType === 1) {
+ textDecoration = getTextDecoration(node.parentNode);
+ if (ed.dom.getStyle(node, 'color') && textDecoration) {
+ ed.dom.setStyle(node, 'text-decoration', textDecoration);
+ } else if (ed.dom.getStyle(node, 'text-decoration') === textDecoration) {
+ ed.dom.setStyle(node, 'text-decoration', null);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Applies the specified format to the current selection or specified node.
- *
- * @method apply
- * @param {String} name Name of format to apply.
- * @param {Object} vars Optional list of variables to replace within format before applying it.
- * @param {Node} node Optional node to apply the format to defaults to current selection.
- */
- function apply(name, vars, node) {
- var formatList = get(name), format = formatList[0], bookmark, rng, isCollapsed = !node && selection.isCollapsed();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Applies the specified format to the current selection or specified node.
+ *
+ * @method apply
+ * @param {String} name Name of format to apply.
+ * @param {Object} vars Optional list of variables to replace within format before applying it.
+ * @param {Node} node Optional node to apply the format to defaults to current selection.
+ */
+ function apply(name, vars, node) {
+ var formatList = get(name), format = formatList[0], bookmark, rng, isCollapsed = !node && selection.isCollapsed();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setElementFormat(elm, fmt) {
- fmt = fmt || format;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setElementFormat(elm, fmt) {
+ fmt = fmt || format;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elm) {
- if (fmt.onformat) {
- fmt.onformat(elm, fmt, vars, node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (elm) {
+ if (fmt.onformat) {
+ fmt.onformat(elm, fmt, vars, node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(fmt.styles, function(value, name) {
- dom.setStyle(elm, name, replaceVars(value, vars));
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(fmt.styles, function (value, name) {
+ dom.setStyle(elm, name, replaceVars(value, vars));
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Needed for the WebKit span spam bug
- // TODO: Remove this once WebKit/Blink fixes this
- if (fmt.styles) {
- var styleVal = dom.getAttrib(elm, 'style');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Needed for the WebKit span spam bug
+ // TODO: Remove this once WebKit/Blink fixes this
+ if (fmt.styles) {
+ var styleVal = dom.getAttrib(elm, 'style');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (styleVal) {
- elm.setAttribute('data-mce-style', styleVal);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (styleVal) {
+ elm.setAttribute('data-mce-style', styleVal);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(fmt.attributes, function(value, name) {
- dom.setAttrib(elm, name, replaceVars(value, vars));
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(fmt.attributes, function (value, name) {
+ dom.setAttrib(elm, name, replaceVars(value, vars));
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(fmt.classes, function(value) {
- value = replaceVars(value, vars);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(fmt.classes, function (value) {
+ value = replaceVars(value, vars);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!dom.hasClass(elm, value)) {
- dom.addClass(elm, value);
- }
- });
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!dom.hasClass(elm, value)) {
+ dom.addClass(elm, value);
+ }
+ });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function applyNodeStyle(formatList, node) {
- var found = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function applyNodeStyle(formatList, node) {
+ var found = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!format.selector) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!format.selector) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Look for matching formats
- each(formatList, function(format) {
- // Check collapsed state if it exists
- if ('collapsed' in format && format.collapsed !== isCollapsed) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Look for matching formats
+ each(formatList, function (format) {
+ // Check collapsed state if it exists
+ if ('collapsed' in format && format.collapsed !== isCollapsed) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (dom.is(node, format.selector) && !isCaretNode(node)) {
- setElementFormat(node, format);
- found = true;
- return false;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (dom.is(node, format.selector) && !isCaretNode(node)) {
+ setElementFormat(node, format);
+ found = true;
+ return false;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return found;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return found;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // This converts: <p>[a</p><p>]b</p> -> <p>[a]</p><p>b</p>
- function adjustSelectionToVisibleSelection() {
- function findSelectionEnd(start, end) {
- var walker = new TreeWalker(end);
- for (node = walker.prev2(); node; node = walker.prev2()) {
- if (node.nodeType == 3 && node.data.length > 0) {
- return node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // This converts: <p>[a</p><p>]b</p> -> <p>[a]</p><p>b</p>
+ function adjustSelectionToVisibleSelection() {
+ function findSelectionEnd(start, end) {
+ var walker = new TreeWalker(end);
+ for (node = walker.prev2(); node; node = walker.prev2()) {
+ if (node.nodeType == 3 && node.data.length > 0) {
+ return node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.childNodes.length > 1 || node == start || node.tagName == 'BR') {
- return node;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.childNodes.length > 1 || node == start || node.tagName == 'BR') {
+ return node;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Adjust selection so that a end container with a end offset of zero is not included in the selection
- // as this isn't visible to the user.
- var rng = ed.selection.getRng();
- var start = rng.startContainer;
- var end = rng.endContainer;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Adjust selection so that a end container with a end offset of zero is not included in the selection
+ // as this isn't visible to the user.
+ var rng = ed.selection.getRng();
+ var start = rng.startContainer;
+ var end = rng.endContainer;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (start != end && rng.endOffset === 0) {
- var newEnd = findSelectionEnd(start, end);
- var endOffset = newEnd.nodeType == 3 ? newEnd.data.length : newEnd.childNodes.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (start != end && rng.endOffset === 0) {
+ var newEnd = findSelectionEnd(start, end);
+ var endOffset = newEnd.nodeType == 3 ? newEnd.data.length : newEnd.childNodes.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng.setEnd(newEnd, endOffset);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng.setEnd(newEnd, endOffset);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return rng;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return rng;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function applyRngStyle(rng, bookmark, node_specific) {
- var newWrappers = [], wrapName, wrapElm, contentEditable = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function applyRngStyle(rng, bookmark, nodeSpecific) {
+ var newWrappers = [], wrapName, wrapElm, contentEditable = true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup wrapper element
- wrapName = format.inline || format.block;
- wrapElm = dom.create(wrapName);
- setElementFormat(wrapElm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup wrapper element
+ wrapName = format.inline || format.block;
+ wrapElm = dom.create(wrapName);
+ setElementFormat(wrapElm);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rangeUtils.walk(rng, function(nodes) {
- var currentWrapElm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rangeUtils.walk(rng, function (nodes) {
+ var currentWrapElm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Process a list of nodes wrap them.
- */
- function process(node) {
- var nodeName, parentName, hasContentEditableState, lastContentEditable;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Process a list of nodes wrap them.
+ */
+ function process(node) {
+ var nodeName, parentName, hasContentEditableState, lastContentEditable;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- lastContentEditable = contentEditable;
- nodeName = node.nodeName.toLowerCase();
- parentName = node.parentNode.nodeName.toLowerCase();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ lastContentEditable = contentEditable;
+ nodeName = node.nodeName.toLowerCase();
+ parentName = node.parentNode.nodeName.toLowerCase();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Node has a contentEditable value
- if (node.nodeType === 1 && getContentEditable(node)) {
- lastContentEditable = contentEditable;
- contentEditable = getContentEditable(node) === "true";
- hasContentEditableState = true; // We don't want to wrap the container only it's children
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Node has a contentEditable value
+ if (node.nodeType === 1 && getContentEditable(node)) {
+ lastContentEditable = contentEditable;
+ contentEditable = getContentEditable(node) === "true";
+ hasContentEditableState = true; // We don't want to wrap the container only it's children
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Stop wrapping on br elements
- if (isEq(nodeName, 'br')) {
- currentWrapElm = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Stop wrapping on br elements
+ if (isEq(nodeName, 'br')) {
+ currentWrapElm = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove any br elements when we wrap things
- if (format.block) {
- dom.remove(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove any br elements when we wrap things
+ if (format.block) {
+ dom.remove(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If node is wrapper type
- if (format.wrapper && matchNode(node, name, vars)) {
- currentWrapElm = 0;
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If node is wrapper type
+ if (format.wrapper && matchNode(node, name, vars)) {
+ currentWrapElm = 0;
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Can we rename the block
- // TODO: Break this if up, too complex
- if (contentEditable && !hasContentEditableState && format.block &&
- !format.wrapper && isTextBlock(nodeName) && isValid(parentName, wrapName)) {
- node = dom.rename(node, wrapName);
- setElementFormat(node);
- newWrappers.push(node);
- currentWrapElm = 0;
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Can we rename the block
+ // TODO: Break this if up, too complex
+ if (contentEditable && !hasContentEditableState && format.block &&
+ !format.wrapper && isTextBlock(nodeName) && isValid(parentName, wrapName)) {
+ node = dom.rename(node, wrapName);
+ setElementFormat(node);
+ newWrappers.push(node);
+ currentWrapElm = 0;
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle selector patterns
- if (format.selector) {
- var found = applyNodeStyle(formatList, node);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handle selector patterns
+ if (format.selector) {
+ var found = applyNodeStyle(formatList, node);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Continue processing if a selector match wasn't found and a inline element is defined
- if (!format.inline || found) {
- currentWrapElm = 0;
- return;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Continue processing if a selector match wasn't found and a inline element is defined
+ if (!format.inline || found) {
+ currentWrapElm = 0;
+ return;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Is it valid to wrap this item
- // TODO: Break this if up, too complex
- if (contentEditable && !hasContentEditableState && isValid(wrapName, nodeName) && isValid(parentName, wrapName) &&
- !(!node_specific && node.nodeType === 3 &&
- node.nodeValue.length === 1 &&
- node.nodeValue.charCodeAt(0) === 65279) &&
- !isCaretNode(node) &&
- (!format.inline || !isBlock(node))) {
- // Start wrapping
- if (!currentWrapElm) {
- // Wrap the node
- currentWrapElm = dom.clone(wrapElm, FALSE);
- node.parentNode.insertBefore(currentWrapElm, node);
- newWrappers.push(currentWrapElm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Is it valid to wrap this item
+ // TODO: Break this if up, too complex
+ if (contentEditable && !hasContentEditableState && isValid(wrapName, nodeName) && isValid(parentName, wrapName) &&
+ !(!nodeSpecific && node.nodeType === 3 &&
+ node.nodeValue.length === 1 &&
+ node.nodeValue.charCodeAt(0) === 65279) &&
+ !isCaretNode(node) &&
+ (!format.inline || !isBlock(node))) {
+ // Start wrapping
+ if (!currentWrapElm) {
+ // Wrap the node
+ currentWrapElm = dom.clone(wrapElm, FALSE);
+ node.parentNode.insertBefore(currentWrapElm, node);
+ newWrappers.push(currentWrapElm);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- currentWrapElm.appendChild(node);
- } else {
- // Start a new wrapper for possible children
- currentWrapElm = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ currentWrapElm.appendChild(node);
+ } else {
+ // Start a new wrapper for possible children
+ currentWrapElm = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(grep(node.childNodes), process);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(grep(node.childNodes), process);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (hasContentEditableState) {
- contentEditable = lastContentEditable; // Restore last contentEditable state from stack
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (hasContentEditableState) {
+ contentEditable = lastContentEditable; // Restore last contentEditable state from stack
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // End the last wrapper
- currentWrapElm = 0;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // End the last wrapper
+ currentWrapElm = 0;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Process siblings from range
- each(nodes, process);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Process siblings from range
+ each(nodes, process);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Apply formats to links as well to get the color of the underline to change as well
- if (format.links === true) {
- each(newWrappers, function(node) {
- function process(node) {
- if (node.nodeName === 'A') {
- setElementFormat(node, format);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Apply formats to links as well to get the color of the underline to change as well
+ if (format.links === true) {
+ each(newWrappers, function (node) {
+ function process(node) {
+ if (node.nodeName === 'A') {
+ setElementFormat(node, format);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(grep(node.childNodes), process);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(grep(node.childNodes), process);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- process(node);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ process(node);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Cleanup
- each(newWrappers, function(node) {
- var childCount;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Cleanup
+ each(newWrappers, function (node) {
+ var childCount;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getChildCount(node) {
- var count = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getChildCount(node) {
+ var count = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(node.childNodes, function(node) {
- if (!isWhiteSpaceNode(node) && !isBookmarkNode(node)) {
- count++;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(node.childNodes, function (node) {
+ if (!isWhiteSpaceNode(node) && !isBookmarkNode(node)) {
+ count++;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return count;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return count;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getChildElementNode(root) {
- var child = false;
- each(root.childNodes, function(node) {
- if (isElementNode(node)) {
- child = node;
- return false; // break loop
- }
- });
- return child;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getChildElementNode(root) {
+ var child = false;
+ each(root.childNodes, function (node) {
+ if (isElementNode(node)) {
+ child = node;
+ return false; // break loop
+ }
+ });
+ return child;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function matchNestedWrapper(node, filter) {
- do {
- if (getChildCount(node) !== 1) {
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function matchNestedWrapper(node, filter) {
+ do {
+ if (getChildCount(node) !== 1) {
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = getChildElementNode(node);
- if (!node) {
- break;
- } else if (filter(node)) {
- return node;
- }
- } while (node);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = getChildElementNode(node);
+ if (!node) {
+ break;
+ } else if (filter(node)) {
+ return node;
+ }
+ } while (node);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function mergeStyles(node) {
- var child, clone;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function mergeStyles(node) {
+ var child, clone;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- child = getChildElementNode(node);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ child = getChildElementNode(node);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If child was found and of the same type as the current node
- if (child && !isBookmarkNode(child) && matchName(child, format)) {
- clone = dom.clone(child, FALSE);
- setElementFormat(clone);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If child was found and of the same type as the current node
+ if (child && !isBookmarkNode(child) && matchName(child, format)) {
+ clone = dom.clone(child, FALSE);
+ setElementFormat(clone);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.replace(clone, node, TRUE);
- dom.remove(child, 1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.replace(clone, node, TRUE);
+ dom.remove(child, 1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return clone || node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return clone || node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- childCount = getChildCount(node);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ childCount = getChildCount(node);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove empty nodes but only if there is multiple wrappers and they are not block
- // elements so never remove single <h1></h1> since that would remove the
- // current empty block element where the caret is at
- if ((newWrappers.length > 1 || !isBlock(node)) && childCount === 0) {
- dom.remove(node, 1);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove empty nodes but only if there is multiple wrappers and they are not block
+ // elements so never remove single <h1></h1> since that would remove the
+ // current empty block element where the caret is at
+ if ((newWrappers.length > 1 || !isBlock(node)) && childCount === 0) {
+ dom.remove(node, 1);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (format.inline || format.wrapper) {
- // Merges the current node with it's children of similar type to reduce the number of elements
- if (!format.exact && childCount === 1) {
- node = mergeStyles(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (format.inline || format.wrapper) {
+ // Merges the current node with it's children of similar type to reduce the number of elements
+ if (!format.exact && childCount === 1) {
+ node = mergeStyles(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove/merge children
- each(formatList, function(format) {
- // Merge all children of similar type will move styles from child to parent
- // this: <span style="color:red"><b><span style="color:red; font-size:10px">text</span></b></span>
- // will become: <span style="color:red"><b><span style="font-size:10px">text</span></b></span>
- each(dom.select(format.inline, node), function(child) {
- if (isBookmarkNode(child)) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove/merge children
+ each(formatList, function (format) {
+ // Merge all children of similar type will move styles from child to parent
+ // this: <span style="color:red"><b><span style="color:red; font-size:10px">text</span></b></span>
+ // will become: <span style="color:red"><b><span style="font-size:10px">text</span></b></span>
+ each(dom.select(format.inline, node), function (child) {
+ if (!isElementNode(child)) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- removeFormat(format, vars, child, format.exact ? child : null);
- });
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ removeFormat(format, vars, child, format.exact ? child : null);
+ });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove format if direct parent already has the same format
- if (matchNode(node.parentNode, name, vars)) {
- if (removeFormat(format, vars, node)) {
- node = 0;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove format if direct parent already has the same format
+ if (matchNode(node.parentNode, name, vars)) {
+ if (removeFormat(format, vars, node)) {
+ node = 0;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove format if any ancestor already has the same format
- if (format.merge_with_parents) {
- dom.getParent(node.parentNode, function(parent) {
- if (matchNode(parent, name, vars)) {
- if (removeFormat(format, vars, node)) {
- node = 0;
- }
- return TRUE;
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove format if any ancestor already has the same format
+ if (format.merge_with_parents) {
+ dom.getParent(node.parentNode, function (parent) {
+ if (matchNode(parent, name, vars)) {
+ if (removeFormat(format, vars, node)) {
+ node = 0;
+ }
+ return TRUE;
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // fontSize defines the line height for the whole branch of nested style wrappers,
- // therefore it should be set on the outermost wrapper
- if (!isBlock(node) && !getStyle(node, 'fontSize')) {
- var styleNode = matchNestedWrapper(node, hasStyle('fontSize'));
- if (styleNode) {
- apply('fontsize', {value: getStyle(styleNode, 'fontSize')}, node);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // fontSize defines the line height for the whole branch of nested style wrappers,
+ // therefore it should be set on the outermost wrapper
+ if (node && !isBlock(node) && !getStyle(node, 'fontSize')) {
+ var styleNode = matchNestedWrapper(node, hasStyle('fontSize'));
+ if (styleNode) {
+ apply('fontsize', { value: getStyle(styleNode, 'fontSize') }, node);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Merge next and previous siblings if they are similar <b>text</b><b>text</b> becomes <b>texttext</b>
- if (node && format.merge_siblings !== false) {
- node = mergeSiblings(getNonWhiteSpaceSibling(node), node);
- node = mergeSiblings(node, getNonWhiteSpaceSibling(node, TRUE));
- }
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Merge next and previous siblings if they are similar <b>text</b><b>text</b> becomes <b>texttext</b>
+ if (node && format.merge_siblings !== false) {
+ node = mergeSiblings(getNonWhiteSpaceSibling(node), node);
+ node = mergeSiblings(node, getNonWhiteSpaceSibling(node, TRUE));
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (getContentEditable(selection.getNode()) === "false") {
- node = selection.getNode();
- for (var i = 0, l = formatList.length; i < l; i++) {
- if (formatList[i].ceFalseOverride && dom.is(node, formatList[i].selector)) {
- setElementFormat(node, formatList[i]);
- return;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (getContentEditable(selection.getNode()) === "false") {
+ node = selection.getNode();
+ for (var i = 0, l = formatList.length; i < l; i++) {
+ if (formatList[i].ceFalseOverride && dom.is(node, formatList[i].selector)) {
+ setElementFormat(node, formatList[i]);
+ return;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (format) {
- if (node) {
- if (node.nodeType) {
- if (!applyNodeStyle(formatList, node)) {
- rng = dom.createRng();
- rng.setStartBefore(node);
- rng.setEndAfter(node);
- applyRngStyle(expandRng(rng, formatList), null, true);
- }
- } else {
- applyRngStyle(node, null, true);
- }
- } else {
- if (!isCollapsed || !format.inline || dom.select('td[data-mce-selected],th[data-mce-selected]').length) {
- // Obtain selection node before selection is unselected by applyRngStyle()
- var curSelNode = ed.selection.getNode();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (format) {
+ if (node) {
+ if (node.nodeType) {
+ if (!applyNodeStyle(formatList, node)) {
+ rng = dom.createRng();
+ rng.setStartBefore(node);
+ rng.setEndAfter(node);
+ applyRngStyle(expandRng(rng, formatList), null, true);
+ }
+ } else {
+ applyRngStyle(node, null, true);
+ }
+ } else {
+ if (!isCollapsed || !format.inline || dom.select('td[data-mce-selected],th[data-mce-selected]').length) {
+ // Obtain selection node before selection is unselected by applyRngStyle()
+ var curSelNode = ed.selection.getNode();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If the formats have a default block and we can't find a parent block then
- // start wrapping it with a DIV this is for forced_root_blocks: false
- // It's kind of a hack but people should be using the default block type P since all desktop editors work that way
- if (!forcedRootBlock && formatList[0].defaultBlock && !dom.getParent(curSelNode, dom.isBlock)) {
- apply(formatList[0].defaultBlock);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If the formats have a default block and we can't find a parent block then
+ // start wrapping it with a DIV this is for forced_root_blocks: false
+ // It's kind of a hack but people should be using the default block type P since all desktop editors work that way
+ if (!forcedRootBlock && formatList[0].defaultBlock && !dom.getParent(curSelNode, dom.isBlock)) {
+ apply(formatList[0].defaultBlock);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Apply formatting to selection
- ed.selection.setRng(adjustSelectionToVisibleSelection());
- bookmark = selection.getBookmark();
- applyRngStyle(expandRng(selection.getRng(TRUE), formatList), bookmark);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Apply formatting to selection
+ ed.selection.setRng(adjustSelectionToVisibleSelection());
+ bookmark = selection.getBookmark();
+ applyRngStyle(expandRng(selection.getRng(TRUE), formatList), bookmark);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (format.styles) {
- // Colored nodes should be underlined so that the color of the underline matches the text color.
- if (format.styles.color || format.styles.textDecoration) {
- walk(curSelNode, processUnderlineAndColor, 'childNodes');
- processUnderlineAndColor(curSelNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (format.styles) {
+ // Colored nodes should be underlined so that the color of the underline matches the text color.
+ if (format.styles.color || format.styles.textDecoration) {
+ walk(curSelNode, processUnderlineAndColor, 'childNodes');
+ processUnderlineAndColor(curSelNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // nodes with font-size should have their own background color as well to fit the line-height (see TINY-882)
- if (format.styles.backgroundColor) {
- processChildElements(curSelNode,
- hasStyle('fontSize'),
- applyStyle('backgroundColor', replaceVars(format.styles.backgroundColor, vars))
- );
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // nodes with font-size should have their own background color as well to fit the line-height (see TINY-882)
+ if (format.styles.backgroundColor) {
+ processChildElements(curSelNode,
+ hasStyle('fontSize'),
+ applyStyle('backgroundColor', replaceVars(format.styles.backgroundColor, vars))
+ );
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- selection.moveToBookmark(bookmark);
- moveStart(selection.getRng(TRUE));
- ed.nodeChanged();
- } else {
- performCaretAction('apply', name, vars);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ selection.moveToBookmark(bookmark);
+ moveStart(selection.getRng(TRUE));
+ ed.nodeChanged();
+ } else {
+ performCaretAction('apply', name, vars);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Hooks.postProcess(name, ed);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Hooks.postProcess(name, ed);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes the specified format from the current selection or specified node.
- *
- * @method remove
- * @param {String} name Name of format to remove.
- * @param {Object} vars Optional list of variables to replace within format before removing it.
- * @param {Node/Range} node Optional node or DOM range to remove the format from defaults to current selection.
- */
- function remove(name, vars, node, similar) {
- var formatList = get(name), format = formatList[0], bookmark, rng, contentEditable = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes the specified format from the current selection or specified node.
+ *
+ * @method remove
+ * @param {String} name Name of format to remove.
+ * @param {Object} vars Optional list of variables to replace within format before removing it.
+ * @param {Node/Range} node Optional node or DOM range to remove the format from defaults to current selection.
+ */
+ function remove(name, vars, node, similar) {
+ var formatList = get(name), format = formatList[0], bookmark, rng, contentEditable = true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Merges the styles for each node
- function process(node) {
- var children, i, l, lastContentEditable, hasContentEditableState;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Merges the styles for each node
+ function process(node) {
+ var children, i, l, lastContentEditable, hasContentEditableState;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Node has a contentEditable value
- if (node.nodeType === 1 && getContentEditable(node)) {
- lastContentEditable = contentEditable;
- contentEditable = getContentEditable(node) === "true";
- hasContentEditableState = true; // We don't want to wrap the container only it's children
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Node has a contentEditable value
+ if (node.nodeType === 1 && getContentEditable(node)) {
+ lastContentEditable = contentEditable;
+ contentEditable = getContentEditable(node) === "true";
+ hasContentEditableState = true; // We don't want to wrap the container only it's children
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Grab the children first since the nodelist might be changed
- children = grep(node.childNodes);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Grab the children first since the nodelist might be changed
+ children = grep(node.childNodes);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Process current node
- if (contentEditable && !hasContentEditableState) {
- for (i = 0, l = formatList.length; i < l; i++) {
- if (removeFormat(formatList[i], vars, node, node)) {
- break;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Process current node
+ if (contentEditable && !hasContentEditableState) {
+ for (i = 0, l = formatList.length; i < l; i++) {
+ if (removeFormat(formatList[i], vars, node, node)) {
+ break;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Process the children
- if (format.deep) {
- if (children.length) {
- for (i = 0, l = children.length; i < l; i++) {
- process(children[i]);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Process the children
+ if (format.deep) {
+ if (children.length) {
+ for (i = 0, l = children.length; i < l; i++) {
+ process(children[i]);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (hasContentEditableState) {
- contentEditable = lastContentEditable; // Restore last contentEditable state from stack
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (hasContentEditableState) {
+ contentEditable = lastContentEditable; // Restore last contentEditable state from stack
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function findFormatRoot(container) {
- var formatRoot;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function findFormatRoot(container) {
+ var formatRoot;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Find format root
- each(getParents(container.parentNode).reverse(), function(parent) {
- var format;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find format root
+ each(getParents(container.parentNode).reverse(), function (parent) {
+ var format;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Find format root element
- if (!formatRoot && parent.id != '_start' && parent.id != '_end') {
- // Is the node matching the format we are looking for
- format = matchNode(parent, name, vars, similar);
- if (format && format.split !== false) {
- formatRoot = parent;
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find format root element
+ if (!formatRoot && parent.id != '_start' && parent.id != '_end') {
+ // Is the node matching the format we are looking for
+ format = matchNode(parent, name, vars, similar);
+ if (format && format.split !== false) {
+ formatRoot = parent;
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return formatRoot;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return formatRoot;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function wrapAndSplit(formatRoot, container, target, split) {
- var parent, clone, lastClone, firstClone, i, formatRootParent;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function wrapAndSplit(formatRoot, container, target, split) {
+ var parent, clone, lastClone, firstClone, i, formatRootParent;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Format root found then clone formats and split it
- if (formatRoot) {
- formatRootParent = formatRoot.parentNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Format root found then clone formats and split it
+ if (formatRoot) {
+ formatRootParent = formatRoot.parentNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (parent = container.parentNode; parent && parent != formatRootParent; parent = parent.parentNode) {
- clone = dom.clone(parent, FALSE);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (parent = container.parentNode; parent && parent != formatRootParent; parent = parent.parentNode) {
+ clone = dom.clone(parent, FALSE);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0; i < formatList.length; i++) {
- if (removeFormat(formatList[i], vars, clone, clone)) {
- clone = 0;
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0; i < formatList.length; i++) {
+ if (removeFormat(formatList[i], vars, clone, clone)) {
+ clone = 0;
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Build wrapper node
- if (clone) {
- if (lastClone) {
- clone.appendChild(lastClone);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Build wrapper node
+ if (clone) {
+ if (lastClone) {
+ clone.appendChild(lastClone);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!firstClone) {
- firstClone = clone;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!firstClone) {
+ firstClone = clone;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- lastClone = clone;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ lastClone = clone;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Never split block elements if the format is mixed
- if (split && (!format.mixed || !isBlock(formatRoot))) {
- container = dom.split(formatRoot, container);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Never split block elements if the format is mixed
+ if (split && (!format.mixed || !isBlock(formatRoot))) {
+ container = dom.split(formatRoot, container);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Wrap container in cloned formats
- if (lastClone) {
- target.parentNode.insertBefore(lastClone, target);
- firstClone.appendChild(target);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Wrap container in cloned formats
+ if (lastClone) {
+ target.parentNode.insertBefore(lastClone, target);
+ firstClone.appendChild(target);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return container;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return container;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function splitToFormatRoot(container) {
- return wrapAndSplit(findFormatRoot(container), container, container, true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function splitToFormatRoot(container) {
+ return wrapAndSplit(findFormatRoot(container), container, container, true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function unwrap(start) {
- var node = dom.get(start ? '_start' : '_end'),
- out = node[start ? 'firstChild' : 'lastChild'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function unwrap(start) {
+ var node = dom.get(start ? '_start' : '_end'),
+ out = node[start ? 'firstChild' : 'lastChild'];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If the end is placed within the start the result will be removed
- // So this checks if the out node is a bookmark node if it is it
- // checks for another more suitable node
- if (isBookmarkNode(out)) {
- out = out[start ? 'firstChild' : 'lastChild'];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If the end is placed within the start the result will be removed
+ // So this checks if the out node is a bookmark node if it is it
+ // checks for another more suitable node
+ if (isBookmarkNode(out)) {
+ out = out[start ? 'firstChild' : 'lastChild'];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Since dom.remove removes empty text nodes then we need to try to find a better node
- if (out.nodeType == 3 && out.data.length === 0) {
- out = start ? node.previousSibling || node.nextSibling : node.nextSibling || node.previousSibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Since dom.remove removes empty text nodes then we need to try to find a better node
+ if (out.nodeType == 3 && out.data.length === 0) {
+ out = start ? node.previousSibling || node.nextSibling : node.nextSibling || node.previousSibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.remove(node, true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.remove(node, true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return out;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return out;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function removeRngStyle(rng) {
- var startContainer, endContainer;
- var commonAncestorContainer = rng.commonAncestorContainer;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function removeRngStyle(rng) {
+ var startContainer, endContainer;
+ var commonAncestorContainer = rng.commonAncestorContainer;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng = expandRng(rng, formatList, TRUE);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng = expandRng(rng, formatList, TRUE);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (format.split) {
- startContainer = getContainer(rng, TRUE);
- endContainer = getContainer(rng);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (format.split) {
+ startContainer = getContainer(rng, TRUE);
+ endContainer = getContainer(rng);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (startContainer != endContainer) {
- // WebKit will render the table incorrectly if we wrap a TH or TD in a SPAN
- // so let's see if we can use the first child instead
- // This will happen if you triple click a table cell and use remove formatting
- if (/^(TR|TH|TD)$/.test(startContainer.nodeName) && startContainer.firstChild) {
- if (startContainer.nodeName == "TR") {
- startContainer = startContainer.firstChild.firstChild || startContainer;
- } else {
- startContainer = startContainer.firstChild || startContainer;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (startContainer != endContainer) {
+ // WebKit will render the table incorrectly if we wrap a TH or TD in a SPAN
+ // so let's see if we can use the first child instead
+ // This will happen if you triple click a table cell and use remove formatting
+ if (/^(TR|TH|TD)$/.test(startContainer.nodeName) && startContainer.firstChild) {
+ if (startContainer.nodeName == "TR") {
+ startContainer = startContainer.firstChild.firstChild || startContainer;
+ } else {
+ startContainer = startContainer.firstChild || startContainer;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Try to adjust endContainer as well if cells on the same row were selected - bug #6410
- if (commonAncestorContainer &&
- /^T(HEAD|BODY|FOOT|R)$/.test(commonAncestorContainer.nodeName) &&
- isTableCell(endContainer) && endContainer.firstChild) {
- endContainer = endContainer.firstChild || endContainer;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Try to adjust endContainer as well if cells on the same row were selected - bug #6410
+ if (commonAncestorContainer &&
+ /^T(HEAD|BODY|FOOT|R)$/.test(commonAncestorContainer.nodeName) &&
+ isTableCell(endContainer) && endContainer.firstChild) {
+ endContainer = endContainer.firstChild || endContainer;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (dom.isChildOf(startContainer, endContainer) && !isBlock(endContainer) &&
- !isTableCell(startContainer) && !isTableCell(endContainer)) {
- startContainer = wrap(startContainer, 'span', {id: '_start', 'data-mce-type': 'bookmark'});
- splitToFormatRoot(startContainer);
- startContainer = unwrap(TRUE);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (dom.isChildOf(startContainer, endContainer) && !isBlock(endContainer) &&
+ !isTableCell(startContainer) && !isTableCell(endContainer)) {
+ startContainer = wrap(startContainer, 'span', { id: '_start', 'data-mce-type': 'bookmark' });
+ splitToFormatRoot(startContainer);
+ startContainer = unwrap(TRUE);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Wrap start/end nodes in span element since these might be cloned/moved
- startContainer = wrap(startContainer, 'span', {id: '_start', 'data-mce-type': 'bookmark'});
- endContainer = wrap(endContainer, 'span', {id: '_end', 'data-mce-type': 'bookmark'});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Wrap start/end nodes in span element since these might be cloned/moved
+ startContainer = wrap(startContainer, 'span', { id: '_start', 'data-mce-type': 'bookmark' });
+ endContainer = wrap(endContainer, 'span', { id: '_end', 'data-mce-type': 'bookmark' });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Split start/end
- splitToFormatRoot(startContainer);
- splitToFormatRoot(endContainer);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Split start/end
+ splitToFormatRoot(startContainer);
+ splitToFormatRoot(endContainer);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Unwrap start/end to get real elements again
- startContainer = unwrap(TRUE);
- endContainer = unwrap();
- } else {
- startContainer = endContainer = splitToFormatRoot(startContainer);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Unwrap start/end to get real elements again
+ startContainer = unwrap(TRUE);
+ endContainer = unwrap();
+ } else {
+ startContainer = endContainer = splitToFormatRoot(startContainer);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Update range positions since they might have changed after the split operations
- rng.startContainer = startContainer.parentNode ? startContainer.parentNode : startContainer;
- rng.startOffset = nodeIndex(startContainer);
- rng.endContainer = endContainer.parentNode ? endContainer.parentNode : endContainer;
- rng.endOffset = nodeIndex(endContainer) + 1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Update range positions since they might have changed after the split operations
+ rng.startContainer = startContainer.parentNode ? startContainer.parentNode : startContainer;
+ rng.startOffset = nodeIndex(startContainer);
+ rng.endContainer = endContainer.parentNode ? endContainer.parentNode : endContainer;
+ rng.endOffset = nodeIndex(endContainer) + 1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove items between start/end
- rangeUtils.walk(rng, function(nodes) {
- each(nodes, function(node) {
- process(node);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove items between start/end
+ rangeUtils.walk(rng, function (nodes) {
+ each(nodes, function (node) {
+ process(node);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove parent span if it only contains text-decoration: underline, yet a parent node is also underlined.
- if (node.nodeType === 1 && ed.dom.getStyle(node, 'text-decoration') === 'underline' &&
- node.parentNode && getTextDecoration(node.parentNode) === 'underline') {
- removeFormat({
- 'deep': false,
- 'exact': true,
- 'inline': 'span',
- 'styles': {
- 'textDecoration': 'underline'
- }
- }, null, node);
- }
- });
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove parent span if it only contains text-decoration: underline, yet a parent node is also underlined.
+ if (node.nodeType === 1 && ed.dom.getStyle(node, 'text-decoration') === 'underline' &&
+ node.parentNode && getTextDecoration(node.parentNode) === 'underline') {
+ removeFormat({
+ 'deep': false,
+ 'exact': true,
+ 'inline': 'span',
+ 'styles': {
+ 'textDecoration': 'underline'
+ }
+ }, null, node);
+ }
+ });
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle node
- if (node) {
- if (node.nodeType) {
- rng = dom.createRng();
- rng.setStartBefore(node);
- rng.setEndAfter(node);
- removeRngStyle(rng);
- } else {
- removeRngStyle(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handle node
+ if (node) {
+ if (node.nodeType) {
+ rng = dom.createRng();
+ rng.setStartBefore(node);
+ rng.setEndAfter(node);
+ removeRngStyle(rng);
+ } else {
+ removeRngStyle(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (getContentEditable(selection.getNode()) === "false") {
- node = selection.getNode();
- for (var i = 0, l = formatList.length; i < l; i++) {
- if (formatList[i].ceFalseOverride) {
- if (removeFormat(formatList[i], vars, node, node)) {
- break;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (getContentEditable(selection.getNode()) === "false") {
+ node = selection.getNode();
+ for (var i = 0, l = formatList.length; i < l; i++) {
+ if (formatList[i].ceFalseOverride) {
+ if (removeFormat(formatList[i], vars, node, node)) {
+ break;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!selection.isCollapsed() || !format.inline || dom.select('td[data-mce-selected],th[data-mce-selected]').length) {
- bookmark = selection.getBookmark();
- removeRngStyle(selection.getRng(TRUE));
- selection.moveToBookmark(bookmark);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!selection.isCollapsed() || !format.inline || dom.select('td[data-mce-selected],th[data-mce-selected]').length) {
+ bookmark = selection.getBookmark();
+ removeRngStyle(selection.getRng(TRUE));
+ selection.moveToBookmark(bookmark);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if start element still has formatting then we are at: "<b>text|</b>text"
- // and need to move the start into the next text node
- if (format.inline && match(name, vars, selection.getStart())) {
- moveStart(selection.getRng(true));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if start element still has formatting then we are at: "<b>text|</b>text"
+ // and need to move the start into the next text node
+ if (format.inline && match(name, vars, selection.getStart())) {
+ moveStart(selection.getRng(true));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ed.nodeChanged();
- } else {
- performCaretAction('remove', name, vars, similar);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ed.nodeChanged();
+ } else {
+ performCaretAction('remove', name, vars, similar);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Toggles the specified format on/off.
- *
- * @method toggle
- * @param {String} name Name of format to apply/remove.
- * @param {Object} vars Optional list of variables to replace within format before applying/removing it.
- * @param {Node} node Optional node to apply the format to or remove from. Defaults to current selection.
- */
- function toggle(name, vars, node) {
- var fmt = get(name);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Toggles the specified format on/off.
+ *
+ * @method toggle
+ * @param {String} name Name of format to apply/remove.
+ * @param {Object} vars Optional list of variables to replace within format before applying/removing it.
+ * @param {Node} node Optional node to apply the format to or remove from. Defaults to current selection.
+ */
+ function toggle(name, vars, node) {
+ var fmt = get(name);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (match(name, vars, node) && (!('toggle' in fmt[0]) || fmt[0].toggle)) {
- remove(name, vars, node);
- } else {
- apply(name, vars, node);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (match(name, vars, node) && (!('toggle' in fmt[0]) || fmt[0].toggle)) {
+ remove(name, vars, node);
+ } else {
+ apply(name, vars, node);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Return true/false if the specified node has the specified format.
- *
- * @method matchNode
- * @param {Node} node Node to check the format on.
- * @param {String} name Format name to check.
- * @param {Object} vars Optional list of variables to replace before checking it.
- * @param {Boolean} similar Match format that has similar properties.
- * @return {Object} Returns the format object it matches or undefined if it doesn't match.
- */
- function matchNode(node, name, vars, similar) {
- var formatList = get(name), format, i, classes;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Return true/false if the specified node has the specified format.
+ *
+ * @method matchNode
+ * @param {Node} node Node to check the format on.
+ * @param {String} name Format name to check.
+ * @param {Object} vars Optional list of variables to replace before checking it.
+ * @param {Boolean} similar Match format that has similar properties.
+ * @return {Object} Returns the format object it matches or undefined if it doesn't match.
+ */
+ function matchNode(node, name, vars, similar) {
+ var formatList = get(name), format, i, classes;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function matchItems(node, format, item_name) {
- var key, value, items = format[item_name], i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function matchItems(node, format, itemName) {
+ var key, value, items = format[itemName], i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Custom match
- if (format.onmatch) {
- return format.onmatch(node, format, item_name);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Custom match
+ if (format.onmatch) {
+ return format.onmatch(node, format, itemName);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check all items
- if (items) {
- // Non indexed object
- if (items.length === undef) {
- for (key in items) {
- if (items.hasOwnProperty(key)) {
- if (item_name === 'attributes') {
- value = dom.getAttrib(node, key);
- } else {
- value = getStyle(node, key);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check all items
+ if (items) {
+ // Non indexed object
+ if (items.length === undef) {
+ for (key in items) {
+ if (items.hasOwnProperty(key)) {
+ if (itemName === 'attributes') {
+ value = dom.getAttrib(node, key);
+ } else {
+ value = getStyle(node, key);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (similar && !value && !format.exact) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (similar && !value && !format.exact) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ((!similar || format.exact) && !isEq(value, normalizeStyleValue(replaceVars(items[key], vars), key))) {
- return;
- }
- }
- }
- } else {
- // Only one match needed for indexed arrays
- for (i = 0; i < items.length; i++) {
- if (item_name === 'attributes' ? dom.getAttrib(node, items[i]) : getStyle(node, items[i])) {
- return format;
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((!similar || format.exact) && !isEq(value, normalizeStyleValue(replaceVars(items[key], vars), key))) {
+ return;
+ }
+ }
+ }
+ } else {
+ // Only one match needed for indexed arrays
+ for (i = 0; i < items.length; i++) {
+ if (itemName === 'attributes' ? dom.getAttrib(node, items[i]) : getStyle(node, items[i])) {
+ return format;
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return format;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return format;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (formatList && node) {
- // Check each format in list
- for (i = 0; i < formatList.length; i++) {
- format = formatList[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (formatList && node) {
+ // Check each format in list
+ for (i = 0; i < formatList.length; i++) {
+ format = formatList[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Name name, attributes, styles and classes
- if (matchName(node, format) && matchItems(node, format, 'attributes') && matchItems(node, format, 'styles')) {
- // Match classes
- if ((classes = format.classes)) {
- for (i = 0; i < classes.length; i++) {
- if (!dom.hasClass(node, classes[i])) {
- return;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Name name, attributes, styles and classes
+ if (matchName(node, format) && matchItems(node, format, 'attributes') && matchItems(node, format, 'styles')) {
+ // Match classes
+ if ((classes = format.classes)) {
+ for (i = 0; i < classes.length; i++) {
+ if (!dom.hasClass(node, classes[i])) {
+ return;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return format;
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return format;
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Matches the current selection or specified node against the specified format name.
- *
- * @method match
- * @param {String} name Name of format to match.
- * @param {Object} vars Optional list of variables to replace before checking it.
- * @param {Node} node Optional node to check.
- * @return {boolean} true/false if the specified selection/node matches the format.
- */
- function match(name, vars, node) {
- var startNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Matches the current selection or specified node against the specified format name.
+ *
+ * @method match
+ * @param {String} name Name of format to match.
+ * @param {Object} vars Optional list of variables to replace before checking it.
+ * @param {Node} node Optional node to check.
+ * @return {boolean} true/false if the specified selection/node matches the format.
+ */
+ function match(name, vars, node) {
+ var startNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function matchParents(node) {
- var root = dom.getRoot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function matchParents(node) {
+ var root = dom.getRoot();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node === root) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node === root) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Find first node with similar format settings
- node = dom.getParent(node, function(node) {
- if (matchesUnInheritedFormatSelector(node, name)) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find first node with similar format settings
+ node = dom.getParent(node, function (node) {
+ if (matchesUnInheritedFormatSelector(node, name)) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return node.parentNode === root || !!matchNode(node, name, vars, true);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return node.parentNode === root || !!matchNode(node, name, vars, true);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Do an exact check on the similar format element
- return matchNode(node, name, vars);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Do an exact check on the similar format element
+ return matchNode(node, name, vars);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check specified node
- if (node) {
- return matchParents(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check specified node
+ if (node) {
+ return matchParents(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check selected node
- node = selection.getNode();
- if (matchParents(node)) {
- return TRUE;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check selected node
+ node = selection.getNode();
+ if (matchParents(node)) {
+ return TRUE;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check start node if it's different
- startNode = selection.getStart();
- if (startNode != node) {
- if (matchParents(startNode)) {
- return TRUE;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check start node if it's different
+ startNode = selection.getStart();
+ if (startNode != node) {
+ if (matchParents(startNode)) {
+ return TRUE;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return FALSE;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return FALSE;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Matches the current selection against the array of formats and returns a new array with matching formats.
- *
- * @method matchAll
- * @param {Array} names Name of format to match.
- * @param {Object} vars Optional list of variables to replace before checking it.
- * @return {Array} Array with matched formats.
- */
- function matchAll(names, vars) {
- var startElement, matchedFormatNames = [], checkedMap = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Matches the current selection against the array of formats and returns a new array with matching formats.
+ *
+ * @method matchAll
+ * @param {Array} names Name of format to match.
+ * @param {Object} vars Optional list of variables to replace before checking it.
+ * @return {Array} Array with matched formats.
+ */
+ function matchAll(names, vars) {
+ var startElement, matchedFormatNames = [], checkedMap = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check start of selection for formats
- startElement = selection.getStart();
- dom.getParent(startElement, function(node) {
- var i, name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check start of selection for formats
+ startElement = selection.getStart();
+ dom.getParent(startElement, function (node) {
+ var i, name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0; i < names.length; i++) {
- name = names[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0; i < names.length; i++) {
+ name = names[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!checkedMap[name] && matchNode(node, name, vars)) {
- checkedMap[name] = true;
- matchedFormatNames.push(name);
- }
- }
- }, dom.getRoot());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!checkedMap[name] && matchNode(node, name, vars)) {
+ checkedMap[name] = true;
+ matchedFormatNames.push(name);
+ }
+ }
+ }, dom.getRoot());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return matchedFormatNames;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return matchedFormatNames;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the specified format can be applied to the current selection or not. It
- * will currently only check the state for selector formats, it returns true on all other format types.
- *
- * @method canApply
- * @param {String} name Name of format to check.
- * @return {boolean} true/false if the specified format can be applied to the current selection/node.
- */
- function canApply(name) {
- var formatList = get(name), startNode, parents, i, x, selector;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the specified format can be applied to the current selection or not. It
+ * will currently only check the state for selector formats, it returns true on all other format types.
+ *
+ * @method canApply
+ * @param {String} name Name of format to check.
+ * @return {boolean} true/false if the specified format can be applied to the current selection/node.
+ */
+ function canApply(name) {
+ var formatList = get(name), startNode, parents, i, x, selector;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (formatList) {
- startNode = selection.getStart();
- parents = getParents(startNode);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (formatList) {
+ startNode = selection.getStart();
+ parents = getParents(startNode);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (x = formatList.length - 1; x >= 0; x--) {
- selector = formatList[x].selector;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (x = formatList.length - 1; x >= 0; x--) {
+ selector = formatList[x].selector;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Format is not selector based then always return TRUE
- // Is it has a defaultBlock then it's likely it can be applied for example align on a non block element line
- if (!selector || formatList[x].defaultBlock) {
- return TRUE;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Format is not selector based then always return TRUE
+ // Is it has a defaultBlock then it's likely it can be applied for example align on a non block element line
+ if (!selector || formatList[x].defaultBlock) {
+ return TRUE;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = parents.length - 1; i >= 0; i--) {
- if (dom.is(parents[i], selector)) {
- return TRUE;
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = parents.length - 1; i >= 0; i--) {
+ if (dom.is(parents[i], selector)) {
+ return TRUE;
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return FALSE;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return FALSE;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Executes the specified callback when the current selection matches the formats or not.
- *
- * @method formatChanged
- * @param {String} formats Comma separated list of formats to check for.
- * @param {function} callback Callback with state and args when the format is changed/toggled on/off.
- * @param {Boolean} similar True/false state if the match should handle similar or exact formats.
- */
- function formatChanged(formats, callback, similar) {
- var currentFormats;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Executes the specified callback when the current selection matches the formats or not.
+ *
+ * @method formatChanged
+ * @param {String} formats Comma separated list of formats to check for.
+ * @param {function} callback Callback with state and args when the format is changed/toggled on/off.
+ * @param {Boolean} similar True/false state if the match should handle similar or exact formats.
+ */
+ function formatChanged(formats, callback, similar) {
+ var currentFormats;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup format node change logic
- if (!formatChangeData) {
- formatChangeData = {};
- currentFormats = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup format node change logic
+ if (!formatChangeData) {
+ formatChangeData = {};
+ currentFormats = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ed.on('NodeChange', function(e) {
- var parents = getParents(e.element), matchedFormats = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ed.on('NodeChange', function (e) {
+ var parents = getParents(e.element), matchedFormats = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Ignore bogus nodes like the <a> tag created by moveStart()
- parents = Tools.grep(parents, function(node) {
- return node.nodeType == 1 && !node.getAttribute('data-mce-bogus');
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Ignore bogus nodes like the <a> tag created by moveStart()
+ parents = Tools.grep(parents, function (node) {
+ return node.nodeType == 1 && !node.getAttribute('data-mce-bogus');
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check for new formats
- each(formatChangeData, function(callbacks, format) {
- each(parents, function(node) {
- if (matchNode(node, format, {}, callbacks.similar)) {
- if (!currentFormats[format]) {
- // Execute callbacks
- each(callbacks, function(callback) {
- callback(true, {node: node, format: format, parents: parents});
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check for new formats
+ each(formatChangeData, function (callbacks, format) {
+ each(parents, function (node) {
+ if (matchNode(node, format, {}, callbacks.similar)) {
+ if (!currentFormats[format]) {
+ // Execute callbacks
+ each(callbacks, function (callback) {
+ callback(true, { node: node, format: format, parents: parents });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- currentFormats[format] = callbacks;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ currentFormats[format] = callbacks;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- matchedFormats[format] = callbacks;
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ matchedFormats[format] = callbacks;
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (matchesUnInheritedFormatSelector(node, format)) {
- return false;
- }
- });
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (matchesUnInheritedFormatSelector(node, format)) {
+ return false;
+ }
+ });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if current formats still match
- each(currentFormats, function(callbacks, format) {
- if (!matchedFormats[format]) {
- delete currentFormats[format];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if current formats still match
+ each(currentFormats, function (callbacks, format) {
+ if (!matchedFormats[format]) {
+ delete currentFormats[format];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(callbacks, function(callback) {
- callback(false, {node: e.element, format: format, parents: parents});
- });
- }
- });
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(callbacks, function (callback) {
+ callback(false, { node: e.element, format: format, parents: parents });
+ });
+ }
+ });
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add format listeners
- each(formats.split(','), function(format) {
- if (!formatChangeData[format]) {
- formatChangeData[format] = [];
- formatChangeData[format].similar = similar;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add format listeners
+ each(formats.split(','), function (format) {
+ if (!formatChangeData[format]) {
+ formatChangeData[format] = [];
+ formatChangeData[format].similar = similar;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- formatChangeData[format].push(callback);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ formatChangeData[format].push(callback);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a preview css text for the specified format.
- *
- * @method getCssText
- * @param {String/Object} format Format to generate preview css text for.
- * @return {String} Css text for the specified format.
- * @example
- * var cssText1 = editor.formatter.getCssText('bold');
- * var cssText2 = editor.formatter.getCssText({inline: 'b'});
- */
- function getCssText(format) {
- return Preview.getCssText(ed, format);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a preview css text for the specified format.
+ *
+ * @method getCssText
+ * @param {String/Object} format Format to generate preview css text for.
+ * @return {String} Css text for the specified format.
+ * @example
+ * var cssText1 = editor.formatter.getCssText('bold');
+ * var cssText2 = editor.formatter.getCssText({inline: 'b'});
+ */
+ function getCssText(format) {
+ return Preview.getCssText(ed, format);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Expose to public
- extend(this, {
- get: get,
- register: register,
- unregister: unregister,
- apply: apply,
- remove: remove,
- toggle: toggle,
- match: match,
- matchAll: matchAll,
- matchNode: matchNode,
- canApply: canApply,
- formatChanged: formatChanged,
- getCssText: getCssText
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Expose to public
+ extend(this, {
+ get: get,
+ register: register,
+ unregister: unregister,
+ apply: apply,
+ remove: remove,
+ toggle: toggle,
+ match: match,
+ matchAll: matchAll,
+ matchNode: matchNode,
+ canApply: canApply,
+ formatChanged: formatChanged,
+ getCssText: getCssText
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Initialize
- defaultFormats();
- addKeyboardShortcuts();
- ed.on('BeforeGetContent', function(e) {
- if (markCaretContainersBogus && e.format != 'raw') {
- markCaretContainersBogus();
- }
- });
- ed.on('mouseup keydown', function(e) {
- if (disableCaretContainer) {
- disableCaretContainer(e);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Initialize
+ defaultFormats();
+ addKeyboardShortcuts();
+ ed.on('BeforeGetContent', function (e) {
+ if (markCaretContainersBogus && e.format != 'raw') {
+ markCaretContainersBogus();
+ }
+ });
+ ed.on('mouseup keydown', function (e) {
+ if (disableCaretContainer) {
+ disableCaretContainer(e);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Private functions
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Private functions
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Checks if the specified nodes name matches the format inline/block or selector.
- *
- * @private
- * @param {Node} node Node to match against the specified format.
- * @param {Object} format Format object o match with.
- * @return {boolean} true/false if the format matches.
- */
- function matchName(node, format) {
- // Check for inline match
- if (isEq(node, format.inline)) {
- return TRUE;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Checks if the specified nodes name matches the format inline/block or selector.
+ *
+ * @private
+ * @param {Node} node Node to match against the specified format.
+ * @param {Object} format Format object o match with.
+ * @return {boolean} true/false if the format matches.
+ */
+ function matchName(node, format) {
+ // Check for inline match
+ if (isEq(node, format.inline)) {
+ return TRUE;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check for block match
- if (isEq(node, format.block)) {
- return TRUE;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check for block match
+ if (isEq(node, format.block)) {
+ return TRUE;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check for selector match
- if (format.selector) {
- return node.nodeType == 1 && dom.is(node, format.selector);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check for selector match
+ if (format.selector) {
+ return node.nodeType == 1 && dom.is(node, format.selector);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Compares two string/nodes regardless of their case.
- *
- * @private
- * @param {String/Node} str1 Node or string to compare.
- * @param {String/Node} str2 Node or string to compare.
- * @return {boolean} True/false if they match.
- */
- function isEq(str1, str2) {
- str1 = str1 || '';
- str2 = str2 || '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Compares two string/nodes regardless of their case.
+ *
+ * @private
+ * @param {String/Node} str1 Node or string to compare.
+ * @param {String/Node} str2 Node or string to compare.
+ * @return {boolean} True/false if they match.
+ */
+ function isEq(str1, str2) {
+ str1 = str1 || '';
+ str2 = str2 || '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- str1 = '' + (str1.nodeName || str1);
- str2 = '' + (str2.nodeName || str2);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ str1 = '' + (str1.nodeName || str1);
+ str2 = '' + (str2.nodeName || str2);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return str1.toLowerCase() == str2.toLowerCase();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return str1.toLowerCase() == str2.toLowerCase();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function processChildElements(node, filter, process) {
- each(node.childNodes, function(node) {
- if (isElementNode(node)) {
- if (filter(node)) {
- process(node);
- }
- if (node.hasChildNodes()) {
- processChildElements(node, filter, process);
- }
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function processChildElements(node, filter, process) {
+ each(node.childNodes, function (node) {
+ if (isElementNode(node)) {
+ if (filter(node)) {
+ process(node);
+ }
+ if (node.hasChildNodes()) {
+ processChildElements(node, filter, process);
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isElementNode(node) {
- return node.nodeType == 1 && !isBookmarkNode(node) && !isWhiteSpaceNode(node) && !isCaretNode(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isElementNode(node) {
+ return node && node.nodeType === 1 && !isBookmarkNode(node) && !isCaretNode(node) && !NodeType.isBogus(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hasStyle(name) {
- return Fun.curry(function(name, node) {
- return !!(node && getStyle(node, name));
- }, name);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hasStyle(name) {
+ return Fun.curry(function (name, node) {
+ return !!(node && getStyle(node, name));
+ }, name);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function applyStyle(name, value) {
- return Fun.curry(function(name, value, node) {
- dom.setStyle(node, name, value);
- }, name, value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function applyStyle(name, value) {
+ return Fun.curry(function (name, value, node) {
+ dom.setStyle(node, name, value);
+ }, name, value);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the style by name on the specified node. This method modifies the style
- * contents to make it more easy to match. This will resolve a few browser issues.
- *
- * @private
- * @param {Node} node to get style from.
- * @param {String} name Style name to get.
- * @return {String} Style item value.
- */
- function getStyle(node, name) {
- return normalizeStyleValue(dom.getStyle(node, name), name);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the style by name on the specified node. This method modifies the style
+ * contents to make it more easy to match. This will resolve a few browser issues.
+ *
+ * @private
+ * @param {Node} node to get style from.
+ * @param {String} name Style name to get.
+ * @return {String} Style item value.
+ */
+ function getStyle(node, name) {
+ return normalizeStyleValue(dom.getStyle(node, name), name);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Normalize style value by name. This method modifies the style contents
- * to make it more easy to match. This will resolve a few browser issues.
- *
- * @private
- * @param {String} value Value to get style from.
- * @param {String} name Style name to get.
- * @return {String} Style item value.
- */
- function normalizeStyleValue(value, name) {
- // Force the format to hex
- if (name == 'color' || name == 'backgroundColor') {
- value = dom.toHex(value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Normalize style value by name. This method modifies the style contents
+ * to make it more easy to match. This will resolve a few browser issues.
+ *
+ * @private
+ * @param {String} value Value to get style from.
+ * @param {String} name Style name to get.
+ * @return {String} Style item value.
+ */
+ function normalizeStyleValue(value, name) {
+ // Force the format to hex
+ if (name == 'color' || name == 'backgroundColor') {
+ value = dom.toHex(value);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Opera will return bold as 700
- if (name == 'fontWeight' && value == 700) {
- value = 'bold';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Opera will return bold as 700
+ if (name == 'fontWeight' && value == 700) {
+ value = 'bold';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Normalize fontFamily so "'Font name', Font" becomes: "Font name,Font"
- if (name == 'fontFamily') {
- value = value.replace(/[\'\"]/g, '').replace(/,\s+/g, ',');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Normalize fontFamily so "'Font name', Font" becomes: "Font name,Font"
+ if (name == 'fontFamily') {
+ value = value.replace(/[\'\"]/g, '').replace(/,\s+/g, ',');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return '' + value;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return '' + value;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Replaces variables in the value. The variable format is %var.
- *
- * @private
- * @param {String} value Value to replace variables in.
- * @param {Object} vars Name/value array with variables to replace.
- * @return {String} New value with replaced variables.
- */
- function replaceVars(value, vars) {
- if (typeof value != "string") {
- value = value(vars);
- } else if (vars) {
- value = value.replace(/%(\w+)/g, function(str, name) {
- return vars[name] || str;
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Replaces variables in the value. The variable format is %var.
+ *
+ * @private
+ * @param {String} value Value to replace variables in.
+ * @param {Object} vars Name/value array with variables to replace.
+ * @return {String} New value with replaced variables.
+ */
+ function replaceVars(value, vars) {
+ if (typeof value != "string") {
+ value = value(vars);
+ } else if (vars) {
+ value = value.replace(/%(\w+)/g, function (str, name) {
+ return vars[name] || str;
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return value;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return value;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isWhiteSpaceNode(node) {
- return node && node.nodeType === 3 && /^([\t \r\n]+|)$/.test(node.nodeValue);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isWhiteSpaceNode(node) {
+ return node && node.nodeType === 3 && /^([\t \r\n]+|)$/.test(node.nodeValue);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function wrap(node, name, attrs) {
- var wrapper = dom.create(name, attrs);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function wrap(node, name, attrs) {
+ var wrapper = dom.create(name, attrs);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node.parentNode.insertBefore(wrapper, node);
- wrapper.appendChild(node);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node.parentNode.insertBefore(wrapper, node);
+ wrapper.appendChild(node);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return wrapper;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return wrapper;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Expands the specified range like object to depending on format.
- *
- * For example on block formats it will move the start/end position
- * to the beginning of the current block.
- *
- * @private
- * @param {Object} rng Range like object.
- * @param {Array} format Array with formats to expand by.
- * @param {Boolean} remove
- * @return {Object} Expanded range like object.
- */
- function expandRng(rng, format, remove) {
- var lastIdx, leaf, endPoint,
- startContainer = rng.startContainer,
- startOffset = rng.startOffset,
- endContainer = rng.endContainer,
- endOffset = rng.endOffset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Expands the specified range like object to depending on format.
+ *
+ * For example on block formats it will move the start/end position
+ * to the beginning of the current block.
+ *
+ * @private
+ * @param {Object} rng Range like object.
+ * @param {Array} format Array with formats to expand by.
+ * @param {Boolean} remove
+ * @return {Object} Expanded range like object.
+ */
+ function expandRng(rng, format, remove) {
+ var lastIdx, leaf, endPoint,
+ startContainer = rng.startContainer,
+ startOffset = rng.startOffset,
+ endContainer = rng.endContainer,
+ endOffset = rng.endOffset;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // This function walks up the tree if there is no siblings before/after the node
- function findParentContainer(start) {
- var container, parent, sibling, siblingName, root;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // This function walks up the tree if there is no siblings before/after the node
+ function findParentContainer(start) {
+ var container, parent, sibling, siblingName, root;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = parent = start ? startContainer : endContainer;
- siblingName = start ? 'previousSibling' : 'nextSibling';
- root = dom.getRoot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = parent = start ? startContainer : endContainer;
+ siblingName = start ? 'previousSibling' : 'nextSibling';
+ root = dom.getRoot();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isBogusBr(node) {
- return node.nodeName == "BR" && node.getAttribute('data-mce-bogus') && !node.nextSibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isBogusBr(node) {
+ return node.nodeName == "BR" && node.getAttribute('data-mce-bogus') && !node.nextSibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If it's a text node and the offset is inside the text
- if (container.nodeType == 3 && !isWhiteSpaceNode(container)) {
- if (start ? startOffset > 0 : endOffset < container.nodeValue.length) {
- return container;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If it's a text node and the offset is inside the text
+ if (container.nodeType == 3 && !isWhiteSpaceNode(container)) {
+ if (start ? startOffset > 0 : endOffset < container.nodeValue.length) {
+ return container;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /*eslint no-constant-condition:0 */
- while (true) {
- // Stop expanding on block elements
- if (!format[0].block_expand && isBlock(parent)) {
- return parent;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /*eslint no-constant-condition:0 */
+ while (true) {
+ // Stop expanding on block elements
+ if (!format[0].block_expand && isBlock(parent)) {
+ return parent;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Walk left/right
- for (sibling = parent[siblingName]; sibling; sibling = sibling[siblingName]) {
- if (!isBookmarkNode(sibling) && !isWhiteSpaceNode(sibling) && !isBogusBr(sibling)) {
- return parent;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Walk left/right
+ for (sibling = parent[siblingName]; sibling; sibling = sibling[siblingName]) {
+ if (!isBookmarkNode(sibling) && !isWhiteSpaceNode(sibling) && !isBogusBr(sibling)) {
+ return parent;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if we can move up are we at root level or body level
- if (parent == root || parent.parentNode == root) {
- container = parent;
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if we can move up are we at root level or body level
+ if (parent == root || parent.parentNode == root) {
+ container = parent;
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parent = parent.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parent = parent.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return container;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return container;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // This function walks down the tree to find the leaf at the selection.
- // The offset is also returned as if node initially a leaf, the offset may be in the middle of the text node.
- function findLeaf(node, offset) {
- if (offset === undef) {
- offset = node.nodeType === 3 ? node.length : node.childNodes.length;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // This function walks down the tree to find the leaf at the selection.
+ // The offset is also returned as if node initially a leaf, the offset may be in the middle of the text node.
+ function findLeaf(node, offset) {
+ if (offset === undef) {
+ offset = node.nodeType === 3 ? node.length : node.childNodes.length;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (node && node.hasChildNodes()) {
- node = node.childNodes[offset];
- if (node) {
- offset = node.nodeType === 3 ? node.length : node.childNodes.length;
- }
- }
- return {node: node, offset: offset};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (node && node.hasChildNodes()) {
+ node = node.childNodes[offset];
+ if (node) {
+ offset = node.nodeType === 3 ? node.length : node.childNodes.length;
+ }
+ }
+ return { node: node, offset: offset };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If index based start position then resolve it
- if (startContainer.nodeType == 1 && startContainer.hasChildNodes()) {
- lastIdx = startContainer.childNodes.length - 1;
- startContainer = startContainer.childNodes[startOffset > lastIdx ? lastIdx : startOffset];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If index based start position then resolve it
+ if (startContainer.nodeType == 1 && startContainer.hasChildNodes()) {
+ lastIdx = startContainer.childNodes.length - 1;
+ startContainer = startContainer.childNodes[startOffset > lastIdx ? lastIdx : startOffset];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (startContainer.nodeType == 3) {
- startOffset = 0;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (startContainer.nodeType == 3) {
+ startOffset = 0;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If index based end position then resolve it
- if (endContainer.nodeType == 1 && endContainer.hasChildNodes()) {
- lastIdx = endContainer.childNodes.length - 1;
- endContainer = endContainer.childNodes[endOffset > lastIdx ? lastIdx : endOffset - 1];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If index based end position then resolve it
+ if (endContainer.nodeType == 1 && endContainer.hasChildNodes()) {
+ lastIdx = endContainer.childNodes.length - 1;
+ endContainer = endContainer.childNodes[endOffset > lastIdx ? lastIdx : endOffset - 1];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (endContainer.nodeType == 3) {
- endOffset = endContainer.nodeValue.length;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (endContainer.nodeType == 3) {
+ endOffset = endContainer.nodeValue.length;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Expands the node to the closes contentEditable false element if it exists
- function findParentContentEditable(node) {
- var parent = node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Expands the node to the closes contentEditable false element if it exists
+ function findParentContentEditable(node) {
+ var parent = node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (parent) {
- if (parent.nodeType === 1 && getContentEditable(parent)) {
- return getContentEditable(parent) === "false" ? parent : node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (parent) {
+ if (parent.nodeType === 1 && getContentEditable(parent)) {
+ return getContentEditable(parent) === "false" ? parent : node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parent = parent.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parent = parent.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function findWordEndPoint(container, offset, start) {
- var walker, node, pos, lastTextNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function findWordEndPoint(container, offset, start) {
+ var walker, node, pos, lastTextNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function findSpace(node, offset) {
- var pos, pos2, str = node.nodeValue;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function findSpace(node, offset) {
+ var pos, pos2, str = node.nodeValue;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof offset == "undefined") {
- offset = start ? str.length : 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof offset == "undefined") {
+ offset = start ? str.length : 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (start) {
- pos = str.lastIndexOf(' ', offset);
- pos2 = str.lastIndexOf('\u00a0', offset);
- pos = pos > pos2 ? pos : pos2;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (start) {
+ pos = str.lastIndexOf(' ', offset);
+ pos2 = str.lastIndexOf('\u00a0', offset);
+ pos = pos > pos2 ? pos : pos2;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Include the space on remove to avoid tag soup
- if (pos !== -1 && !remove) {
- pos++;
- }
- } else {
- pos = str.indexOf(' ', offset);
- pos2 = str.indexOf('\u00a0', offset);
- pos = pos !== -1 && (pos2 === -1 || pos < pos2) ? pos : pos2;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Include the space on remove to avoid tag soup
+ if (pos !== -1 && !remove) {
+ pos++;
+ }
+ } else {
+ pos = str.indexOf(' ', offset);
+ pos2 = str.indexOf('\u00a0', offset);
+ pos = pos !== -1 && (pos2 === -1 || pos < pos2) ? pos : pos2;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return pos;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return pos;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (container.nodeType === 3) {
- pos = findSpace(container, offset);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (container.nodeType === 3) {
+ pos = findSpace(container, offset);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (pos !== -1) {
- return {container: container, offset: pos};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (pos !== -1) {
+ return { container: container, offset: pos };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- lastTextNode = container;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ lastTextNode = container;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Walk the nodes inside the block
- walker = new TreeWalker(container, dom.getParent(container, isBlock) || ed.getBody());
- while ((node = walker[start ? 'prev' : 'next']())) {
- if (node.nodeType === 3) {
- lastTextNode = node;
- pos = findSpace(node);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Walk the nodes inside the block
+ walker = new TreeWalker(container, dom.getParent(container, isBlock) || ed.getBody());
+ while ((node = walker[start ? 'prev' : 'next']())) {
+ if (node.nodeType === 3) {
+ lastTextNode = node;
+ pos = findSpace(node);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (pos !== -1) {
- return {container: node, offset: pos};
- }
- } else if (isBlock(node)) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (pos !== -1) {
+ return { container: node, offset: pos };
+ }
+ } else if (isBlock(node)) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (lastTextNode) {
- if (start) {
- offset = 0;
- } else {
- offset = lastTextNode.length;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (lastTextNode) {
+ if (start) {
+ offset = 0;
+ } else {
+ offset = lastTextNode.length;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {container: lastTextNode, offset: offset};
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return { container: lastTextNode, offset: offset };
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function findSelectorEndPoint(container, sibling_name) {
- var parents, i, y, curFormat;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function findSelectorEndPoint(container, siblingName) {
+ var parents, i, y, curFormat;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (container.nodeType == 3 && container.nodeValue.length === 0 && container[sibling_name]) {
- container = container[sibling_name];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (container.nodeType == 3 && container.nodeValue.length === 0 && container[siblingName]) {
+ container = container[siblingName];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parents = getParents(container);
- for (i = 0; i < parents.length; i++) {
- for (y = 0; y < format.length; y++) {
- curFormat = format[y];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parents = getParents(container);
+ for (i = 0; i < parents.length; i++) {
+ for (y = 0; y < format.length; y++) {
+ curFormat = format[y];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If collapsed state is set then skip formats that doesn't match that
- if ("collapsed" in curFormat && curFormat.collapsed !== rng.collapsed) {
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If collapsed state is set then skip formats that doesn't match that
+ if ("collapsed" in curFormat && curFormat.collapsed !== rng.collapsed) {
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (dom.is(parents[i], curFormat.selector)) {
- return parents[i];
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (dom.is(parents[i], curFormat.selector)) {
+ return parents[i];
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return container;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return container;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function findBlockEndPoint(container, sibling_name) {
- var node, root = dom.getRoot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function findBlockEndPoint(container, siblingName) {
+ var node, root = dom.getRoot();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Expand to block of similar type
- if (!format[0].wrapper) {
- node = dom.getParent(container, format[0].block, root);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Expand to block of similar type
+ if (!format[0].wrapper) {
+ node = dom.getParent(container, format[0].block, root);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Expand to first wrappable block element or any block element
- if (!node) {
- node = dom.getParent(container.nodeType == 3 ? container.parentNode : container, function(node) {
- // Fixes #6183 where it would expand to editable parent element in inline mode
- return node != root && isTextBlock(node);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Expand to first wrappable block element or any block element
+ if (!node) {
+ node = dom.getParent(container.nodeType == 3 ? container.parentNode : container, function (node) {
+ // Fixes #6183 where it would expand to editable parent element in inline mode
+ return node != root && isTextBlock(node);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Exclude inner lists from wrapping
- if (node && format[0].wrapper) {
- node = getParents(node, 'ul,ol').reverse()[0] || node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Exclude inner lists from wrapping
+ if (node && format[0].wrapper) {
+ node = getParents(node, 'ul,ol').reverse()[0] || node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Didn't find a block element look for first/last wrappable element
- if (!node) {
- node = container;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Didn't find a block element look for first/last wrappable element
+ if (!node) {
+ node = container;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (node[sibling_name] && !isBlock(node[sibling_name])) {
- node = node[sibling_name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (node[siblingName] && !isBlock(node[siblingName])) {
+ node = node[siblingName];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Break on BR but include it will be removed later on
- // we can't remove it now since we need to check if it can be wrapped
- if (isEq(node, 'br')) {
- break;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Break on BR but include it will be removed later on
+ // we can't remove it now since we need to check if it can be wrapped
+ if (isEq(node, 'br')) {
+ break;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return node || container;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return node || container;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Expand to closest contentEditable element
- startContainer = findParentContentEditable(startContainer);
- endContainer = findParentContentEditable(endContainer);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Expand to closest contentEditable element
+ startContainer = findParentContentEditable(startContainer);
+ endContainer = findParentContentEditable(endContainer);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Exclude bookmark nodes if possible
- if (isBookmarkNode(startContainer.parentNode) || isBookmarkNode(startContainer)) {
- startContainer = isBookmarkNode(startContainer) ? startContainer : startContainer.parentNode;
- startContainer = startContainer.nextSibling || startContainer;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Exclude bookmark nodes if possible
+ if (isBookmarkNode(startContainer.parentNode) || isBookmarkNode(startContainer)) {
+ startContainer = isBookmarkNode(startContainer) ? startContainer : startContainer.parentNode;
+ startContainer = startContainer.nextSibling || startContainer;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (startContainer.nodeType == 3) {
- startOffset = 0;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (startContainer.nodeType == 3) {
+ startOffset = 0;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isBookmarkNode(endContainer.parentNode) || isBookmarkNode(endContainer)) {
- endContainer = isBookmarkNode(endContainer) ? endContainer : endContainer.parentNode;
- endContainer = endContainer.previousSibling || endContainer;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isBookmarkNode(endContainer.parentNode) || isBookmarkNode(endContainer)) {
+ endContainer = isBookmarkNode(endContainer) ? endContainer : endContainer.parentNode;
+ endContainer = endContainer.previousSibling || endContainer;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (endContainer.nodeType == 3) {
- endOffset = endContainer.length;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (endContainer.nodeType == 3) {
+ endOffset = endContainer.length;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (format[0].inline) {
- if (rng.collapsed) {
- // Expand left to closest word boundary
- endPoint = findWordEndPoint(startContainer, startOffset, true);
- if (endPoint) {
- startContainer = endPoint.container;
- startOffset = endPoint.offset;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (format[0].inline) {
+ if (rng.collapsed) {
+ // Expand left to closest word boundary
+ endPoint = findWordEndPoint(startContainer, startOffset, true);
+ if (endPoint) {
+ startContainer = endPoint.container;
+ startOffset = endPoint.offset;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Expand right to closest word boundary
- endPoint = findWordEndPoint(endContainer, endOffset);
- if (endPoint) {
- endContainer = endPoint.container;
- endOffset = endPoint.offset;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Expand right to closest word boundary
+ endPoint = findWordEndPoint(endContainer, endOffset);
+ if (endPoint) {
+ endContainer = endPoint.container;
+ endOffset = endPoint.offset;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Avoid applying formatting to a trailing space.
- leaf = findLeaf(endContainer, endOffset);
- if (leaf.node) {
- while (leaf.node && leaf.offset === 0 && leaf.node.previousSibling) {
- leaf = findLeaf(leaf.node.previousSibling);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Avoid applying formatting to a trailing space.
+ leaf = findLeaf(endContainer, endOffset);
+ if (leaf.node) {
+ while (leaf.node && leaf.offset === 0 && leaf.node.previousSibling) {
+ leaf = findLeaf(leaf.node.previousSibling);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (leaf.node && leaf.offset > 0 && leaf.node.nodeType === 3 &&
- leaf.node.nodeValue.charAt(leaf.offset - 1) === ' ') {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (leaf.node && leaf.offset > 0 && leaf.node.nodeType === 3 &&
+ leaf.node.nodeValue.charAt(leaf.offset - 1) === ' ') {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (leaf.offset > 1) {
- endContainer = leaf.node;
- endContainer.splitText(leaf.offset - 1);
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (leaf.offset > 1) {
+ endContainer = leaf.node;
+ endContainer.splitText(leaf.offset - 1);
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move start/end point up the tree if the leaves are sharp and if we are in different containers
- // Example * becomes !: !<p><b><i>*text</i><i>text*</i></b></p>!
- // This will reduce the number of wrapper elements that needs to be created
- // Move start point up the tree
- if (format[0].inline || format[0].block_expand) {
- if (!format[0].inline || (startContainer.nodeType != 3 || startOffset === 0)) {
- startContainer = findParentContainer(true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move start/end point up the tree if the leaves are sharp and if we are in different containers
+ // Example * becomes !: !<p><b><i>*text</i><i>text*</i></b></p>!
+ // This will reduce the number of wrapper elements that needs to be created
+ // Move start point up the tree
+ if (format[0].inline || format[0].block_expand) {
+ if (!format[0].inline || (startContainer.nodeType != 3 || startOffset === 0)) {
+ startContainer = findParentContainer(true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!format[0].inline || (endContainer.nodeType != 3 || endOffset === endContainer.nodeValue.length)) {
- endContainer = findParentContainer();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!format[0].inline || (endContainer.nodeType != 3 || endOffset === endContainer.nodeValue.length)) {
+ endContainer = findParentContainer();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Expand start/end container to matching selector
- if (format[0].selector && format[0].expand !== FALSE && !format[0].inline) {
- // Find new startContainer/endContainer if there is better one
- startContainer = findSelectorEndPoint(startContainer, 'previousSibling');
- endContainer = findSelectorEndPoint(endContainer, 'nextSibling');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Expand start/end container to matching selector
+ if (format[0].selector && format[0].expand !== FALSE && !format[0].inline) {
+ // Find new startContainer/endContainer if there is better one
+ startContainer = findSelectorEndPoint(startContainer, 'previousSibling');
+ endContainer = findSelectorEndPoint(endContainer, 'nextSibling');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Expand start/end container to matching block element or text node
- if (format[0].block || format[0].selector) {
- // Find new startContainer/endContainer if there is better one
- startContainer = findBlockEndPoint(startContainer, 'previousSibling');
- endContainer = findBlockEndPoint(endContainer, 'nextSibling');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Expand start/end container to matching block element or text node
+ if (format[0].block || format[0].selector) {
+ // Find new startContainer/endContainer if there is better one
+ startContainer = findBlockEndPoint(startContainer, 'previousSibling');
+ endContainer = findBlockEndPoint(endContainer, 'nextSibling');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Non block element then try to expand up the leaf
- if (format[0].block) {
- if (!isBlock(startContainer)) {
- startContainer = findParentContainer(true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Non block element then try to expand up the leaf
+ if (format[0].block) {
+ if (!isBlock(startContainer)) {
+ startContainer = findParentContainer(true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isBlock(endContainer)) {
- endContainer = findParentContainer();
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isBlock(endContainer)) {
+ endContainer = findParentContainer();
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup index for startContainer
- if (startContainer.nodeType == 1) {
- startOffset = nodeIndex(startContainer);
- startContainer = startContainer.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup index for startContainer
+ if (startContainer.nodeType == 1) {
+ startOffset = nodeIndex(startContainer);
+ startContainer = startContainer.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup index for endContainer
- if (endContainer.nodeType == 1) {
- endOffset = nodeIndex(endContainer) + 1;
- endContainer = endContainer.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup index for endContainer
+ if (endContainer.nodeType == 1) {
+ endOffset = nodeIndex(endContainer) + 1;
+ endContainer = endContainer.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Return new range like object
- return {
- startContainer: startContainer,
- startOffset: startOffset,
- endContainer: endContainer,
- endOffset: endOffset
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Return new range like object
+ return {
+ startContainer: startContainer,
+ startOffset: startOffset,
+ endContainer: endContainer,
+ endOffset: endOffset
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isColorFormatAndAnchor(node, format) {
- return format.links && node.tagName == 'A';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isColorFormatAndAnchor(node, format) {
+ return format.links && node.tagName == 'A';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes the specified format for the specified node. It will also remove the node if it doesn't have
- * any attributes if the format specifies it to do so.
- *
- * @private
- * @param {Object} format Format object with items to remove from node.
- * @param {Object} vars Name/value object with variables to apply to format.
- * @param {Node} node Node to remove the format styles on.
- * @param {Node} compare_node Optional compare node, if specified the styles will be compared to that node.
- * @return {Boolean} True/false if the node was removed or not.
- */
- function removeFormat(format, vars, node, compare_node) {
- var i, attrs, stylesModified;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes the specified format for the specified node. It will also remove the node if it doesn't have
+ * any attributes if the format specifies it to do so.
+ *
+ * @private
+ * @param {Object} format Format object with items to remove from node.
+ * @param {Object} vars Name/value object with variables to apply to format.
+ * @param {Node} node Node to remove the format styles on.
+ * @param {Node} compareNode Optional compare node, if specified the styles will be compared to that node.
+ * @return {Boolean} True/false if the node was removed or not.
+ */
+ function removeFormat(format, vars, node, compareNode) {
+ var i, attrs, stylesModified;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if node matches format
- if (!matchName(node, format) && !isColorFormatAndAnchor(node, format)) {
- return FALSE;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if node matches format
+ if (!matchName(node, format) && !isColorFormatAndAnchor(node, format)) {
+ return FALSE;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Should we compare with format attribs and styles
- if (format.remove != 'all') {
- // Remove styles
- each(format.styles, function(value, name) {
- value = normalizeStyleValue(replaceVars(value, vars), name);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Should we compare with format attribs and styles
+ if (format.remove != 'all') {
+ // Remove styles
+ each(format.styles, function (value, name) {
+ value = normalizeStyleValue(replaceVars(value, vars), name);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Indexed array
- if (typeof name === 'number') {
- name = value;
- compare_node = 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Indexed array
+ if (typeof name === 'number') {
+ name = value;
+ compareNode = 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (format.remove_similar || (!compare_node || isEq(getStyle(compare_node, name), value))) {
- dom.setStyle(node, name, '');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (format.remove_similar || (!compareNode || isEq(getStyle(compareNode, name), value))) {
+ dom.setStyle(node, name, '');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- stylesModified = 1;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ stylesModified = 1;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove style attribute if it's empty
- if (stylesModified && dom.getAttrib(node, 'style') === '') {
- node.removeAttribute('style');
- node.removeAttribute('data-mce-style');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove style attribute if it's empty
+ if (stylesModified && dom.getAttrib(node, 'style') === '') {
+ node.removeAttribute('style');
+ node.removeAttribute('data-mce-style');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove attributes
- each(format.attributes, function(value, name) {
- var valueOut;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove attributes
+ each(format.attributes, function (value, name) {
+ var valueOut;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- value = replaceVars(value, vars);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ value = replaceVars(value, vars);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Indexed array
- if (typeof name === 'number') {
- name = value;
- compare_node = 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Indexed array
+ if (typeof name === 'number') {
+ name = value;
+ compareNode = 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!compare_node || isEq(dom.getAttrib(compare_node, name), value)) {
- // Keep internal classes
- if (name == 'class') {
- value = dom.getAttrib(node, name);
- if (value) {
- // Build new class value where everything is removed except the internal prefixed classes
- valueOut = '';
- each(value.split(/\s+/), function(cls) {
- if (/mce\-\w+/.test(cls)) {
- valueOut += (valueOut ? ' ' : '') + cls;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!compareNode || isEq(dom.getAttrib(compareNode, name), value)) {
+ // Keep internal classes
+ if (name == 'class') {
+ value = dom.getAttrib(node, name);
+ if (value) {
+ // Build new class value where everything is removed except the internal prefixed classes
+ valueOut = '';
+ each(value.split(/\s+/), function (cls) {
+ if (/mce\-\w+/.test(cls)) {
+ valueOut += (valueOut ? ' ' : '') + cls;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // We got some internal classes left
- if (valueOut) {
- dom.setAttrib(node, name, valueOut);
- return;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // We got some internal classes left
+ if (valueOut) {
+ dom.setAttrib(node, name, valueOut);
+ return;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // IE6 has a bug where the attribute doesn't get removed correctly
- if (name == "class") {
- node.removeAttribute('className');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // IE6 has a bug where the attribute doesn't get removed correctly
+ if (name == "class") {
+ node.removeAttribute('className');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove mce prefixed attributes
- if (MCE_ATTR_RE.test(name)) {
- node.removeAttribute('data-mce-' + name);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove mce prefixed attributes
+ if (MCE_ATTR_RE.test(name)) {
+ node.removeAttribute('data-mce-' + name);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node.removeAttribute(name);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node.removeAttribute(name);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove classes
- each(format.classes, function(value) {
- value = replaceVars(value, vars);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove classes
+ each(format.classes, function (value) {
+ value = replaceVars(value, vars);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!compare_node || dom.hasClass(compare_node, value)) {
- dom.removeClass(node, value);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!compareNode || dom.hasClass(compareNode, value)) {
+ dom.removeClass(node, value);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check for non internal attributes
- attrs = dom.getAttribs(node);
- for (i = 0; i < attrs.length; i++) {
- var attrName = attrs[i].nodeName;
- if (attrName.indexOf('_') !== 0 && attrName.indexOf('data-') !== 0) {
- return FALSE;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check for non internal attributes
+ attrs = dom.getAttribs(node);
+ for (i = 0; i < attrs.length; i++) {
+ var attrName = attrs[i].nodeName;
+ if (attrName.indexOf('_') !== 0 && attrName.indexOf('data-') !== 0) {
+ return FALSE;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove the inline child if it's empty for example <b> or <span>
- if (format.remove != 'none') {
- removeNode(node, format);
- return TRUE;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove the inline child if it's empty for example <b> or <span>
+ if (format.remove != 'none') {
+ removeNode(node, format);
+ return TRUE;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes the node and wrap it's children in paragraphs before doing so or
- * appends BR elements to the beginning/end of the block element if forcedRootBlocks is disabled.
- *
- * If the div in the node below gets removed:
- * text<div>text</div>text
- *
- * Output becomes:
- * text<div><br />text<br /></div>text
- *
- * So when the div is removed the result is:
- * text<br />text<br />text
- *
- * @private
- * @param {Node} node Node to remove + apply BR/P elements to.
- * @param {Object} format Format rule.
- * @return {Node} Input node.
- */
- function removeNode(node, format) {
- var parentNode = node.parentNode, rootBlockElm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes the node and wrap it's children in paragraphs before doing so or
+ * appends BR elements to the beginning/end of the block element if forcedRootBlocks is disabled.
+ *
+ * If the div in the node below gets removed:
+ * text<div>text</div>text
+ *
+ * Output becomes:
+ * text<div><br />text<br /></div>text
+ *
+ * So when the div is removed the result is:
+ * text<br />text<br />text
+ *
+ * @private
+ * @param {Node} node Node to remove + apply BR/P elements to.
+ * @param {Object} format Format rule.
+ * @return {Node} Input node.
+ */
+ function removeNode(node, format) {
+ var parentNode = node.parentNode, rootBlockElm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function find(node, next, inc) {
- node = getNonWhiteSpaceSibling(node, next, inc);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function find(node, next, inc) {
+ node = getNonWhiteSpaceSibling(node, next, inc);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return !node || (node.nodeName == 'BR' || isBlock(node));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return !node || (node.nodeName == 'BR' || isBlock(node));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (format.block) {
- if (!forcedRootBlock) {
- // Append BR elements if needed before we remove the block
- if (isBlock(node) && !isBlock(parentNode)) {
- if (!find(node, FALSE) && !find(node.firstChild, TRUE, 1)) {
- node.insertBefore(dom.create('br'), node.firstChild);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (format.block) {
+ if (!forcedRootBlock) {
+ // Append BR elements if needed before we remove the block
+ if (isBlock(node) && !isBlock(parentNode)) {
+ if (!find(node, FALSE) && !find(node.firstChild, TRUE, 1)) {
+ node.insertBefore(dom.create('br'), node.firstChild);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!find(node, TRUE) && !find(node.lastChild, FALSE, 1)) {
- node.appendChild(dom.create('br'));
- }
- }
- } else {
- // Wrap the block in a forcedRootBlock if we are at the root of document
- if (parentNode == dom.getRoot()) {
- if (!format.list_block || !isEq(node, format.list_block)) {
- each(grep(node.childNodes), function(node) {
- if (isValid(forcedRootBlock, node.nodeName.toLowerCase())) {
- if (!rootBlockElm) {
- rootBlockElm = wrap(node, forcedRootBlock);
- dom.setAttribs(rootBlockElm, ed.settings.forced_root_block_attrs);
- } else {
- rootBlockElm.appendChild(node);
- }
- } else {
- rootBlockElm = 0;
- }
- });
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!find(node, TRUE) && !find(node.lastChild, FALSE, 1)) {
+ node.appendChild(dom.create('br'));
+ }
+ }
+ } else {
+ // Wrap the block in a forcedRootBlock if we are at the root of document
+ if (parentNode == dom.getRoot()) {
+ if (!format.list_block || !isEq(node, format.list_block)) {
+ each(grep(node.childNodes), function (node) {
+ if (isValid(forcedRootBlock, node.nodeName.toLowerCase())) {
+ if (!rootBlockElm) {
+ rootBlockElm = wrap(node, forcedRootBlock);
+ dom.setAttribs(rootBlockElm, ed.settings.forced_root_block_attrs);
+ } else {
+ rootBlockElm.appendChild(node);
+ }
+ } else {
+ rootBlockElm = 0;
+ }
+ });
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Never remove nodes that isn't the specified inline element if a selector is specified too
- if (format.selector && format.inline && !isEq(format.inline, node)) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Never remove nodes that isn't the specified inline element if a selector is specified too
+ if (format.selector && format.inline && !isEq(format.inline, node)) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.remove(node, 1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.remove(node, 1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the next/previous non whitespace node.
- *
- * @private
- * @param {Node} node Node to start at.
- * @param {boolean} next (Optional) Include next or previous node defaults to previous.
- * @param {boolean} inc (Optional) Include the current node in checking. Defaults to false.
- * @return {Node} Next or previous node or undefined if it wasn't found.
- */
- function getNonWhiteSpaceSibling(node, next, inc) {
- if (node) {
- next = next ? 'nextSibling' : 'previousSibling';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the next/previous non whitespace node.
+ *
+ * @private
+ * @param {Node} node Node to start at.
+ * @param {boolean} next (Optional) Include next or previous node defaults to previous.
+ * @param {boolean} inc (Optional) Include the current node in checking. Defaults to false.
+ * @return {Node} Next or previous node or undefined if it wasn't found.
+ */
+ function getNonWhiteSpaceSibling(node, next, inc) {
+ if (node) {
+ next = next ? 'nextSibling' : 'previousSibling';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (node = inc ? node : node[next]; node; node = node[next]) {
- if (node.nodeType == 1 || !isWhiteSpaceNode(node)) {
- return node;
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (node = inc ? node : node[next]; node; node = node[next]) {
+ if (node.nodeType == 1 || !isWhiteSpaceNode(node)) {
+ return node;
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Merges the next/previous sibling element if they match.
- *
- * @private
- * @param {Node} prev Previous node to compare/merge.
- * @param {Node} next Next node to compare/merge.
- * @return {Node} Next node if we didn't merge and prev node if we did.
- */
- function mergeSiblings(prev, next) {
- var sibling, tmpSibling, elementUtils = new ElementUtils(dom);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Merges the next/previous sibling element if they match.
+ *
+ * @private
+ * @param {Node} prev Previous node to compare/merge.
+ * @param {Node} next Next node to compare/merge.
+ * @return {Node} Next node if we didn't merge and prev node if we did.
+ */
+ function mergeSiblings(prev, next) {
+ var sibling, tmpSibling, elementUtils = new ElementUtils(dom);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function findElementSibling(node, sibling_name) {
- for (sibling = node; sibling; sibling = sibling[sibling_name]) {
- if (sibling.nodeType == 3 && sibling.nodeValue.length !== 0) {
- return node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function findElementSibling(node, siblingName) {
+ for (sibling = node; sibling; sibling = sibling[siblingName]) {
+ if (sibling.nodeType == 3 && sibling.nodeValue.length !== 0) {
+ return node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (sibling.nodeType == 1 && !isBookmarkNode(sibling)) {
- return sibling;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (sibling.nodeType == 1 && !isBookmarkNode(sibling)) {
+ return sibling;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if next/prev exists and that they are elements
- if (prev && next) {
- // If previous sibling is empty then jump over it
- prev = findElementSibling(prev, 'previousSibling');
- next = findElementSibling(next, 'nextSibling');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if next/prev exists and that they are elements
+ if (prev && next) {
+ // If previous sibling is empty then jump over it
+ prev = findElementSibling(prev, 'previousSibling');
+ next = findElementSibling(next, 'nextSibling');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Compare next and previous nodes
- if (elementUtils.compare(prev, next)) {
- // Append nodes between
- for (sibling = prev.nextSibling; sibling && sibling != next;) {
- tmpSibling = sibling;
- sibling = sibling.nextSibling;
- prev.appendChild(tmpSibling);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Compare next and previous nodes
+ if (elementUtils.compare(prev, next)) {
+ // Append nodes between
+ for (sibling = prev.nextSibling; sibling && sibling != next;) {
+ tmpSibling = sibling;
+ sibling = sibling.nextSibling;
+ prev.appendChild(tmpSibling);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove next node
- dom.remove(next);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove next node
+ dom.remove(next);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move children into prev node
- each(grep(next.childNodes), function(node) {
- prev.appendChild(node);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move children into prev node
+ each(grep(next.childNodes), function (node) {
+ prev.appendChild(node);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return prev;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return prev;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return next;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return next;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getContainer(rng, start) {
- var container, offset, lastIdx;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getContainer(rng, start) {
+ var container, offset, lastIdx;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = rng[start ? 'startContainer' : 'endContainer'];
- offset = rng[start ? 'startOffset' : 'endOffset'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = rng[start ? 'startContainer' : 'endContainer'];
+ offset = rng[start ? 'startOffset' : 'endOffset'];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (container.nodeType == 1) {
- lastIdx = container.childNodes.length - 1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (container.nodeType == 1) {
+ lastIdx = container.childNodes.length - 1;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!start && offset) {
- offset--;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!start && offset) {
+ offset--;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = container.childNodes[offset > lastIdx ? lastIdx : offset];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = container.childNodes[offset > lastIdx ? lastIdx : offset];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If start text node is excluded then walk to the next node
- if (container.nodeType === 3 && start && offset >= container.nodeValue.length) {
- container = new TreeWalker(container, ed.getBody()).next() || container;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If start text node is excluded then walk to the next node
+ if (container.nodeType === 3 && start && offset >= container.nodeValue.length) {
+ container = new TreeWalker(container, ed.getBody()).next() || container;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If end text node is excluded then walk to the previous node
- if (container.nodeType === 3 && !start && offset === 0) {
- container = new TreeWalker(container, ed.getBody()).prev() || container;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If end text node is excluded then walk to the previous node
+ if (container.nodeType === 3 && !start && offset === 0) {
+ container = new TreeWalker(container, ed.getBody()).prev() || container;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return container;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return container;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function performCaretAction(type, name, vars, similar) {
- var caretContainerId = '_mce_caret', debug = ed.settings.caret_debug;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function performCaretAction(type, name, vars, similar) {
+ var caretContainerId = '_mce_caret', debug = ed.settings.caret_debug;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Creates a caret container bogus element
- function createCaretContainer(fill) {
- var caretContainer = dom.create('span', {id: caretContainerId, 'data-mce-bogus': true, style: debug ? 'color:red' : ''});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Creates a caret container bogus element
+ function createCaretContainer(fill) {
+ var caretContainer = dom.create('span', { id: caretContainerId, 'data-mce-bogus': true, style: debug ? 'color:red' : '' });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (fill) {
- caretContainer.appendChild(ed.getDoc().createTextNode(INVISIBLE_CHAR));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (fill) {
+ caretContainer.appendChild(ed.getDoc().createTextNode(INVISIBLE_CHAR));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return caretContainer;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return caretContainer;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isCaretContainerEmpty(node, nodes) {
- while (node) {
- if ((node.nodeType === 3 && node.nodeValue !== INVISIBLE_CHAR) || node.childNodes.length > 1) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isCaretContainerEmpty(node, nodes) {
+ while (node) {
+ if ((node.nodeType === 3 && node.nodeValue !== INVISIBLE_CHAR) || node.childNodes.length > 1) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Collect nodes
- if (nodes && node.nodeType === 1) {
- nodes.push(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Collect nodes
+ if (nodes && node.nodeType === 1) {
+ nodes.push(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.firstChild;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node.firstChild;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Returns any parent caret container element
- function getParentCaretContainer(node) {
- while (node) {
- if (node.id === caretContainerId) {
- return node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Returns any parent caret container element
+ function getParentCaretContainer(node) {
+ while (node) {
+ if (node.id === caretContainerId) {
+ return node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.parentNode;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node.parentNode;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Finds the first text node in the specified node
- function findFirstTextNode(node) {
- var walker;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Finds the first text node in the specified node
+ function findFirstTextNode(node) {
+ var walker;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node) {
- walker = new TreeWalker(node, node);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node) {
+ walker = new TreeWalker(node, node);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (node = walker.current(); node; node = walker.next()) {
- if (node.nodeType === 3) {
- return node;
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (node = walker.current(); node; node = walker.next()) {
+ if (node.nodeType === 3) {
+ return node;
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Removes the caret container for the specified node or all on the current document
- function removeCaretContainer(node, move_caret) {
- var child, rng;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Removes the caret container for the specified node or all on the current document
+ function removeCaretContainer(node, moveCaret) {
+ var child, rng;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!node) {
- node = getParentCaretContainer(selection.getStart());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!node) {
+ node = getParentCaretContainer(selection.getStart());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!node) {
- while ((node = dom.get(caretContainerId))) {
- removeCaretContainer(node, false);
- }
- }
- } else {
- rng = selection.getRng(true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!node) {
+ while ((node = dom.get(caretContainerId))) {
+ removeCaretContainer(node, false);
+ }
+ }
+ } else {
+ rng = selection.getRng(true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isCaretContainerEmpty(node)) {
- if (move_caret !== false) {
- rng.setStartBefore(node);
- rng.setEndBefore(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isCaretContainerEmpty(node)) {
+ if (moveCaret !== false) {
+ rng.setStartBefore(node);
+ rng.setEndBefore(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.remove(node);
- } else {
- child = findFirstTextNode(node);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.remove(node);
+ } else {
+ child = findFirstTextNode(node);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (child.nodeValue.charAt(0) === INVISIBLE_CHAR) {
- child.deleteData(0, 1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (child.nodeValue.charAt(0) === INVISIBLE_CHAR) {
+ child.deleteData(0, 1);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Fix for bug #6976
- if (rng.startContainer == child && rng.startOffset > 0) {
- rng.setStart(child, rng.startOffset - 1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Fix for bug #6976
+ if (rng.startContainer == child && rng.startOffset > 0) {
+ rng.setStart(child, rng.startOffset - 1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rng.endContainer == child && rng.endOffset > 0) {
- rng.setEnd(child, rng.endOffset - 1);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rng.endContainer == child && rng.endOffset > 0) {
+ rng.setEnd(child, rng.endOffset - 1);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.remove(node, 1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.remove(node, 1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- selection.setRng(rng);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ selection.setRng(rng);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Applies formatting to the caret position
- function applyCaretFormat() {
- var rng, caretContainer, textNode, offset, bookmark, container, text;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Applies formatting to the caret position
+ function applyCaretFormat() {
+ var rng, caretContainer, textNode, offset, bookmark, container, text;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng = selection.getRng(true);
- offset = rng.startOffset;
- container = rng.startContainer;
- text = container.nodeValue;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng = selection.getRng(true);
+ offset = rng.startOffset;
+ container = rng.startContainer;
+ text = container.nodeValue;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- caretContainer = getParentCaretContainer(selection.getStart());
- if (caretContainer) {
- textNode = findFirstTextNode(caretContainer);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ caretContainer = getParentCaretContainer(selection.getStart());
+ if (caretContainer) {
+ textNode = findFirstTextNode(caretContainer);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Expand to word if caret is in the middle of a text node and the char before/after is a alpha numeric character
- var wordcharRegex = /[^\s\u00a0\u00ad\u200b\ufeff]/;
- if (text && offset > 0 && offset < text.length &&
- wordcharRegex.test(text.charAt(offset)) && wordcharRegex.test(text.charAt(offset - 1))) {
- // Get bookmark of caret position
- bookmark = selection.getBookmark();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Expand to word if caret is in the middle of a text node and the char before/after is a alpha numeric character
+ var wordcharRegex = /[^\s\u00a0\u00ad\u200b\ufeff]/;
+ if (text && offset > 0 && offset < text.length &&
+ wordcharRegex.test(text.charAt(offset)) && wordcharRegex.test(text.charAt(offset - 1))) {
+ // Get bookmark of caret position
+ bookmark = selection.getBookmark();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Collapse bookmark range (WebKit)
- rng.collapse(true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Collapse bookmark range (WebKit)
+ rng.collapse(true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Expand the range to the closest word and split it at those points
- rng = expandRng(rng, get(name));
- rng = rangeUtils.split(rng);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Expand the range to the closest word and split it at those points
+ rng = expandRng(rng, get(name));
+ rng = rangeUtils.split(rng);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Apply the format to the range
- apply(name, vars, rng);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Apply the format to the range
+ apply(name, vars, rng);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move selection back to caret position
- selection.moveToBookmark(bookmark);
- } else {
- if (!caretContainer || textNode.nodeValue !== INVISIBLE_CHAR) {
- caretContainer = createCaretContainer(true);
- textNode = caretContainer.firstChild;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move selection back to caret position
+ selection.moveToBookmark(bookmark);
+ } else {
+ if (!caretContainer || textNode.nodeValue !== INVISIBLE_CHAR) {
+ caretContainer = createCaretContainer(true);
+ textNode = caretContainer.firstChild;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng.insertNode(caretContainer);
- offset = 1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng.insertNode(caretContainer);
+ offset = 1;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- apply(name, vars, caretContainer);
- } else {
- apply(name, vars, caretContainer);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ apply(name, vars, caretContainer);
+ } else {
+ apply(name, vars, caretContainer);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move selection to text node
- selection.setCursorLocation(textNode, offset);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move selection to text node
+ selection.setCursorLocation(textNode, offset);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function removeCaretFormat() {
- var rng = selection.getRng(true), container, offset, bookmark,
- hasContentAfter, node, formatNode, parents = [], i, caretContainer;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function removeCaretFormat() {
+ var rng = selection.getRng(true), container, offset, bookmark,
+ hasContentAfter, node, formatNode, parents = [], i, caretContainer;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = rng.startContainer;
- offset = rng.startOffset;
- node = container;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = rng.startContainer;
+ offset = rng.startOffset;
+ node = container;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (container.nodeType == 3) {
- if (offset != container.nodeValue.length) {
- hasContentAfter = true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (container.nodeType == 3) {
+ if (offset != container.nodeValue.length) {
+ hasContentAfter = true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (node) {
- if (matchNode(node, name, vars, similar)) {
- formatNode = node;
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (node) {
+ if (matchNode(node, name, vars, similar)) {
+ formatNode = node;
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.nextSibling) {
- hasContentAfter = true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.nextSibling) {
+ hasContentAfter = true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parents.push(node);
- node = node.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parents.push(node);
+ node = node.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Node doesn't have the specified format
- if (!formatNode) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Node doesn't have the specified format
+ if (!formatNode) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Is there contents after the caret then remove the format on the element
- if (hasContentAfter) {
- // Get bookmark of caret position
- bookmark = selection.getBookmark();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Is there contents after the caret then remove the format on the element
+ if (hasContentAfter) {
+ // Get bookmark of caret position
+ bookmark = selection.getBookmark();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Collapse bookmark range (WebKit)
- rng.collapse(true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Collapse bookmark range (WebKit)
+ rng.collapse(true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Expand the range to the closest word and split it at those points
- rng = expandRng(rng, get(name), true);
- rng = rangeUtils.split(rng);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Expand the range to the closest word and split it at those points
+ rng = expandRng(rng, get(name), true);
+ rng = rangeUtils.split(rng);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove the format from the range
- remove(name, vars, rng);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove the format from the range
+ remove(name, vars, rng);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move selection back to caret position
- selection.moveToBookmark(bookmark);
- } else {
- caretContainer = createCaretContainer();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move selection back to caret position
+ selection.moveToBookmark(bookmark);
+ } else {
+ caretContainer = createCaretContainer();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = caretContainer;
- for (i = parents.length - 1; i >= 0; i--) {
- node.appendChild(dom.clone(parents[i], false));
- node = node.firstChild;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = caretContainer;
+ for (i = parents.length - 1; i >= 0; i--) {
+ node.appendChild(dom.clone(parents[i], false));
+ node = node.firstChild;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Insert invisible character into inner most format element
- node.appendChild(dom.doc.createTextNode(INVISIBLE_CHAR));
- node = node.firstChild;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Insert invisible character into inner most format element
+ node.appendChild(dom.doc.createTextNode(INVISIBLE_CHAR));
+ node = node.firstChild;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var block = dom.getParent(formatNode, isTextBlock);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var block = dom.getParent(formatNode, isTextBlock);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (block && dom.isEmpty(block)) {
- // Replace formatNode with caretContainer when removing format from empty block like <p><b>|</b></p>
- formatNode.parentNode.replaceChild(caretContainer, formatNode);
- } else {
- // Insert caret container after the formatted node
- dom.insertAfter(caretContainer, formatNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (block && dom.isEmpty(block)) {
+ // Replace formatNode with caretContainer when removing format from empty block like <p><b>|</b></p>
+ formatNode.parentNode.replaceChild(caretContainer, formatNode);
+ } else {
+ // Insert caret container after the formatted node
+ dom.insertAfter(caretContainer, formatNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move selection to text node
- selection.setCursorLocation(node, 1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move selection to text node
+ selection.setCursorLocation(node, 1);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If the formatNode is empty, we can remove it safely.
- if (dom.isEmpty(formatNode)) {
- dom.remove(formatNode);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If the formatNode is empty, we can remove it safely.
+ if (dom.isEmpty(formatNode)) {
+ dom.remove(formatNode);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Checks if the parent caret container node isn't empty if that is the case it
- // will remove the bogus state on all children that isn't empty
- function unmarkBogusCaretParents() {
- var caretContainer;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Checks if the parent caret container node isn't empty if that is the case it
+ // will remove the bogus state on all children that isn't empty
+ function unmarkBogusCaretParents() {
+ var caretContainer;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- caretContainer = getParentCaretContainer(selection.getStart());
- if (caretContainer && !dom.isEmpty(caretContainer)) {
- walk(caretContainer, function(node) {
- if (node.nodeType == 1 && node.id !== caretContainerId && !dom.isEmpty(node)) {
- dom.setAttrib(node, 'data-mce-bogus', null);
- }
- }, 'childNodes');
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ caretContainer = getParentCaretContainer(selection.getStart());
+ if (caretContainer && !dom.isEmpty(caretContainer)) {
+ walk(caretContainer, function (node) {
+ if (node.nodeType == 1 && node.id !== caretContainerId && !dom.isEmpty(node)) {
+ dom.setAttrib(node, 'data-mce-bogus', null);
+ }
+ }, 'childNodes');
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Only bind the caret events once
- if (!ed._hasCaretEvents) {
- // Mark current caret container elements as bogus when getting the contents so we don't end up with empty elements
- markCaretContainersBogus = function() {
- var nodes = [], i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Only bind the caret events once
+ if (!ed._hasCaretEvents) {
+ // Mark current caret container elements as bogus when getting the contents so we don't end up with empty elements
+ markCaretContainersBogus = function () {
+ var nodes = [], i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isCaretContainerEmpty(getParentCaretContainer(selection.getStart()), nodes)) {
- // Mark children
- i = nodes.length;
- while (i--) {
- dom.setAttrib(nodes[i], 'data-mce-bogus', '1');
- }
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isCaretContainerEmpty(getParentCaretContainer(selection.getStart()), nodes)) {
+ // Mark children
+ i = nodes.length;
+ while (i--) {
+ dom.setAttrib(nodes[i], 'data-mce-bogus', '1');
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- disableCaretContainer = function(e) {
- var keyCode = e.keyCode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ disableCaretContainer = function (e) {
+ var keyCode = e.keyCode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- removeCaretContainer();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ removeCaretContainer();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove caret container if it's empty
- if (keyCode == 8 && selection.isCollapsed() && selection.getStart().innerHTML == INVISIBLE_CHAR) {
- removeCaretContainer(getParentCaretContainer(selection.getStart()));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove caret container if it's empty
+ if (keyCode == 8 && selection.isCollapsed() && selection.getStart().innerHTML == INVISIBLE_CHAR) {
+ removeCaretContainer(getParentCaretContainer(selection.getStart()));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove caret container on keydown and it's left/right arrow keys
- if (keyCode == 37 || keyCode == 39) {
- removeCaretContainer(getParentCaretContainer(selection.getStart()));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove caret container on keydown and it's left/right arrow keys
+ if (keyCode == 37 || keyCode == 39) {
+ removeCaretContainer(getParentCaretContainer(selection.getStart()));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- unmarkBogusCaretParents();
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ unmarkBogusCaretParents();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove bogus state if they got filled by contents using editor.selection.setContent
- ed.on('SetContent', function(e) {
- if (e.selection) {
- unmarkBogusCaretParents();
- }
- });
- ed._hasCaretEvents = true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove bogus state if they got filled by contents using editor.selection.setContent
+ ed.on('SetContent', function (e) {
+ if (e.selection) {
+ unmarkBogusCaretParents();
+ }
+ });
+ ed._hasCaretEvents = true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Do apply or remove caret format
- if (type == "apply") {
- applyCaretFormat();
- } else {
- removeCaretFormat();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Do apply or remove caret format
+ if (type == "apply") {
+ applyCaretFormat();
+ } else {
+ removeCaretFormat();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Moves the start to the first suitable text node.
- */
- function moveStart(rng) {
- var container = rng.startContainer,
- offset = rng.startOffset, isAtEndOfText,
- walker, node, nodes, tmpNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Moves the start to the first suitable text node.
+ */
+ function moveStart(rng) {
+ var container = rng.startContainer,
+ offset = rng.startOffset, isAtEndOfText,
+ walker, node, nodes, tmpNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rng.startContainer == rng.endContainer) {
- if (isInlineBlock(rng.startContainer.childNodes[rng.startOffset])) {
- return;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rng.startContainer == rng.endContainer) {
+ if (isInlineBlock(rng.startContainer.childNodes[rng.startOffset])) {
+ return;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Convert text node into index if possible
- if (container.nodeType == 3 && offset >= container.nodeValue.length) {
- // Get the parent container location and walk from there
- offset = nodeIndex(container);
- container = container.parentNode;
- isAtEndOfText = true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Convert text node into index if possible
+ if (container.nodeType == 3 && offset >= container.nodeValue.length) {
+ // Get the parent container location and walk from there
+ offset = nodeIndex(container);
+ container = container.parentNode;
+ isAtEndOfText = true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move startContainer/startOffset in to a suitable node
- if (container.nodeType == 1) {
- nodes = container.childNodes;
- container = nodes[Math.min(offset, nodes.length - 1)];
- walker = new TreeWalker(container, dom.getParent(container, dom.isBlock));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move startContainer/startOffset in to a suitable node
+ if (container.nodeType == 1) {
+ nodes = container.childNodes;
+ container = nodes[Math.min(offset, nodes.length - 1)];
+ walker = new TreeWalker(container, dom.getParent(container, dom.isBlock));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If offset is at end of the parent node walk to the next one
- if (offset > nodes.length - 1 || isAtEndOfText) {
- walker.next();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If offset is at end of the parent node walk to the next one
+ if (offset > nodes.length - 1 || isAtEndOfText) {
+ walker.next();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (node = walker.current(); node; node = walker.next()) {
- if (node.nodeType == 3 && !isWhiteSpaceNode(node)) {
- // IE has a "neat" feature where it moves the start node into the closest element
- // we can avoid this by inserting an element before it and then remove it after we set the selection
- tmpNode = dom.create('a', {'data-mce-bogus': 'all'}, INVISIBLE_CHAR);
- node.parentNode.insertBefore(tmpNode, node);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (node = walker.current(); node; node = walker.next()) {
+ if (node.nodeType == 3 && !isWhiteSpaceNode(node)) {
+ // IE has a "neat" feature where it moves the start node into the closest element
+ // we can avoid this by inserting an element before it and then remove it after we set the selection
+ tmpNode = dom.create('a', { 'data-mce-bogus': 'all' }, INVISIBLE_CHAR);
+ node.parentNode.insertBefore(tmpNode, node);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set selection and remove tmpNode
- rng.setStart(node, 0);
- selection.setRng(rng);
- dom.remove(tmpNode);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set selection and remove tmpNode
+ rng.setStart(node, 0);
+ selection.setRng(rng);
+ dom.remove(tmpNode);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
- }
- }
- }
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
+ }
+ }
+ }
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/undo/Diff.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Diff.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -21783,150 +22797,151 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.undo.Diff
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/undo/Diff", [
-], function () {
- var KEEP = 0, INSERT = 1, DELETE = 2;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.undo.Diff',
+ [
+ ],
+ function () {
+ var KEEP = 0, INSERT = 1, DELETE = 2;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var diff = function (left, right) {
- var size = left.length + right.length + 2;
- var vDown = new Array(size);
- var vUp = new Array(size);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var diff = function (left, right) {
+ var size = left.length + right.length + 2;
+ var vDown = new Array(size);
+ var vUp = new Array(size);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var snake = function (start, end, diag) {
- return {
- start: start,
- end: end,
- diag: diag
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var snake = function (start, end, diag) {
+ return {
+ start: start,
+ end: end,
+ diag: diag
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var buildScript = function (start1, end1, start2, end2, script) {
- var middle = getMiddleSnake(start1, end1, start2, end2);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var buildScript = function (start1, end1, start2, end2, script) {
+ var middle = getMiddleSnake(start1, end1, start2, end2);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (middle === null || middle.start === end1 && middle.diag === end1 - end2 ||
- middle.end === start1 && middle.diag === start1 - start2) {
- var i = start1;
- var j = start2;
- while (i < end1 || j < end2) {
- if (i < end1 && j < end2 && left[i] === right[j]) {
- script.push([KEEP, left[i]]);
- ++i;
- ++j;
- } else {
- if (end1 - start1 > end2 - start2) {
- script.push([DELETE, left[i]]);
- ++i;
- } else {
- script.push([INSERT, right[j]]);
- ++j;
- }
- }
- }
- } else {
- buildScript(start1, middle.start, start2, middle.start - middle.diag, script);
- for (var i2 = middle.start; i2 < middle.end; ++i2) {
- script.push([KEEP, left[i2]]);
- }
- buildScript(middle.end, end1, middle.end - middle.diag, end2, script);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (middle === null || middle.start === end1 && middle.diag === end1 - end2 ||
+ middle.end === start1 && middle.diag === start1 - start2) {
+ var i = start1;
+ var j = start2;
+ while (i < end1 || j < end2) {
+ if (i < end1 && j < end2 && left[i] === right[j]) {
+ script.push([KEEP, left[i]]);
+ ++i;
+ ++j;
+ } else {
+ if (end1 - start1 > end2 - start2) {
+ script.push([DELETE, left[i]]);
+ ++i;
+ } else {
+ script.push([INSERT, right[j]]);
+ ++j;
+ }
+ }
+ }
+ } else {
+ buildScript(start1, middle.start, start2, middle.start - middle.diag, script);
+ for (var i2 = middle.start; i2 < middle.end; ++i2) {
+ script.push([KEEP, left[i2]]);
+ }
+ buildScript(middle.end, end1, middle.end - middle.diag, end2, script);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var buildSnake = function (start, diag, end1, end2) {
- var end = start;
- while (end - diag < end2 && end < end1 && left[end] === right[end - diag]) {
- ++end;
- }
- return snake(start, end, diag);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var buildSnake = function (start, diag, end1, end2) {
+ var end = start;
+ while (end - diag < end2 && end < end1 && left[end] === right[end - diag]) {
+ ++end;
+ }
+ return snake(start, end, diag);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getMiddleSnake = function (start1, end1, start2, end2) {
- // Myers Algorithm
- // Initialisations
- var m = end1 - start1;
- var n = end2 - start2;
- if (m === 0 || n === 0) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getMiddleSnake = function (start1, end1, start2, end2) {
+ // Myers Algorithm
+ // Initialisations
+ var m = end1 - start1;
+ var n = end2 - start2;
+ if (m === 0 || n === 0) {
+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var delta = m - n;
- var sum = n + m;
- var offset = (sum % 2 === 0 ? sum : sum + 1) / 2;
- vDown[1 + offset] = start1;
- vUp[1 + offset] = end1 + 1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var delta = m - n;
+ var sum = n + m;
+ var offset = (sum % 2 === 0 ? sum : sum + 1) / 2;
+ vDown[1 + offset] = start1;
+ vUp[1 + offset] = end1 + 1;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var d = 0; d <= offset; ++d) {
- // Down
- for (var k = -d; k <= d; k += 2) {
- // First step
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (var d = 0; d <= offset; ++d) {
+ // Down
+ for (var k = -d; k <= d; k += 2) {
+ // First step
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var i = k + offset;
- if (k === -d || k != d && vDown[i - 1] < vDown[i + 1]) {
- vDown[i] = vDown[i + 1];
- } else {
- vDown[i] = vDown[i - 1] + 1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var i = k + offset;
+ if (k === -d || k != d && vDown[i - 1] < vDown[i + 1]) {
+ vDown[i] = vDown[i + 1];
+ } else {
+ vDown[i] = vDown[i - 1] + 1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var x = vDown[i];
- var y = x - start1 + start2 - k;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var x = vDown[i];
+ var y = x - start1 + start2 - k;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (x < end1 && y < end2 && left[x] === right[y]) {
- vDown[i] = ++x;
- ++y;
- }
- // Second step
- if (delta % 2 != 0 && delta - d <= k && k <= delta + d) {
- if (vUp[i - delta] <= vDown[i]) {
- return buildSnake(vUp[i - delta], k + start1 - start2, end1, end2);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (x < end1 && y < end2 && left[x] === right[y]) {
+ vDown[i] = ++x;
+ ++y;
+ }
+ // Second step
+ if (delta % 2 != 0 && delta - d <= k && k <= delta + d) {
+ if (vUp[i - delta] <= vDown[i]) {
+ return buildSnake(vUp[i - delta], k + start1 - start2, end1, end2);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Up
- for (k = delta - d; k <= delta + d; k += 2) {
- // First step
- i = k + offset - delta;
- if (k === delta - d || k != delta + d && vUp[i + 1] <= vUp[i - 1]) {
- vUp[i] = vUp[i + 1] - 1;
- } else {
- vUp[i] = vUp[i - 1];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Up
+ for (k = delta - d; k <= delta + d; k += 2) {
+ // First step
+ i = k + offset - delta;
+ if (k === delta - d || k != delta + d && vUp[i + 1] <= vUp[i - 1]) {
+ vUp[i] = vUp[i + 1] - 1;
+ } else {
+ vUp[i] = vUp[i - 1];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- x = vUp[i] - 1;
- y = x - start1 + start2 - k;
- while (x >= start1 && y >= start2 && left[x] === right[y]) {
- vUp[i] = x--;
- y--;
- }
- // Second step
- if (delta % 2 === 0 && -d <= k && k <= d) {
- if (vUp[i] <= vDown[i + delta]) {
- return buildSnake(vUp[i], k + start1 - start2, end1, end2);
- }
- }
- }
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ x = vUp[i] - 1;
+ y = x - start1 + start2 - k;
+ while (x >= start1 && y >= start2 && left[x] === right[y]) {
+ vUp[i] = x--;
+ y--;
+ }
+ // Second step
+ if (delta % 2 === 0 && -d <= k && k <= d) {
+ if (vUp[i] <= vDown[i + delta]) {
+ return buildSnake(vUp[i], k + start1 - start2, end1, end2);
+ }
+ }
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var script = [];
- buildScript(0, left.length, 0, right.length, script);
- return script;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var script = [];
+ buildScript(0, left.length, 0, right.length, script);
+ return script;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- KEEP: KEEP,
- DELETE: DELETE,
- INSERT: INSERT,
- diff: diff
- };
-});
-
-// Included from: js/tinymce/classes/undo/Fragments.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ KEEP: KEEP,
+ DELETE: DELETE,
+ INSERT: INSERT,
+ diff: diff
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Fragments.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -21938,94 +22953,95 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.undo.Fragments
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/undo/Fragments", [
- "tinymce/util/Arr",
- "tinymce/html/Entities",
- "tinymce/undo/Diff"
-], function (Arr, Entities, Diff) {
- var getOuterHtml = function (elm) {
- if (elm.nodeType === 1) {
- return elm.outerHTML;
- } else if (elm.nodeType === 3) {
- return Entities.encodeRaw(elm.data, false);
- } else if (elm.nodeType === 8) {
- return '<!--' + elm.data + '-->';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.undo.Fragments',
+ [
+ "tinymce.core.util.Arr",
+ "tinymce.core.html.Entities",
+ "tinymce.core.undo.Diff"
+ ],
+ function (Arr, Entities, Diff) {
+ var getOuterHtml = function (elm) {
+ if (elm.nodeType === 1) {
+ return elm.outerHTML;
+ } else if (elm.nodeType === 3) {
+ return Entities.encodeRaw(elm.data, false);
+ } else if (elm.nodeType === 8) {
+ return '<!--' + elm.data + '-->';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return '';
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return '';
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var createFragment = function(html) {
- var frag, node, container;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createFragment = function (html) {
+ var frag, node, container;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = document.createElement("div");
- frag = document.createDocumentFragment();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = document.createElement("div");
+ frag = document.createDocumentFragment();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (html) {
- container.innerHTML = html;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (html) {
+ container.innerHTML = html;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while ((node = container.firstChild)) {
- frag.appendChild(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while ((node = container.firstChild)) {
+ frag.appendChild(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return frag;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return frag;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var insertAt = function (elm, html, index) {
- var fragment = createFragment(html);
- if (elm.hasChildNodes() && index < elm.childNodes.length) {
- var target = elm.childNodes[index];
- target.parentNode.insertBefore(fragment, target);
- } else {
- elm.appendChild(fragment);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var insertAt = function (elm, html, index) {
+ var fragment = createFragment(html);
+ if (elm.hasChildNodes() && index < elm.childNodes.length) {
+ var target = elm.childNodes[index];
+ target.parentNode.insertBefore(fragment, target);
+ } else {
+ elm.appendChild(fragment);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var removeAt = function (elm, index) {
- if (elm.hasChildNodes() && index < elm.childNodes.length) {
- var target = elm.childNodes[index];
- target.parentNode.removeChild(target);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var removeAt = function (elm, index) {
+ if (elm.hasChildNodes() && index < elm.childNodes.length) {
+ var target = elm.childNodes[index];
+ target.parentNode.removeChild(target);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var applyDiff = function (diff, elm) {
- var index = 0;
- Arr.each(diff, function (action) {
- if (action[0] === Diff.KEEP) {
- index++;
- } else if (action[0] === Diff.INSERT) {
- insertAt(elm, action[1], index);
- index++;
- } else if (action[0] === Diff.DELETE) {
- removeAt(elm, index);
- }
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var applyDiff = function (diff, elm) {
+ var index = 0;
+ Arr.each(diff, function (action) {
+ if (action[0] === Diff.KEEP) {
+ index++;
+ } else if (action[0] === Diff.INSERT) {
+ insertAt(elm, action[1], index);
+ index++;
+ } else if (action[0] === Diff.DELETE) {
+ removeAt(elm, index);
+ }
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var read = function (elm) {
- return Arr.map(elm.childNodes, getOuterHtml);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var read = function (elm) {
+ return Arr.map(elm.childNodes, getOuterHtml);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var write = function (fragments, elm) {
- var currentFragments = Arr.map(elm.childNodes, getOuterHtml);
- applyDiff(Diff.diff(currentFragments, fragments), elm);
- return elm;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var write = function (fragments, elm) {
+ var currentFragments = Arr.map(elm.childNodes, getOuterHtml);
+ applyDiff(Diff.diff(currentFragments, fragments), elm);
+ return elm;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- read: read,
- write: write
- };
-});
-
-// Included from: js/tinymce/classes/undo/Levels.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ read: read,
+ write: write
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Levels.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -22037,80 +23053,81 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.undo.Levels
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/undo/Levels", [
- "tinymce/util/Arr",
- "tinymce/undo/Fragments"
-], function (Arr, Fragments) {
- var hasIframes = function (html) {
- return html.indexOf('</iframe>') !== -1;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.undo.Levels',
+ [
+ "tinymce.core.util.Arr",
+ "tinymce.core.undo.Fragments"
+ ],
+ function (Arr, Fragments) {
+ var hasIframes = function (html) {
+ return html.indexOf('</iframe>') !== -1;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var createFragmentedLevel = function (fragments) {
- return {
- type: 'fragmented',
- fragments: fragments,
- content: '',
- bookmark: null,
- beforeBookmark: null
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createFragmentedLevel = function (fragments) {
+ return {
+ type: 'fragmented',
+ fragments: fragments,
+ content: '',
+ bookmark: null,
+ beforeBookmark: null
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var createCompleteLevel = function (content) {
- return {
- type: 'complete',
- fragments: null,
- content: content,
- bookmark: null,
- beforeBookmark: null
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createCompleteLevel = function (content) {
+ return {
+ type: 'complete',
+ fragments: null,
+ content: content,
+ bookmark: null,
+ beforeBookmark: null
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var createFromEditor = function (editor) {
- var fragments, content, trimmedFragments;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createFromEditor = function (editor) {
+ var fragments, content, trimmedFragments;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- fragments = Fragments.read(editor.getBody());
- trimmedFragments = Arr.map(fragments, function (html) {
- return editor.serializer.trimContent(html);
- });
- content = trimmedFragments.join('');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ fragments = Fragments.read(editor.getBody());
+ trimmedFragments = Arr.map(fragments, function (html) {
+ return editor.serializer.trimContent(html);
+ });
+ content = trimmedFragments.join('');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return hasIframes(content) ? createFragmentedLevel(trimmedFragments) : createCompleteLevel(content);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return hasIframes(content) ? createFragmentedLevel(trimmedFragments) : createCompleteLevel(content);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var applyToEditor = function (editor, level, before) {
- if (level.type === 'fragmented') {
- Fragments.write(level.fragments, editor.getBody());
- } else {
- editor.setContent(level.content, {format: 'raw'});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var applyToEditor = function (editor, level, before) {
+ if (level.type === 'fragmented') {
+ Fragments.write(level.fragments, editor.getBody());
+ } else {
+ editor.setContent(level.content, { format: 'raw' });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.selection.moveToBookmark(before ? level.beforeBookmark : level.bookmark);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.selection.moveToBookmark(before ? level.beforeBookmark : level.bookmark);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getLevelContent = function (level) {
- return level.type === 'fragmented' ? level.fragments.join('') : level.content;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getLevelContent = function (level) {
+ return level.type === 'fragmented' ? level.fragments.join('') : level.content;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isEq = function (level1, level2) {
- return getLevelContent(level1) === getLevelContent(level2);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isEq = function (level1, level2) {
+ return getLevelContent(level1) === getLevelContent(level2);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- createFragmentedLevel: createFragmentedLevel,
- createCompleteLevel: createCompleteLevel,
- createFromEditor: createFromEditor,
- applyToEditor: applyToEditor,
- isEq: isEq
- };
-});
-
-// Included from: js/tinymce/classes/UndoManager.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ createFragmentedLevel: createFragmentedLevel,
+ createCompleteLevel: createCompleteLevel,
+ createFromEditor: createFromEditor,
+ applyToEditor: applyToEditor,
+ isEq: isEq
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * UndoManager.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -22121,1765 +23138,4842 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.UndoManager
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/UndoManager", [
- "tinymce/util/VK",
- "tinymce/util/Tools",
- "tinymce/undo/Levels"
-], function(VK, Tools, Levels) {
- return function(editor) {
- var self = this, index = 0, data = [], beforeBookmark, isFirstTypedCharacter, locks = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.UndoManager',
+ [
+ "tinymce.core.util.VK",
+ "tinymce.core.util.Tools",
+ "tinymce.core.undo.Levels"
+ ],
+ function (VK, Tools, Levels) {
+ return function (editor) {
+ var self = this, index = 0, data = [], beforeBookmark, isFirstTypedCharacter, locks = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setDirty(state) {
- editor.setDirty(state);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isUnlocked = function () {
+ return locks === 0;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function addNonTypingUndoLevel(e) {
- self.typing = false;
- self.add({}, e);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var setTyping = function (typing) {
+ if (isUnlocked()) {
+ self.typing = typing;
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function endTyping() {
- if (self.typing) {
- self.typing = false;
- self.add();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setDirty(state) {
+ editor.setDirty(state);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add initial undo level when the editor is initialized
- editor.on('init', function() {
- self.add();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function addNonTypingUndoLevel(e) {
+ setTyping(false);
+ self.add({}, e);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Get position before an execCommand is processed
- editor.on('BeforeExecCommand', function(e) {
- var cmd = e.command;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function endTyping() {
+ if (self.typing) {
+ setTyping(false);
+ self.add();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (cmd !== 'Undo' && cmd !== 'Redo' && cmd !== 'mceRepaint') {
- endTyping();
- self.beforeChange();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add initial undo level when the editor is initialized
+ editor.on('init', function () {
+ self.add();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add undo level after an execCommand call was made
- editor.on('ExecCommand', function(e) {
- var cmd = e.command;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get position before an execCommand is processed
+ editor.on('BeforeExecCommand', function (e) {
+ var cmd = e.command;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (cmd !== 'Undo' && cmd !== 'Redo' && cmd !== 'mceRepaint') {
- addNonTypingUndoLevel(e);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (cmd !== 'Undo' && cmd !== 'Redo' && cmd !== 'mceRepaint') {
+ endTyping();
+ self.beforeChange();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('ObjectResizeStart Cut', function() {
- self.beforeChange();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add undo level after an execCommand call was made
+ editor.on('ExecCommand', function (e) {
+ var cmd = e.command;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('SaveContent ObjectResized blur', addNonTypingUndoLevel);
- editor.on('DragEnd', addNonTypingUndoLevel);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (cmd !== 'Undo' && cmd !== 'Redo' && cmd !== 'mceRepaint') {
+ addNonTypingUndoLevel(e);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('KeyUp', function(e) {
- var keyCode = e.keyCode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('ObjectResizeStart Cut', function () {
+ self.beforeChange();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If key is prevented then don't add undo level
- // This would happen on keyboard shortcuts for example
- if (e.isDefaultPrevented()) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('SaveContent ObjectResized blur', addNonTypingUndoLevel);
+ editor.on('DragEnd', addNonTypingUndoLevel);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ((keyCode >= 33 && keyCode <= 36) || (keyCode >= 37 && keyCode <= 40) || keyCode === 45 || e.ctrlKey) {
- addNonTypingUndoLevel();
- editor.nodeChanged();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('KeyUp', function (e) {
+ var keyCode = e.keyCode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (keyCode === 46 || keyCode === 8) {
- editor.nodeChanged();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If key is prevented then don't add undo level
+ // This would happen on keyboard shortcuts for example
+ if (e.isDefaultPrevented()) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Fire a TypingUndo event on the first character entered
- if (isFirstTypedCharacter && self.typing) {
- // Make it dirty if the content was changed after typing the first character
- if (!editor.isDirty()) {
- setDirty(data[0] && !Levels.isEq(Levels.createFromEditor(editor), data[0]));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((keyCode >= 33 && keyCode <= 36) || (keyCode >= 37 && keyCode <= 40) || keyCode === 45 || e.ctrlKey) {
+ addNonTypingUndoLevel();
+ editor.nodeChanged();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Fire initial change event
- if (editor.isDirty()) {
- editor.fire('change', {level: data[0], lastLevel: null});
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (keyCode === 46 || keyCode === 8) {
+ editor.nodeChanged();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.fire('TypingUndo');
- isFirstTypedCharacter = false;
- editor.nodeChanged();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Fire a TypingUndo/Change event on the first character entered
+ if (isFirstTypedCharacter && self.typing && Levels.isEq(Levels.createFromEditor(editor), data[0]) === false) {
+ if (editor.isDirty() === false) {
+ setDirty(true);
+ editor.fire('change', { level: data[0], lastLevel: null });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('KeyDown', function(e) {
- var keyCode = e.keyCode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.fire('TypingUndo');
+ isFirstTypedCharacter = false;
+ editor.nodeChanged();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If key is prevented then don't add undo level
- // This would happen on keyboard shortcuts for example
- if (e.isDefaultPrevented()) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('KeyDown', function (e) {
+ var keyCode = e.keyCode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Is character position keys left,right,up,down,home,end,pgdown,pgup,enter
- if ((keyCode >= 33 && keyCode <= 36) || (keyCode >= 37 && keyCode <= 40) || keyCode === 45) {
- if (self.typing) {
- addNonTypingUndoLevel(e);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If key is prevented then don't add undo level
+ // This would happen on keyboard shortcuts for example
+ if (e.isDefaultPrevented()) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Is character position keys left,right,up,down,home,end,pgdown,pgup,enter
+ if ((keyCode >= 33 && keyCode <= 36) || (keyCode >= 37 && keyCode <= 40) || keyCode === 45) {
+ if (self.typing) {
+ addNonTypingUndoLevel(e);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If key isn't Ctrl+Alt/AltGr
- var modKey = (e.ctrlKey && !e.altKey) || e.metaKey;
- if ((keyCode < 16 || keyCode > 20) && keyCode !== 224 && keyCode !== 91 && !self.typing && !modKey) {
- self.beforeChange();
- self.typing = true;
- self.add({}, e);
- isFirstTypedCharacter = true;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('MouseDown', function(e) {
- if (self.typing) {
- addNonTypingUndoLevel(e);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If key isn't Ctrl+Alt/AltGr
+ var modKey = (e.ctrlKey && !e.altKey) || e.metaKey;
+ if ((keyCode < 16 || keyCode > 20) && keyCode !== 224 && keyCode !== 91 && !self.typing && !modKey) {
+ self.beforeChange();
+ setTyping(true);
+ self.add({}, e);
+ isFirstTypedCharacter = true;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add keyboard shortcuts for undo/redo keys
- editor.addShortcut('meta+z', '', 'Undo');
- editor.addShortcut('meta+y,meta+shift+z', '', 'Redo');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('MouseDown', function (e) {
+ if (self.typing) {
+ addNonTypingUndoLevel(e);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('AddUndo Undo Redo ClearUndos', function(e) {
- if (!e.isDefaultPrevented()) {
- editor.nodeChanged();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add keyboard shortcuts for undo/redo keys
+ editor.addShortcut('meta+z', '', 'Undo');
+ editor.addShortcut('meta+y,meta+shift+z', '', 'Redo');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /*eslint consistent-this:0 */
- self = {
- // Explode for debugging reasons
- data: data,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('AddUndo Undo Redo ClearUndos', function (e) {
+ if (!e.isDefaultPrevented()) {
+ editor.nodeChanged();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * State if the user is currently typing or not. This will add a typing operation into one undo
- * level instead of one new level for each keystroke.
- *
- * @field {Boolean} typing
- */
- typing: false,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /*eslint consistent-this:0 */
+ self = {
+ // Explode for debugging reasons
+ data: data,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Stores away a bookmark to be used when performing an undo action so that the selection is before
- * the change has been made.
- *
- * @method beforeChange
- */
- beforeChange: function() {
- if (!locks) {
- beforeBookmark = editor.selection.getBookmark(2, true);
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * State if the user is currently typing or not. This will add a typing operation into one undo
+ * level instead of one new level for each keystroke.
+ *
+ * @field {Boolean} typing
+ */
+ typing: false,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds a new undo level/snapshot to the undo list.
- *
- * @method add
- * @param {Object} level Optional undo level object to add.
- * @param {DOMEvent} event Optional event responsible for the creation of the undo level.
- * @return {Object} Undo level that got added or null it a level wasn't needed.
- */
- add: function(level, event) {
- var i, settings = editor.settings, lastLevel, currentLevel;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Stores away a bookmark to be used when performing an undo action so that the selection is before
+ * the change has been made.
+ *
+ * @method beforeChange
+ */
+ beforeChange: function () {
+ if (isUnlocked()) {
+ beforeBookmark = editor.selection.getBookmark(2, true);
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- currentLevel = Levels.createFromEditor(editor);
- level = level || {};
- level = Tools.extend(level, currentLevel);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds a new undo level/snapshot to the undo list.
+ *
+ * @method add
+ * @param {Object} level Optional undo level object to add.
+ * @param {DOMEvent} event Optional event responsible for the creation of the undo level.
+ * @return {Object} Undo level that got added or null it a level wasn't needed.
+ */
+ add: function (level, event) {
+ var i, settings = editor.settings, lastLevel, currentLevel;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (locks || editor.removed) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ currentLevel = Levels.createFromEditor(editor);
+ level = level || {};
+ level = Tools.extend(level, currentLevel);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- lastLevel = data[index];
- if (editor.fire('BeforeAddUndo', {level: level, lastLevel: lastLevel, originalEvent: event}).isDefaultPrevented()) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isUnlocked() === false || editor.removed) {
+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add undo level if needed
- if (lastLevel && Levels.isEq(lastLevel, level)) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ lastLevel = data[index];
+ if (editor.fire('BeforeAddUndo', { level: level, lastLevel: lastLevel, originalEvent: event }).isDefaultPrevented()) {
+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set before bookmark on previous level
- if (data[index]) {
- data[index].beforeBookmark = beforeBookmark;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add undo level if needed
+ if (lastLevel && Levels.isEq(lastLevel, level)) {
+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Time to compress
- if (settings.custom_undo_redo_levels) {
- if (data.length > settings.custom_undo_redo_levels) {
- for (i = 0; i < data.length - 1; i++) {
- data[i] = data[i + 1];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set before bookmark on previous level
+ if (data[index]) {
+ data[index].beforeBookmark = beforeBookmark;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- data.length--;
- index = data.length;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Time to compress
+ if (settings.custom_undo_redo_levels) {
+ if (data.length > settings.custom_undo_redo_levels) {
+ for (i = 0; i < data.length - 1; i++) {
+ data[i] = data[i + 1];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Get a non intrusive normalized bookmark
- level.bookmark = editor.selection.getBookmark(2, true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ data.length--;
+ index = data.length;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Crop array if needed
- if (index < data.length - 1) {
- data.length = index + 1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get a non intrusive normalized bookmark
+ level.bookmark = editor.selection.getBookmark(2, true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- data.push(level);
- index = data.length - 1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Crop array if needed
+ if (index < data.length - 1) {
+ data.length = index + 1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var args = {level: level, lastLevel: lastLevel, originalEvent: event};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ data.push(level);
+ index = data.length - 1;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.fire('AddUndo', args);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var args = { level: level, lastLevel: lastLevel, originalEvent: event };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (index > 0) {
- setDirty(true);
- editor.fire('change', args);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.fire('AddUndo', args);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return level;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (index > 0) {
+ setDirty(true);
+ editor.fire('change', args);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Undoes the last action.
- *
- * @method undo
- * @return {Object} Undo level or null if no undo was performed.
- */
- undo: function() {
- var level;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return level;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.typing) {
- self.add();
- self.typing = false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Undoes the last action.
+ *
+ * @method undo
+ * @return {Object} Undo level or null if no undo was performed.
+ */
+ undo: function () {
+ var level;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (index > 0) {
- level = data[--index];
- Levels.applyToEditor(editor, level, true);
- setDirty(true);
- editor.fire('undo', {level: level});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.typing) {
+ self.add();
+ self.typing = false;
+ setTyping(false);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return level;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (index > 0) {
+ level = data[--index];
+ Levels.applyToEditor(editor, level, true);
+ setDirty(true);
+ editor.fire('undo', { level: level });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Redoes the last action.
- *
- * @method redo
- * @return {Object} Redo level or null if no redo was performed.
- */
- redo: function() {
- var level;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return level;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (index < data.length - 1) {
- level = data[++index];
- Levels.applyToEditor(editor, level, false);
- setDirty(true);
- editor.fire('redo', {level: level});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Redoes the last action.
+ *
+ * @method redo
+ * @return {Object} Redo level or null if no redo was performed.
+ */
+ redo: function () {
+ var level;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return level;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (index < data.length - 1) {
+ level = data[++index];
+ Levels.applyToEditor(editor, level, false);
+ setDirty(true);
+ editor.fire('redo', { level: level });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes all undo levels.
- *
- * @method clear
- */
- clear: function() {
- data = [];
- index = 0;
- self.typing = false;
- self.data = data;
- editor.fire('ClearUndos');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return level;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the undo manager has any undo levels.
- *
- * @method hasUndo
- * @return {Boolean} true/false if the undo manager has any undo levels.
- */
- hasUndo: function() {
- // Has undo levels or typing and content isn't the same as the initial level
- return index > 0 || (self.typing && data[0] && !Levels.isEq(Levels.createFromEditor(editor), data[0]));
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes all undo levels.
+ *
+ * @method clear
+ */
+ clear: function () {
+ data = [];
+ index = 0;
+ self.typing = false;
+ self.data = data;
+ editor.fire('ClearUndos');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the undo manager has any redo levels.
- *
- * @method hasRedo
- * @return {Boolean} true/false if the undo manager has any redo levels.
- */
- hasRedo: function() {
- return index < data.length - 1 && !self.typing;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the undo manager has any undo levels.
+ *
+ * @method hasUndo
+ * @return {Boolean} true/false if the undo manager has any undo levels.
+ */
+ hasUndo: function () {
+ // Has undo levels or typing and content isn't the same as the initial level
+ return index > 0 || (self.typing && data[0] && !Levels.isEq(Levels.createFromEditor(editor), data[0]));
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Executes the specified mutator function as an undo transaction. The selection
- * before the modification will be stored to the undo stack and if the DOM changes
- * it will add a new undo level. Any methods within the translation that adds undo levels will
- * be ignored. So a translation can include calls to execCommand or editor.insertContent.
- *
- * @method transact
- * @param {function} callback Function that gets executed and has dom manipulation logic in it.
- * @return {Object} Undo level that got added or null it a level wasn't needed.
- */
- transact: function(callback) {
- endTyping();
- self.beforeChange();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the undo manager has any redo levels.
+ *
+ * @method hasRedo
+ * @return {Boolean} true/false if the undo manager has any redo levels.
+ */
+ hasRedo: function () {
+ return index < data.length - 1 && !self.typing;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- try {
- locks++;
- callback();
- } finally {
- locks--;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Executes the specified mutator function as an undo transaction. The selection
+ * before the modification will be stored to the undo stack and if the DOM changes
+ * it will add a new undo level. Any logic within the translation that adds undo levels will
+ * be ignored. So a translation can include calls to execCommand or editor.insertContent.
+ *
+ * @method transact
+ * @param {function} callback Function that gets executed and has dom manipulation logic in it.
+ * @return {Object} Undo level that got added or null it a level wasn't needed.
+ */
+ transact: function (callback) {
+ endTyping();
+ self.beforeChange();
+ self.ignore(callback);
+ return self.add();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self.add();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Executes the specified mutator function as an undo transaction. But without adding an undo level.
+ * Any logic within the translation that adds undo levels will be ignored. So a translation can
+ * include calls to execCommand or editor.insertContent.
+ *
+ * @method ignore
+ * @param {function} callback Function that gets executed and has dom manipulation logic in it.
+ * @return {Object} Undo level that got added or null it a level wasn't needed.
+ */
+ ignore: function (callback) {
+ try {
+ locks++;
+ callback();
+ } finally {
+ locks--;
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds an extra "hidden" undo level by first applying the first mutation and store that to the undo stack
- * then roll back that change and do the second mutation on top of the stack. This will produce an extra
- * undo level that the user doesn't see until they undo.
- *
- * @method extra
- * @param {function} callback1 Function that does mutation but gets stored as a "hidden" extra undo level.
- * @param {function} callback2 Function that does mutation but gets displayed to the user.
- */
- extra: function (callback1, callback2) {
- var lastLevel, bookmark;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds an extra "hidden" undo level by first applying the first mutation and store that to the undo stack
+ * then roll back that change and do the second mutation on top of the stack. This will produce an extra
+ * undo level that the user doesn't see until they undo.
+ *
+ * @method extra
+ * @param {function} callback1 Function that does mutation but gets stored as a "hidden" extra undo level.
+ * @param {function} callback2 Function that does mutation but gets displayed to the user.
+ */
+ extra: function (callback1, callback2) {
+ var lastLevel, bookmark;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.transact(callback1)) {
- bookmark = data[index].bookmark;
- lastLevel = data[index - 1];
- Levels.applyToEditor(editor, lastLevel, true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.transact(callback1)) {
+ bookmark = data[index].bookmark;
+ lastLevel = data[index - 1];
+ Levels.applyToEditor(editor, lastLevel, true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.transact(callback2)) {
- data[index - 1].beforeBookmark = bookmark;
- }
- }
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.transact(callback2)) {
+ data[index - 1].beforeBookmark = bookmark;
+ }
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/EnterKey.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'ephox.katamari.api.Options',
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ [
+ 'ephox.katamari.api.Option'
+ ],
+
+ function (Option) {
+ /** cat :: [Option a] -> [a] */
+ var cat = function (arr) {
+ var r = [];
+ var push = function (x) {
+ r.push(x);
+ };
+ for (var i = 0; i < arr.length; i++) {
+ arr[i].each(push);
+ }
+ return r;
+ };
+
+ /** findMap :: ([a], (a, Int -> Option b)) -> Option b */
+ var findMap = function (arr, f) {
+ for (var i = 0; i < arr.length; i++) {
+ var r = f(arr[i], i);
+ if (r.isSome()) {
+ return r;
+ }
+ }
+ return Option.none();
+ };
+
+ /**
+ * if all elements in arr are 'some', their inner values are passed as arguments to f
+ * f must have arity arr.length
+ */
+ var liftN = function(arr, f) {
+ var r = [];
+ for (var i = 0; i < arr.length; i++) {
+ var x = arr[i];
+ if (x.isSome()) {
+ r.push(x.getOrDie());
+ } else {
+ return Option.none();
+ }
+ }
+ return Option.some(f.apply(null, r));
+ };
+
+ return {
+ cat: cat,
+ findMap: findMap,
+ liftN: liftN
+ };
+ }
+);
+
+define(
+ 'ephox.katamari.data.Immutable',
+
+ [
+ 'ephox.katamari.api.Arr',
+ 'ephox.katamari.api.Fun',
+ 'global!Array',
+ 'global!Error'
+ ],
+
+ function (Arr, Fun, Array, Error) {
+ return function () {
+ var fields = arguments;
+ return function(/* values */) {
+ // Don't use array slice(arguments), makes the whole function unoptimisable on Chrome
+ var values = new Array(arguments.length);
+ for (var i = 0; i < values.length; i++) values[i] = arguments[i];
+
+ if (fields.length !== values.length)
+ throw new Error('Wrong number of arguments to struct. Expected "[' + fields.length + ']", got ' + values.length + ' arguments');
+
+ var struct = {};
+ Arr.each(fields, function (name, i) {
+ struct[name] = Fun.constant(values[i]);
+ });
+ return struct;
+ };
+ };
+ }
+);
+
+define(
+ 'ephox.katamari.api.Obj',
+
+ [
+ 'ephox.katamari.api.Option',
+ 'global!Object'
+ ],
+
+ function (Option, Object) {
+ // There are many variations of Object iteration that are faster than the 'for-in' style:
+ // http://jsperf.com/object-keys-iteration/107
+ //
+ // Use the native keys if it is available (IE9+), otherwise fall back to manually filtering
+ var keys = (function () {
+ var fastKeys = Object.keys;
+
+ // This technically means that 'each' and 'find' on IE8 iterate through the object twice.
+ // This code doesn't run on IE8 much, so it's an acceptable tradeoff.
+ // If it becomes a problem we can always duplicate the feature detection inside each and find as well.
+ var slowKeys = function (o) {
+ var r = [];
+ for (var i in o) {
+ if (o.hasOwnProperty(i)) {
+ r.push(i);
+ }
+ }
+ return r;
+ };
+
+ return fastKeys === undefined ? slowKeys : fastKeys;
+ })();
+
+
+ var each = function (obj, f) {
+ var props = keys(obj);
+ for (var k = 0, len = props.length; k < len; k++) {
+ var i = props[k];
+ var x = obj[i];
+ f(x, i, obj);
+ }
+ };
+
+ /** objectMap :: (JsObj(k, v), (v, k, JsObj(k, v) -> x)) -> JsObj(k, x) */
+ var objectMap = function (obj, f) {
+ return tupleMap(obj, function (x, i, obj) {
+ return {
+ k: i,
+ v: f(x, i, obj)
+ };
+ });
+ };
+
+ /** tupleMap :: (JsObj(k, v), (v, k, JsObj(k, v) -> { k: x, v: y })) -> JsObj(x, y) */
+ var tupleMap = function (obj, f) {
+ var r = {};
+ each(obj, function (x, i) {
+ var tuple = f(x, i, obj);
+ r[tuple.k] = tuple.v;
+ });
+ return r;
+ };
+
+ /** bifilter :: (JsObj(k, v), (v, k -> Bool)) -> { t: JsObj(k, v), f: JsObj(k, v) } */
+ var bifilter = function (obj, pred) {
+ var t = {};
+ var f = {};
+ each(obj, function(x, i) {
+ var branch = pred(x, i) ? t : f;
+ branch[i] = x;
+ });
+ return {
+ t: t,
+ f: f
+ };
+ };
+
+ /** mapToArray :: (JsObj(k, v), (v, k -> a)) -> [a] */
+ var mapToArray = function (obj, f) {
+ var r = [];
+ each(obj, function(value, name) {
+ r.push(f(value, name));
+ });
+ return r;
+ };
+
+ /** find :: (JsObj(k, v), (v, k, JsObj(k, v) -> Bool)) -> Option v */
+ var find = function (obj, pred) {
+ var props = keys(obj);
+ for (var k = 0, len = props.length; k < len; k++) {
+ var i = props[k];
+ var x = obj[i];
+ if (pred(x, i, obj)) {
+ return Option.some(x);
+ }
+ }
+ return Option.none();
+ };
+
+ /** values :: JsObj(k, v) -> [v] */
+ var values = function (obj) {
+ return mapToArray(obj, function (v) {
+ return v;
+ });
+ };
+
+ var size = function (obj) {
+ return values(obj).length;
+ };
+
+ return {
+ bifilter: bifilter,
+ each: each,
+ map: objectMap,
+ mapToArray: mapToArray,
+ tupleMap: tupleMap,
+ find: find,
+ keys: keys,
+ values: values,
+ size: size
+ };
+ }
+);
+define(
+ 'ephox.katamari.api.Type',
+
+ [
+ 'global!Array',
+ 'global!String'
+ ],
+
+ function (Array, String) {
+ var typeOf = function(x) {
+ if (x === null) return 'null';
+ var t = typeof x;
+ if (t === 'object' && Array.prototype.isPrototypeOf(x)) return 'array';
+ if (t === 'object' && String.prototype.isPrototypeOf(x)) return 'string';
+ return t;
+ };
+
+ var isType = function (type) {
+ return function (value) {
+ return typeOf(value) === type;
+ };
+ };
+
+ return {
+ isString: isType('string'),
+ isObject: isType('object'),
+ isArray: isType('array'),
+ isNull: isType('null'),
+ isBoolean: isType('boolean'),
+ isUndefined: isType('undefined'),
+ isFunction: isType('function'),
+ isNumber: isType('number')
+ };
+ }
+);
+
+
+define(
+ 'ephox.katamari.util.BagUtils',
+
+ [
+ 'ephox.katamari.api.Arr',
+ 'ephox.katamari.api.Type',
+ 'global!Error'
+ ],
+
+ function (Arr, Type, Error) {
+ var sort = function (arr) {
+ return arr.slice(0).sort();
+ };
+
+ var reqMessage = function (required, keys) {
+ throw new Error('All required keys (' + sort(required).join(', ') + ') were not specified. Specified keys were: ' + sort(keys).join(', ') + '.');
+ };
+
+ var unsuppMessage = function (unsupported) {
+ throw new Error('Unsupported keys for object: ' + sort(unsupported).join(', '));
+ };
+
+ var validateStrArr = function (label, array) {
+ if (!Type.isArray(array)) throw new Error('The ' + label + ' fields must be an array. Was: ' + array + '.');
+ Arr.each(array, function (a) {
+ if (!Type.isString(a)) throw new Error('The value ' + a + ' in the ' + label + ' fields was not a string.');
+ });
+ };
+
+ var invalidTypeMessage = function (incorrect, type) {
+ throw new Error('All values need to be of type: ' + type + '. Keys (' + sort(incorrect).join(', ') + ') were not.');
+ };
+
+ var checkDupes = function (everything) {
+ var sorted = sort(everything);
+ var dupe = Arr.find(sorted, function (s, i) {
+ return i < sorted.length -1 && s === sorted[i + 1];
+ });
+
+ dupe.each(function (d) {
+ throw new Error('The field: ' + d + ' occurs more than once in the combined fields: [' + sorted.join(', ') + '].');
+ });
+ };
+
+ return {
+ sort: sort,
+ reqMessage: reqMessage,
+ unsuppMessage: unsuppMessage,
+ validateStrArr: validateStrArr,
+ invalidTypeMessage: invalidTypeMessage,
+ checkDupes: checkDupes
+ };
+ }
+);
+define(
+ 'ephox.katamari.data.MixedBag',
+
+ [
+ 'ephox.katamari.api.Arr',
+ 'ephox.katamari.api.Fun',
+ 'ephox.katamari.api.Obj',
+ 'ephox.katamari.api.Option',
+ 'ephox.katamari.util.BagUtils',
+ 'global!Error',
+ 'global!Object'
+ ],
+
+ function (Arr, Fun, Obj, Option, BagUtils, Error, Object) {
+
+ return function (required, optional) {
+ var everything = required.concat(optional);
+ if (everything.length === 0) throw new Error('You must specify at least one required or optional field.');
+
+ BagUtils.validateStrArr('required', required);
+ BagUtils.validateStrArr('optional', optional);
+
+ BagUtils.checkDupes(everything);
+
+ return function (obj) {
+ var keys = Obj.keys(obj);
+
+ // Ensure all required keys are present.
+ var allReqd = Arr.forall(required, function (req) {
+ return Arr.contains(keys, req);
+ });
+
+ if (! allReqd) BagUtils.reqMessage(required, keys);
+
+ var unsupported = Arr.filter(keys, function (key) {
+ return !Arr.contains(everything, key);
+ });
+
+ if (unsupported.length > 0) BagUtils.unsuppMessage(unsupported);
+
+ var r = {};
+ Arr.each(required, function (req) {
+ r[req] = Fun.constant(obj[req]);
+ });
+
+ Arr.each(optional, function (opt) {
+ r[opt] = Fun.constant(Object.prototype.hasOwnProperty.call(obj, opt) ? Option.some(obj[opt]): Option.none());
+ });
+
+ return r;
+ };
+ };
+ }
+);
+define(
+ 'ephox.katamari.api.Struct',
+
+ [
+ 'ephox.katamari.data.Immutable',
+ 'ephox.katamari.data.MixedBag'
+ ],
+
+ function (Immutable, MixedBag) {
+ return {
+ immutable: Immutable,
+ immutableBag: MixedBag
+ };
+ }
+);
+
+define(
+ 'ephox.katamari.api.Global',
+
+ [
+ ],
+
+ function () {
+ return Function('return this;')();
+ }
+);
+
+
+define(
+ 'ephox.katamari.api.Resolve',
+
+ [
+ 'ephox.katamari.api.Global'
+ ],
+
+ function (Global) {
+ /** path :: ([String], JsObj?) -> JsObj */
+ var path = function (parts, scope) {
+ var o = scope !== undefined ? scope : Global;
+ for (var i = 0; i < parts.length && o !== undefined && o !== null; ++i)
+ o = o[parts[i]];
+ return o;
+ };
+
+ /** resolve :: (String, JsObj?) -> JsObj */
+ var resolve = function (p, scope) {
+ var parts = p.split('.');
+ return path(parts, scope);
+ };
+
+ /** step :: (JsObj, String) -> JsObj */
+ var step = function (o, part) {
+ if (o[part] === undefined || o[part] === null)
+ o[part] = {};
+ return o[part];
+ };
+
+ /** forge :: ([String], JsObj?) -> JsObj */
+ var forge = function (parts, target) {
+ var o = target !== undefined ? target : Global;
+ for (var i = 0; i < parts.length; ++i)
+ o = step(o, parts[i]);
+ return o;
+ };
+
+ /** namespace :: (String, JsObj?) -> JsObj */
+ var namespace = function (name, target) {
+ var parts = name.split('.');
+ return forge(parts, target);
+ };
+
+ return {
+ path: path,
+ resolve: resolve,
+ forge: forge,
+ namespace: namespace
+ };
+ }
+);
+
+
+define(
+ 'ephox.sand.util.Global',
+
+ [
+ 'ephox.katamari.api.Resolve'
+ ],
+
+ function (Resolve) {
+ var unsafe = function (name, scope) {
+ return Resolve.resolve(name, scope);
+ };
+
+ var getOrDie = function (name, scope) {
+ var actual = unsafe(name, scope);
+
+ if (actual === undefined) throw name + ' not available on this browser';
+ return actual;
+ };
+
+ return {
+ getOrDie: getOrDie
+ };
+ }
+);
+define(
+ 'ephox.sand.api.Node',
+
+ [
+ 'ephox.sand.util.Global'
+ ],
+
+ function (Global) {
+ /*
+ * MDN says (yes) for IE, but it's undefined on IE8
+ */
+ var node = function () {
+ var f = Global.getOrDie('Node');
+ return f;
+ };
+
+ /*
+ * Most of numerosity doesn't alter the methods on the object.
+ * We're making an exception for Node, because bitwise and is so easy to get wrong.
+ *
+ * Might be nice to ADT this at some point instead of having individual methods.
+ */
+
+ var compareDocumentPosition = function (a, b, match) {
+ // Returns: 0 if e1 and e2 are the same node, or a bitmask comparing the positions
+ // of nodes e1 and e2 in their documents. See the URL below for bitmask interpretation
+ // https://developer.mozilla.org/en-US/docs/Web/API/Node/compareDocumentPosition
+ return (a.compareDocumentPosition(b) & match) !== 0;
+ };
+
+ var documentPositionPreceding = function (a, b) {
+ return compareDocumentPosition(a, b, node().DOCUMENT_POSITION_PRECEDING);
+ };
+
+ var documentPositionContainedBy = function (a, b) {
+ return compareDocumentPosition(a, b, node().DOCUMENT_POSITION_CONTAINED_BY);
+ };
+
+ return {
+ documentPositionPreceding: documentPositionPreceding,
+ documentPositionContainedBy: documentPositionContainedBy
+ };
+ }
+);
+define(
+ 'ephox.katamari.api.Thunk',
+
+ [
+ ],
+
+ function () {
+
+ var cached = function (f) {
+ var called = false;
+ var r;
+ return function() {
+ if (!called) {
+ called = true;
+ r = f.apply(null, arguments);
+ }
+ return r;
+ };
+ };
+
+ return {
+ cached: cached
+ };
+ }
+);
+
+defineGlobal("global!Number", Number);
+define(
+ 'ephox.sand.detect.Version',
+
+ [
+ 'ephox.katamari.api.Arr',
+ 'global!Number',
+ 'global!String'
+ ],
+
+ function (Arr, Number, String) {
+ var firstMatch = function (regexes, s) {
+ for (var i = 0; i < regexes.length; i++) {
+ var x = regexes[i];
+ if (x.test(s)) return x;
+ }
+ return undefined;
+ };
+
+ var find = function (regexes, agent) {
+ var r = firstMatch(regexes, agent);
+ if (!r) return { major : 0, minor : 0 };
+ var group = function(i) {
+ return Number(agent.replace(r, '$' + i));
+ };
+ return nu(group(1), group(2));
+ };
+
+ var detect = function (versionRegexes, agent) {
+ var cleanedAgent = String(agent).toLowerCase();
+
+ if (versionRegexes.length === 0) return unknown();
+ return find(versionRegexes, cleanedAgent);
+ };
+
+ var unknown = function () {
+ return nu(0, 0);
+ };
+
+ var nu = function (major, minor) {
+ return { major: major, minor: minor };
+ };
+
+ return {
+ nu: nu,
+ detect: detect,
+ unknown: unknown
+ };
+ }
+);
+define(
+ 'ephox.sand.core.Browser',
+
+ [
+ 'ephox.katamari.api.Fun',
+ 'ephox.sand.detect.Version'
+ ],
+
+ function (Fun, Version) {
+ var edge = 'Edge';
+ var chrome = 'Chrome';
+ var ie = 'IE';
+ var opera = 'Opera';
+ var firefox = 'Firefox';
+ var safari = 'Safari';
+
+ var isBrowser = function (name, current) {
+ return function () {
+ return current === name;
+ };
+ };
+
+ var unknown = function () {
+ return nu({
+ current: undefined,
+ version: Version.unknown()
+ });
+ };
+
+ var nu = function (info) {
+ var current = info.current;
+ var version = info.version;
+
+ return {
+ current: current,
+ version: version,
+
+ // INVESTIGATE: Rename to Edge ?
+ isEdge: isBrowser(edge, current),
+ isChrome: isBrowser(chrome, current),
+ // NOTE: isIe just looks too weird
+ isIE: isBrowser(ie, current),
+ isOpera: isBrowser(opera, current),
+ isFirefox: isBrowser(firefox, current),
+ isSafari: isBrowser(safari, current)
+ };
+ };
+
+ return {
+ unknown: unknown,
+ nu: nu,
+ edge: Fun.constant(edge),
+ chrome: Fun.constant(chrome),
+ ie: Fun.constant(ie),
+ opera: Fun.constant(opera),
+ firefox: Fun.constant(firefox),
+ safari: Fun.constant(safari)
+ };
+ }
+);
+define(
+ 'ephox.sand.core.OperatingSystem',
+
+ [
+ 'ephox.katamari.api.Fun',
+ 'ephox.sand.detect.Version'
+ ],
+
+ function (Fun, Version) {
+ var windows = 'Windows';
+ var ios = 'iOS';
+ var android = 'Android';
+ var linux = 'Linux';
+ var osx = 'OSX';
+ var solaris = 'Solaris';
+ var freebsd = 'FreeBSD';
+
+ // Though there is a bit of dupe with this and Browser, trying to
+ // reuse code makes it much harder to follow and change.
+ var isOS = function (name, current) {
+ return function () {
+ return current === name;
+ };
+ };
+
+ var unknown = function () {
+ return nu({
+ current: undefined,
+ version: Version.unknown()
+ });
+ };
+
+ var nu = function (info) {
+ var current = info.current;
+ var version = info.version;
+
+ return {
+ current: current,
+ version: version,
+
+ isWindows: isOS(windows, current),
+ // TODO: Fix capitalisation
+ isiOS: isOS(ios, current),
+ isAndroid: isOS(android, current),
+ isOSX: isOS(osx, current),
+ isLinux: isOS(linux, current),
+ isSolaris: isOS(solaris, current),
+ isFreeBSD: isOS(freebsd, current)
+ };
+ };
+
+ return {
+ unknown: unknown,
+ nu: nu,
+
+ windows: Fun.constant(windows),
+ ios: Fun.constant(ios),
+ android: Fun.constant(android),
+ linux: Fun.constant(linux),
+ osx: Fun.constant(osx),
+ solaris: Fun.constant(solaris),
+ freebsd: Fun.constant(freebsd)
+ };
+ }
+);
+define(
+ 'ephox.sand.detect.DeviceType',
+
+ [
+ 'ephox.katamari.api.Fun'
+ ],
+
+ function (Fun) {
+ return function (os, browser, userAgent) {
+ var isiPad = os.isiOS() && /ipad/i.test(userAgent) === true;
+ var isiPhone = os.isiOS() && !isiPad;
+ var isAndroid3 = os.isAndroid() && os.version.major === 3;
+ var isAndroid4 = os.isAndroid() && os.version.major === 4;
+ var isTablet = isiPad || isAndroid3 || ( isAndroid4 && /mobile/i.test(userAgent) === true );
+ var isTouch = os.isiOS() || os.isAndroid();
+ var isPhone = isTouch && !isTablet;
+
+ var iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false;
+
+ return {
+ isiPad : Fun.constant(isiPad),
+ isiPhone: Fun.constant(isiPhone),
+ isTablet: Fun.constant(isTablet),
+ isPhone: Fun.constant(isPhone),
+ isTouch: Fun.constant(isTouch),
+ isAndroid: os.isAndroid,
+ isiOS: os.isiOS,
+ isWebView: Fun.constant(iOSwebview)
+ };
+ };
+ }
+);
+define(
+ 'ephox.sand.detect.UaString',
+
+ [
+ 'ephox.katamari.api.Arr',
+ 'ephox.sand.detect.Version',
+ 'global!String'
+ ],
+
+ function (Arr, Version, String) {
+ var detect = function (candidates, userAgent) {
+ var agent = String(userAgent).toLowerCase();
+ return Arr.find(candidates, function (candidate) {
+ return candidate.search(agent);
+ });
+ };
+
+ // They (browser and os) are the same at the moment, but they might
+ // not stay that way.
+ var detectBrowser = function (browsers, userAgent) {
+ return detect(browsers, userAgent).map(function (browser) {
+ var version = Version.detect(browser.versionRegexes, userAgent);
+ return {
+ current: browser.name,
+ version: version
+ };
+ });
+ };
+
+ var detectOs = function (oses, userAgent) {
+ return detect(oses, userAgent).map(function (os) {
+ var version = Version.detect(os.versionRegexes, userAgent);
+ return {
+ current: os.name,
+ version: version
+ };
+ });
+ };
+
+ return {
+ detectBrowser: detectBrowser,
+ detectOs: detectOs
+ };
+ }
+);
+define(
+ 'ephox.katamari.str.StrAppend',
+
+ [
+
+ ],
+
+ function () {
+ var addToStart = function (str, prefix) {
+ return prefix + str;
+ };
+
+ var addToEnd = function (str, suffix) {
+ return str + suffix;
+ };
+
+ var removeFromStart = function (str, numChars) {
+ return str.substring(numChars);
+ };
+
+ var removeFromEnd = function (str, numChars) {
+ return str.substring(0, str.length - numChars);
+ };
+
+ return {
+ addToStart: addToStart,
+ addToEnd: addToEnd,
+ removeFromStart: removeFromStart,
+ removeFromEnd: removeFromEnd
+ };
+ }
+);
+define(
+ 'ephox.katamari.str.StringParts',
+
+ [
+ 'ephox.katamari.api.Option',
+ 'global!Error'
+ ],
+
+ function (Option, Error) {
+ /** Return the first 'count' letters from 'str'.
+- * e.g. first("abcde", 2) === "ab"
+- */
+ var first = function(str, count) {
+ return str.substr(0, count);
+ };
+
+ /** Return the last 'count' letters from 'str'.
+ * e.g. last("abcde", 2) === "de"
+ */
+ var last = function(str, count) {
+ return str.substr(str.length - count, str.length);
+ };
+
+ var head = function(str) {
+ return str === '' ? Option.none() : Option.some(str.substr(0, 1));
+ };
+
+ var tail = function(str) {
+ return str === '' ? Option.none() : Option.some(str.substring(1));
+ };
+
+ return {
+ first: first,
+ last: last,
+ head: head,
+ tail: tail
+ };
+ }
+);
+define(
+ 'ephox.katamari.api.Strings',
+
+ [
+ 'ephox.katamari.str.StrAppend',
+ 'ephox.katamari.str.StringParts',
+ 'global!Error'
+ ],
+
+ function (StrAppend, StringParts, Error) {
+ var checkRange = function(str, substr, start) {
+ if (substr === '') return true;
+ if (str.length < substr.length) return false;
+ var x = str.substr(start, start + substr.length);
+ return x === substr;
+ };
+
+ /** Given a string and object, perform template-replacements on the string, as specified by the object.
+ * Any template fields of the form ${name} are replaced by the string or number specified as obj["name"]
+ * Based on Douglas Crockford's 'supplant' method for template-replace of strings. Uses different template format.
+ */
+ var supplant = function(str, obj) {
+ var isStringOrNumber = function(a) {
+ var t = typeof a;
+ return t === 'string' || t === 'number';
+ };
+
+ return str.replace(/\${([^{}]*)}/g,
+ function (a, b) {
+ var value = obj[b];
+ return isStringOrNumber(value) ? value : a;
+ }
+ );
+ };
+
+ var removeLeading = function (str, prefix) {
+ return startsWith(str, prefix) ? StrAppend.removeFromStart(str, prefix.length) : str;
+ };
+
+ var removeTrailing = function (str, prefix) {
+ return endsWith(str, prefix) ? StrAppend.removeFromEnd(str, prefix.length) : str;
+ };
+
+ var ensureLeading = function (str, prefix) {
+ return startsWith(str, prefix) ? str : StrAppend.addToStart(str, prefix);
+ };
+
+ var ensureTrailing = function (str, prefix) {
+ return endsWith(str, prefix) ? str : StrAppend.addToEnd(str, prefix);
+ };
+
+ var contains = function(str, substr) {
+ return str.indexOf(substr) !== -1;
+ };
+
+ var capitalize = function(str) {
+ return StringParts.head(str).bind(function (head) {
+ return StringParts.tail(str).map(function (tail) {
+ return head.toUpperCase() + tail;
+ });
+ }).getOr(str);
+ };
+
+ /** Does 'str' start with 'prefix'?
+ * Note: all strings start with the empty string.
+ * More formally, for all strings x, startsWith(x, "").
+ * This is so that for all strings x and y, startsWith(y + x, y)
+ */
+ var startsWith = function(str, prefix) {
+ return checkRange(str, prefix, 0);
+ };
+
+ /** Does 'str' end with 'suffix'?
+ * Note: all strings end with the empty string.
+ * More formally, for all strings x, endsWith(x, "").
+ * This is so that for all strings x and y, endsWith(x + y, y)
+ */
+ var endsWith = function(str, suffix) {
+ return checkRange(str, suffix, str.length - suffix.length);
+ };
+
+
+ /** removes all leading and trailing spaces */
+ var trim = function(str) {
+ return str.replace(/^\s+|\s+$/g, '');
+ };
+
+ var lTrim = function(str) {
+ return str.replace(/^\s+/g, '');
+ };
+
+ var rTrim = function(str) {
+ return str.replace(/\s+$/g, '');
+ };
+
+ return {
+ supplant: supplant,
+ startsWith: startsWith,
+ removeLeading: removeLeading,
+ removeTrailing: removeTrailing,
+ ensureLeading: ensureLeading,
+ ensureTrailing: ensureTrailing,
+ endsWith: endsWith,
+ contains: contains,
+ trim: trim,
+ lTrim: lTrim,
+ rTrim: rTrim,
+ capitalize: capitalize
+ };
+ }
+);
+
+define(
+ 'ephox.sand.info.PlatformInfo',
+
+ [
+ 'ephox.katamari.api.Fun',
+ 'ephox.katamari.api.Strings'
+ ],
+
+ function (Fun, Strings) {
+ var normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/;
+
+ var checkContains = function (target) {
+ return function (uastring) {
+ return Strings.contains(uastring, target);
+ };
+ };
+
+ var browsers = [
+ {
+ name : 'Edge',
+ versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],
+ search: function (uastring) {
+ var monstrosity = Strings.contains(uastring, 'edge/') && Strings.contains(uastring, 'chrome') && Strings.contains(uastring, 'safari') && Strings.contains(uastring, 'applewebkit');
+ return monstrosity;
+ }
+ },
+ {
+ name : 'Chrome',
+ versionRegexes: [/.*?chrome\/([0-9]+)\.([0-9]+).*/, normalVersionRegex],
+ search : function (uastring) {
+ return Strings.contains(uastring, 'chrome') && !Strings.contains(uastring, 'chromeframe');
+ }
+ },
+ {
+ name : 'IE',
+ versionRegexes: [/.*?msie\ ?([0-9]+)\.([0-9]+).*/, /.*?rv:([0-9]+)\.([0-9]+).*/],
+ search: function (uastring) {
+ return Strings.contains(uastring, 'msie') || Strings.contains(uastring, 'trident');
+ }
+ },
+ // INVESTIGATE: Is this still the Opera user agent?
+ {
+ name : 'Opera',
+ versionRegexes: [normalVersionRegex, /.*?opera\/([0-9]+)\.([0-9]+).*/],
+ search : checkContains('opera')
+ },
+ {
+ name : 'Firefox',
+ versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],
+ search : checkContains('firefox')
+ },
+ {
+ name : 'Safari',
+ versionRegexes: [normalVersionRegex, /.*?cpu os ([0-9]+)_([0-9]+).*/],
+ search : function (uastring) {
+ return (Strings.contains(uastring, 'safari') || Strings.contains(uastring, 'mobile/')) && Strings.contains(uastring, 'applewebkit');
+ }
+ }
+ ];
+
+ var oses = [
+ {
+ name : 'Windows',
+ search : checkContains('win'),
+ versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]
+ },
+ {
+ name : 'iOS',
+ search : function (uastring) {
+ return Strings.contains(uastring, 'iphone') || Strings.contains(uastring, 'ipad');
+ },
+ versionRegexes: [/.*?version\/\ ?([0-9]+)\.([0-9]+).*/, /.*cpu os ([0-9]+)_([0-9]+).*/, /.*cpu iphone os ([0-9]+)_([0-9]+).*/]
+ },
+ {
+ name : 'Android',
+ search : checkContains('android'),
+ versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/]
+ },
+ {
+ name : 'OSX',
+ search : checkContains('os x'),
+ versionRegexes: [/.*?os\ x\ ?([0-9]+)_([0-9]+).*/]
+ },
+ {
+ name : 'Linux',
+ search : checkContains('linux'),
+ versionRegexes: [ ]
+ },
+ { name : 'Solaris',
+ search : checkContains('sunos'),
+ versionRegexes: [ ]
+ },
+ {
+ name : 'FreeBSD',
+ search : checkContains('freebsd'),
+ versionRegexes: [ ]
+ }
+ ];
+
+ return {
+ browsers: Fun.constant(browsers),
+ oses: Fun.constant(oses)
+ };
+ }
+);
+define(
+ 'ephox.sand.core.PlatformDetection',
+
+ [
+ 'ephox.sand.core.Browser',
+ 'ephox.sand.core.OperatingSystem',
+ 'ephox.sand.detect.DeviceType',
+ 'ephox.sand.detect.UaString',
+ 'ephox.sand.info.PlatformInfo'
+ ],
+
+ function (Browser, OperatingSystem, DeviceType, UaString, PlatformInfo) {
+ var detect = function (userAgent) {
+ var browsers = PlatformInfo.browsers();
+ var oses = PlatformInfo.oses();
+
+ var browser = UaString.detectBrowser(browsers, userAgent).fold(
+ Browser.unknown,
+ Browser.nu
+ );
+ var os = UaString.detectOs(oses, userAgent).fold(
+ OperatingSystem.unknown,
+ OperatingSystem.nu
+ );
+ var deviceType = DeviceType(os, browser, userAgent);
+
+ return {
+ browser: browser,
+ os: os,
+ deviceType: deviceType
+ };
+ };
+
+ return {
+ detect: detect
+ };
+ }
+);
+defineGlobal("global!navigator", navigator);
+define(
+ 'ephox.sand.api.PlatformDetection',
+
+ [
+ 'ephox.katamari.api.Thunk',
+ 'ephox.sand.core.PlatformDetection',
+ 'global!navigator'
+ ],
+
+ function (Thunk, PlatformDetection, navigator) {
+ var detect = Thunk.cached(function () {
+ var userAgent = navigator.userAgent;
+ return PlatformDetection.detect(userAgent);
+ });
+
+ return {
+ detect: detect
+ };
+ }
+);
+define("global!console", [], function () { if (typeof console === "undefined") console = { log: function () {} }; return console; });
+defineGlobal("global!document", document);
+define(
+ 'ephox.sugar.api.node.Element',
+
+ [
+ 'ephox.katamari.api.Fun',
+ 'global!Error',
+ 'global!console',
+ 'global!document'
+ ],
+
+ function (Fun, Error, console, document) {
+ var fromHtml = function (html, scope) {
+ var doc = scope || document;
+ var div = doc.createElement('div');
+ div.innerHTML = html;
+ if (!div.hasChildNodes() || div.childNodes.length > 1) {
+ console.error('HTML does not have a single root node', html);
+ throw 'HTML must have a single root node';
+ }
+ return fromDom(div.childNodes[0]);
+ };
+
+ var fromTag = function (tag, scope) {
+ var doc = scope || document;
+ var node = doc.createElement(tag);
+ return fromDom(node);
+ };
+
+ var fromText = function (text, scope) {
+ var doc = scope || document;
+ var node = doc.createTextNode(text);
+ return fromDom(node);
+ };
+
+ var fromDom = function (node) {
+ if (node === null || node === undefined) throw new Error('Node cannot be null or undefined');
+ return {
+ dom: Fun.constant(node)
+ };
+ };
+
+ return {
+ fromHtml: fromHtml,
+ fromTag: fromTag,
+ fromText: fromText,
+ fromDom: fromDom
+ };
+ }
+);
+
+define(
+ 'ephox.sugar.api.node.NodeTypes',
+
+ [
+
+ ],
+
+ function () {
+ return {
+ ATTRIBUTE: 2,
+ CDATA_SECTION: 4,
+ COMMENT: 8,
+ DOCUMENT: 9,
+ DOCUMENT_TYPE: 10,
+ DOCUMENT_FRAGMENT: 11,
+ ELEMENT: 1,
+ TEXT: 3,
+ PROCESSING_INSTRUCTION: 7,
+ ENTITY_REFERENCE: 5,
+ ENTITY: 6,
+ NOTATION: 12
+ };
+ }
+);
+define(
+ 'ephox.sugar.api.search.Selectors',
+
+ [
+ 'ephox.katamari.api.Arr',
+ 'ephox.katamari.api.Option',
+ 'ephox.sugar.api.node.Element',
+ 'ephox.sugar.api.node.NodeTypes',
+ 'global!Error',
+ 'global!document'
+ ],
+
+ function (Arr, Option, Element, NodeTypes, Error, document) {
+ /*
+ * There's a lot of code here; the aim is to allow the browser to optimise constant comparisons,
+ * instead of doing object lookup feature detection on every call
+ */
+ var STANDARD = 0;
+ var MSSTANDARD = 1;
+ var WEBKITSTANDARD = 2;
+ var FIREFOXSTANDARD = 3;
+
+ var selectorType = (function () {
+ var test = document.createElement('span');
+ // As of Chrome 34 / Safari 7.1 / FireFox 34, everyone except IE has the unprefixed function.
+ // Still check for the others, but do it last.
+ return test.matches !== undefined ? STANDARD :
+ test.msMatchesSelector !== undefined ? MSSTANDARD :
+ test.webkitMatchesSelector !== undefined ? WEBKITSTANDARD :
+ test.mozMatchesSelector !== undefined ? FIREFOXSTANDARD :
+ -1;
+ })();
+
+
+ var ELEMENT = NodeTypes.ELEMENT;
+ var DOCUMENT = NodeTypes.DOCUMENT;
+
+ var is = function (element, selector) {
+ var elem = element.dom();
+ if (elem.nodeType !== ELEMENT) return false; // documents have querySelector but not matches
+
+ // As of Chrome 34 / Safari 7.1 / FireFox 34, everyone except IE has the unprefixed function.
+ // Still check for the others, but do it last.
+ else if (selectorType === STANDARD) return elem.matches(selector);
+ else if (selectorType === MSSTANDARD) return elem.msMatchesSelector(selector);
+ else if (selectorType === WEBKITSTANDARD) return elem.webkitMatchesSelector(selector);
+ else if (selectorType === FIREFOXSTANDARD) return elem.mozMatchesSelector(selector);
+ else throw new Error('Browser lacks native selectors'); // unfortunately we can't throw this on startup :(
+ };
+
+ var bypassSelector = function (dom) {
+ // Only elements and documents support querySelector
+ return dom.nodeType !== ELEMENT && dom.nodeType !== DOCUMENT ||
+ // IE fix for complex queries on empty nodes: http://jsfiddle.net/spyder/fv9ptr5L/
+ dom.childElementCount === 0;
+ };
+
+ var all = function (selector, scope) {
+ var base = scope === undefined ? document : scope.dom();
+ return bypassSelector(base) ? [] : Arr.map(base.querySelectorAll(selector), Element.fromDom);
+ };
+
+ var one = function (selector, scope) {
+ var base = scope === undefined ? document : scope.dom();
+ return bypassSelector(base) ? Option.none() : Option.from(base.querySelector(selector)).map(Element.fromDom);
+ };
+
+ return {
+ all: all,
+ is: is,
+ one: one
+ };
+ }
+);
+
+define(
+ 'ephox.sugar.api.dom.Compare',
+
+ [
+ 'ephox.katamari.api.Arr',
+ 'ephox.katamari.api.Fun',
+ 'ephox.sand.api.Node',
+ 'ephox.sand.api.PlatformDetection',
+ 'ephox.sugar.api.search.Selectors'
+ ],
+
+ function (Arr, Fun, Node, PlatformDetection, Selectors) {
+
+ var eq = function (e1, e2) {
+ return e1.dom() === e2.dom();
+ };
+
+ var isEqualNode = function (e1, e2) {
+ return e1.dom().isEqualNode(e2.dom());
+ };
+
+ var member = function (element, elements) {
+ return Arr.exists(elements, Fun.curry(eq, element));
+ };
+
+ // DOM contains() method returns true if e1===e2, we define our contains() to return false (a node does not contain itself).
+ var regularContains = function (e1, e2) {
+ var d1 = e1.dom(), d2 = e2.dom();
+ return d1 === d2 ? false : d1.contains(d2);
+ };
+
+ var ieContains = function (e1, e2) {
+ // IE only implements the contains() method for Element nodes.
+ // It fails for Text nodes, so implement it using compareDocumentPosition()
+ // https://connect.microsoft.com/IE/feedback/details/780874/node-contains-is-incorrect
+ // Note that compareDocumentPosition returns CONTAINED_BY if 'e2 *is_contained_by* e1':
+ // Also, compareDocumentPosition defines a node containing itself as false.
+ return Node.documentPositionContainedBy(e1.dom(), e2.dom());
+ };
+
+ var browser = PlatformDetection.detect().browser;
+
+ // Returns: true if node e1 contains e2, otherwise false.
+ // (returns false if e1===e2: A node does not contain itself).
+ var contains = browser.isIE() ? ieContains : regularContains;
+
+ return {
+ eq: eq,
+ isEqualNode: isEqualNode,
+ member: member,
+ contains: contains,
+
+ // Only used by DomUniverse. Remove (or should Selectors.is move here?)
+ is: Selectors.is
+ };
+ }
+);
+
+define(
+ 'ephox.sugar.api.node.Node',
+
+ [
+ 'ephox.sugar.api.node.NodeTypes'
+ ],
+
+ function (NodeTypes) {
+ var name = function (element) {
+ var r = element.dom().nodeName;
+ return r.toLowerCase();
+ };
+
+ var type = function (element) {
+ return element.dom().nodeType;
+ };
+
+ var value = function (element) {
+ return element.dom().nodeValue;
+ };
+
+ var isType = function (t) {
+ return function (element) {
+ return type(element) === t;
+ };
+ };
+
+ var isComment = function (element) {
+ return type(element) === NodeTypes.COMMENT || name(element) === '#comment';
+ };
+
+ var isElement = isType(NodeTypes.ELEMENT);
+ var isText = isType(NodeTypes.TEXT);
+ var isDocument = isType(NodeTypes.DOCUMENT);
+
+ return {
+ name: name,
+ type: type,
+ value: value,
+ isElement: isElement,
+ isText: isText,
+ isDocument: isDocument,
+ isComment: isComment
+ };
+ }
+);
+
+define(
+ 'ephox.sugar.api.node.Body',
+
+ [
+ 'ephox.katamari.api.Thunk',
+ 'ephox.sugar.api.node.Element',
+ 'ephox.sugar.api.node.Node',
+ 'global!document'
+ ],
+
+ function (Thunk, Element, Node, document) {
+
+ // Node.contains() is very, very, very good performance
+ // http://jsperf.com/closest-vs-contains/5
+ var inBody = function (element) {
+ // Technically this is only required on IE, where contains() returns false for text nodes.
+ // But it's cheap enough to run everywhere and Sugar doesn't have platform detection (yet).
+ var dom = Node.isText(element) ? element.dom().parentNode : element.dom();
+
+ // use ownerDocument.body to ensure this works inside iframes.
+ // Normally contains is bad because an element "contains" itself, but here we want that.
+ return dom !== undefined && dom !== null && dom.ownerDocument.body.contains(dom);
+ };
+
+ var body = Thunk.cached(function() {
+ return getBody(Element.fromDom(document));
+ });
+
+ var getBody = function (doc) {
+ var body = doc.dom().body;
+ if (body === null || body === undefined) throw 'Body is not available yet';
+ return Element.fromDom(body);
+ };
+
+ return {
+ body: body,
+ getBody: getBody,
+ inBody: inBody
+ };
+ }
+);
+
+define(
+ 'ephox.sugar.impl.ClosestOrAncestor',
+
+ [
+ 'ephox.katamari.api.Type',
+ 'ephox.katamari.api.Option'
+ ],
+
+ function (Type, Option) {
+ return function (is, ancestor, scope, a, isRoot) {
+ return is(scope, a) ?
+ Option.some(scope) :
+ Type.isFunction(isRoot) && isRoot(scope) ?
+ Option.none() :
+ ancestor(scope, a, isRoot);
+ };
+ }
+);
+define(
+ 'ephox.sugar.api.search.PredicateFind',
+
+ [
+ 'ephox.katamari.api.Type',
+ 'ephox.katamari.api.Arr',
+ 'ephox.katamari.api.Fun',
+ 'ephox.katamari.api.Option',
+ 'ephox.sugar.api.node.Body',
+ 'ephox.sugar.api.dom.Compare',
+ 'ephox.sugar.api.node.Element',
+ 'ephox.sugar.impl.ClosestOrAncestor'
+ ],
+
+ function (Type, Arr, Fun, Option, Body, Compare, Element, ClosestOrAncestor) {
+ var first = function (predicate) {
+ return descendant(Body.body(), predicate);
+ };
+
+ var ancestor = function (scope, predicate, isRoot) {
+ var element = scope.dom();
+ var stop = Type.isFunction(isRoot) ? isRoot : Fun.constant(false);
+
+ while (element.parentNode) {
+ element = element.parentNode;
+ var el = Element.fromDom(element);
+
+ if (predicate(el)) return Option.some(el);
+ else if (stop(el)) break;
+ }
+ return Option.none();
+ };
+
+ var closest = function (scope, predicate, isRoot) {
+ // This is required to avoid ClosestOrAncestor passing the predicate to itself
+ var is = function (scope) {
+ return predicate(scope);
+ };
+ return ClosestOrAncestor(is, ancestor, scope, predicate, isRoot);
+ };
+
+ var sibling = function (scope, predicate) {
+ var element = scope.dom();
+ if (!element.parentNode) return Option.none();
+
+ return child(Element.fromDom(element.parentNode), function (x) {
+ return !Compare.eq(scope, x) && predicate(x);
+ });
+ };
+
+ var child = function (scope, predicate) {
+ var result = Arr.find(scope.dom().childNodes,
+ Fun.compose(predicate, Element.fromDom));
+ return result.map(Element.fromDom);
+ };
+
+ var descendant = function (scope, predicate) {
+ var descend = function (element) {
+ for (var i = 0; i < element.childNodes.length; i++) {
+ if (predicate(Element.fromDom(element.childNodes[i])))
+ return Option.some(Element.fromDom(element.childNodes[i]));
+
+ var res = descend(element.childNodes[i]);
+ if (res.isSome())
+ return res;
+ }
+
+ return Option.none();
+ };
+
+ return descend(scope.dom());
+ };
+
+ return {
+ first: first,
+ ancestor: ancestor,
+ closest: closest,
+ sibling: sibling,
+ child: child,
+ descendant: descendant
+ };
+ }
+);
+
+define(
+ 'ephox.sugar.alien.Recurse',
+
+ [
+
+ ],
+
+ function () {
+ /**
+ * Applies f repeatedly until it completes (by returning Option.none()).
+ *
+ * Normally would just use recursion, but JavaScript lacks tail call optimisation.
+ *
+ * This is what recursion looks like when manually unravelled :)
+ */
+ var toArray = function (target, f) {
+ var r = [];
+
+ var recurse = function (e) {
+ r.push(e);
+ return f(e);
+ };
+
+ var cur = f(target);
+ do {
+ cur = cur.bind(recurse);
+ } while (cur.isSome());
+
+ return r;
+ };
+
+ return {
+ toArray: toArray
+ };
+ }
+);
+define(
+ 'ephox.sugar.api.search.Traverse',
+
+ [
+ 'ephox.katamari.api.Type',
+ 'ephox.katamari.api.Arr',
+ 'ephox.katamari.api.Fun',
+ 'ephox.katamari.api.Option',
+ 'ephox.katamari.api.Struct',
+ 'ephox.sugar.alien.Recurse',
+ 'ephox.sugar.api.dom.Compare',
+ 'ephox.sugar.api.node.Element'
+ ],
+
+ function (Type, Arr, Fun, Option, Struct, Recurse, Compare, Element) {
+ // The document associated with the current element
+ var owner = function (element) {
+ return Element.fromDom(element.dom().ownerDocument);
+ };
+
+ var documentElement = function (element) {
+ // TODO: Avoid unnecessary wrap/unwrap here
+ var doc = owner(element);
+ return Element.fromDom(doc.dom().documentElement);
+ };
+
+ // The window element associated with the element
+ var defaultView = function (element) {
+ var el = element.dom();
+ var defaultView = el.ownerDocument.defaultView;
+ return Element.fromDom(defaultView);
+ };
+
+ var parent = function (element) {
+ var dom = element.dom();
+ return Option.from(dom.parentNode).map(Element.fromDom);
+ };
+
+ var findIndex = function (element) {
+ return parent(element).bind(function (p) {
+ // TODO: Refactor out children so we can avoid the constant unwrapping
+ var kin = children(p);
+ return Arr.findIndex(kin, function (elem) {
+ return Compare.eq(element, elem);
+ });
+ });
+ };
+
+ var parents = function (element, isRoot) {
+ var stop = Type.isFunction(isRoot) ? isRoot : Fun.constant(false);
+
+ // This is used a *lot* so it needs to be performant, not recursive
+ var dom = element.dom();
+ var ret = [];
+
+ while (dom.parentNode !== null && dom.parentNode !== undefined) {
+ var rawParent = dom.parentNode;
+ var parent = Element.fromDom(rawParent);
+ ret.push(parent);
+
+ if (stop(parent) === true) break;
+ else dom = rawParent;
+ }
+ return ret;
+ };
+
+ var siblings = function (element) {
+ // TODO: Refactor out children so we can just not add self instead of filtering afterwards
+ var filterSelf = function (elements) {
+ return Arr.filter(elements, function (x) {
+ return !Compare.eq(element, x);
+ });
+ };
+
+ return parent(element).map(children).map(filterSelf).getOr([]);
+ };
+
+ var offsetParent = function (element) {
+ var dom = element.dom();
+ return Option.from(dom.offsetParent).map(Element.fromDom);
+ };
+
+ var prevSibling = function (element) {
+ var dom = element.dom();
+ return Option.from(dom.previousSibling).map(Element.fromDom);
+ };
+
+ var nextSibling = function (element) {
+ var dom = element.dom();
+ return Option.from(dom.nextSibling).map(Element.fromDom);
+ };
+
+ var prevSiblings = function (element) {
+ // This one needs to be reversed, so they're still in DOM order
+ return Arr.reverse(Recurse.toArray(element, prevSibling));
+ };
+
+ var nextSiblings = function (element) {
+ return Recurse.toArray(element, nextSibling);
+ };
+
+ var children = function (element) {
+ var dom = element.dom();
+ return Arr.map(dom.childNodes, Element.fromDom);
+ };
+
+ var child = function (element, index) {
+ var children = element.dom().childNodes;
+ return Option.from(children[index]).map(Element.fromDom);
+ };
+
+ var firstChild = function (element) {
+ return child(element, 0);
+ };
+
+ var lastChild = function (element) {
+ return child(element, element.dom().childNodes.length - 1);
+ };
+
+ var spot = Struct.immutable('element', 'offset');
+ var leaf = function (element, offset) {
+ var cs = children(element);
+ return cs.length > 0 && offset < cs.length ? spot(cs[offset], 0) : spot(element, offset);
+ };
+
+ return {
+ owner: owner,
+ defaultView: defaultView,
+ documentElement: documentElement,
+ parent: parent,
+ findIndex: findIndex,
+ parents: parents,
+ siblings: siblings,
+ prevSibling: prevSibling,
+ offsetParent: offsetParent,
+ prevSiblings: prevSiblings,
+ nextSibling: nextSibling,
+ nextSiblings: nextSiblings,
+ children: children,
+ child: child,
+ firstChild: firstChild,
+ lastChild: lastChild,
+ leaf: leaf
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * EnterKey.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * CaretUtils.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Contains logic for handling the enter key to split/generate block elements.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Utility functions shared by the caret logic.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @class tinymce.EnterKey
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @class tinymce.caret.CaretUtils
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/EnterKey", [
- "tinymce/dom/TreeWalker",
- "tinymce/dom/RangeUtils",
- "tinymce/caret/CaretContainer",
- "tinymce/Env"
-], function(TreeWalker, RangeUtils, CaretContainer, Env) {
- var isIE = Env.ie && Env.ie < 11;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.caret.CaretUtils',
+ [
+ "tinymce.core.util.Fun",
+ "tinymce.core.dom.TreeWalker",
+ "tinymce.core.dom.NodeType",
+ "tinymce.core.caret.CaretPosition",
+ "tinymce.core.caret.CaretContainer",
+ "tinymce.core.caret.CaretCandidate"
+ ],
+ function (Fun, TreeWalker, NodeType, CaretPosition, CaretContainer, CaretCandidate) {
+ var isContentEditableTrue = NodeType.isContentEditableTrue,
+ isContentEditableFalse = NodeType.isContentEditableFalse,
+ isBlockLike = NodeType.matchStyleValues('display', 'block table table-cell table-caption'),
+ isCaretContainer = CaretContainer.isCaretContainer,
+ isCaretContainerBlock = CaretContainer.isCaretContainerBlock,
+ curry = Fun.curry,
+ isElement = NodeType.isElement,
+ isCaretCandidate = CaretCandidate.isCaretCandidate;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function(editor) {
- var dom = editor.dom, selection = editor.selection, settings = editor.settings;
- var undoManager = editor.undoManager, schema = editor.schema, nonEmptyElementsMap = schema.getNonEmptyElements(),
- moveCaretBeforeOnEnterElementsMap = schema.getMoveCaretBeforeOnEnterElements();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isForwards(direction) {
+ return direction > 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function handleEnterKey(evt) {
- var rng, tmpRng, editableRoot, container, offset, parentBlock, documentMode, shiftKey,
- newBlock, fragment, containerBlock, parentBlockName, containerBlockName, newBlockName, isAfterLastNodeInContainer;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isBackwards(direction) {
+ return direction < 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Returns true if the block can be split into two blocks or not
- function canSplitBlock(node) {
- return node &&
- dom.isBlock(node) &&
- !/^(TD|TH|CAPTION|FORM)$/.test(node.nodeName) &&
- !/^(fixed|absolute)/i.test(node.style.position) &&
- dom.getContentEditable(node) !== "true";
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function skipCaretContainers(walk, shallow) {
+ var node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isTableCell(node) {
- return node && /^(TD|TH|CAPTION)$/.test(node.nodeName);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while ((node = walk(shallow))) {
+ if (!isCaretContainerBlock(node)) {
+ return node;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Renders empty block on IE
- function renderBlockOnIE(block) {
- var oldRng;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (dom.isBlock(block)) {
- oldRng = selection.getRng();
- block.appendChild(dom.create('span', null, '\u00a0'));
- selection.select(block);
- block.lastChild.outerHTML = '';
- selection.setRng(oldRng);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function findNode(node, direction, predicateFn, rootNode, shallow) {
+ var walker = new TreeWalker(node, rootNode);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove the first empty inline element of the block so this: <p><b><em></em></b>x</p> becomes this: <p>x</p>
- function trimInlineElementsOnLeftSideOfBlock(block) {
- var node = block, firstChilds = [], i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isBackwards(direction)) {
+ if (isContentEditableFalse(node) || isCaretContainerBlock(node)) {
+ node = skipCaretContainers(walker.prev, true);
+ if (predicateFn(node)) {
+ return node;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!node) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while ((node = skipCaretContainers(walker.prev, shallow))) {
+ if (predicateFn(node)) {
+ return node;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Find inner most first child ex: <p><i><b>*</b></i></p>
- while ((node = node.firstChild)) {
- if (dom.isBlock(node)) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isForwards(direction)) {
+ if (isContentEditableFalse(node) || isCaretContainerBlock(node)) {
+ node = skipCaretContainers(walker.next, true);
+ if (predicateFn(node)) {
+ return node;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.nodeType == 1 && !nonEmptyElementsMap[node.nodeName.toLowerCase()]) {
- firstChilds.push(node);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while ((node = skipCaretContainers(walker.next, shallow))) {
+ if (predicateFn(node)) {
+ return node;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- i = firstChilds.length;
- while (i--) {
- node = firstChilds[i];
- if (!node.hasChildNodes() || (node.firstChild == node.lastChild && node.firstChild.nodeValue === '')) {
- dom.remove(node);
- } else {
- // Remove <a> </a> see #5381
- if (node.nodeName == "A" && (node.innerText || node.textContent) === ' ') {
- dom.remove(node);
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Moves the caret to a suitable position within the root for example in the first non
- // pure whitespace text node or before an image
- function moveToCaretPosition(root) {
- var walker, node, rng, lastNode = root, tempElm;
- function firstNonWhiteSpaceNodeSibling(node) {
- while (node) {
- if (node.nodeType == 1 || (node.nodeType == 3 && node.data && /[\r\n\s]/.test(node.data))) {
- return node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getEditingHost(node, rootNode) {
+ for (node = node.parentNode; node && node != rootNode; node = node.parentNode) {
+ if (isContentEditableTrue(node)) {
+ return node;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.nextSibling;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return rootNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!root) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getParentBlock(node, rootNode) {
+ while (node && node != rootNode) {
+ if (isBlockLike(node)) {
+ return node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Old IE versions doesn't properly render blocks with br elements in them
- // For example <p><br></p> wont be rendered correctly in a contentEditable area
- // until you remove the br producing <p></p>
- if (Env.ie && Env.ie < 9 && parentBlock && parentBlock.firstChild) {
- if (parentBlock.firstChild == parentBlock.lastChild && parentBlock.firstChild.tagName == 'BR') {
- dom.remove(parentBlock.firstChild);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (/^(LI|DT|DD)$/.test(root.nodeName)) {
- var firstChild = firstNonWhiteSpaceNodeSibling(root.firstChild);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (firstChild && /^(UL|OL|DL)$/.test(firstChild.nodeName)) {
- root.insertBefore(dom.doc.createTextNode('\u00a0'), root.firstChild);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isInSameBlock(caretPosition1, caretPosition2, rootNode) {
+ return getParentBlock(caretPosition1.container(), rootNode) == getParentBlock(caretPosition2.container(), rootNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng = dom.createRng();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isInSameEditingHost(caretPosition1, caretPosition2, rootNode) {
+ return getEditingHost(caretPosition1.container(), rootNode) == getEditingHost(caretPosition2.container(), rootNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Normalize whitespace to remove empty text nodes. Fix for: #6904
- // Gecko will be able to place the caret in empty text nodes but it won't render propery
- // Older IE versions will sometimes crash so for now ignore all IE versions
- if (!Env.ie) {
- root.normalize();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getChildNodeAtRelativeOffset(relativeOffset, caretPosition) {
+ var container, offset;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (root.hasChildNodes()) {
- walker = new TreeWalker(root, root);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!caretPosition) {
+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while ((node = walker.current())) {
- if (node.nodeType == 3) {
- rng.setStart(node, 0);
- rng.setEnd(node, 0);
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = caretPosition.container();
+ offset = caretPosition.offset();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (moveCaretBeforeOnEnterElementsMap[node.nodeName.toLowerCase()]) {
- rng.setStartBefore(node);
- rng.setEndBefore(node);
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isElement(container)) {
+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- lastNode = node;
- node = walker.next();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return container.childNodes[offset + relativeOffset];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!node) {
- rng.setStart(lastNode, 0);
- rng.setEnd(lastNode, 0);
- }
- } else {
- if (root.nodeName == 'BR') {
- if (root.nextSibling && dom.isBlock(root.nextSibling)) {
- // Trick on older IE versions to render the caret before the BR between two lists
- if (!documentMode || documentMode < 9) {
- tempElm = dom.create('br');
- root.parentNode.insertBefore(tempElm, root);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function beforeAfter(before, node) {
+ var range = node.ownerDocument.createRange();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng.setStartBefore(root);
- rng.setEndBefore(root);
- } else {
- rng.setStartAfter(root);
- rng.setEndAfter(root);
- }
- } else {
- rng.setStart(root, 0);
- rng.setEnd(root, 0);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (before) {
+ range.setStartBefore(node);
+ range.setEndBefore(node);
+ } else {
+ range.setStartAfter(node);
+ range.setEndAfter(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- selection.setRng(rng);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return range;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove tempElm created for old IE:s
- dom.remove(tempElm);
- selection.scrollIntoView(root);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isNodesInSameBlock(rootNode, node1, node2) {
+ return getParentBlock(node1, rootNode) == getParentBlock(node2, rootNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setForcedBlockAttrs(node) {
- var forcedRootBlockName = settings.forced_root_block;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function lean(left, rootNode, node) {
+ var sibling, siblingName;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (forcedRootBlockName && forcedRootBlockName.toLowerCase() === node.tagName.toLowerCase()) {
- dom.setAttribs(node, settings.forced_root_block_attrs);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (left) {
+ siblingName = 'previousSibling';
+ } else {
+ siblingName = 'nextSibling';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function emptyBlock(elm) {
- // BR is needed in empty blocks on non IE browsers
- elm.innerHTML = !isIE ? '<br data-mce-bogus="1">' : '';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (node && node != rootNode) {
+ sibling = node[siblingName];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Creates a new block element by cloning the current one or creating a new one if the name is specified
- // This function will also copy any text formatting from the parent block and add it to the new one
- function createNewBlock(name) {
- var node = container, block, clonedNode, caretNode, textInlineElements = schema.getTextInlineElements();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isCaretContainer(sibling)) {
+ sibling = sibling[siblingName];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name || parentBlockName == "TABLE") {
- block = dom.create(name || newBlockName);
- setForcedBlockAttrs(block);
- } else {
- block = parentBlock.cloneNode(false);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isContentEditableFalse(sibling)) {
+ if (isNodesInSameBlock(rootNode, sibling, node)) {
+ return sibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- caretNode = block;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Clone any parent styles
- if (settings.keep_styles !== false) {
- do {
- if (textInlineElements[node.nodeName]) {
- // Never clone a caret containers
- if (node.id == '_mce_caret') {
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isCaretCandidate(sibling)) {
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- clonedNode = node.cloneNode(false);
- dom.setAttrib(clonedNode, 'id', ''); // Remove ID since it needs to be document unique
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (block.hasChildNodes()) {
- clonedNode.appendChild(block.firstChild);
- block.appendChild(clonedNode);
- } else {
- caretNode = clonedNode;
- block.appendChild(clonedNode);
- }
- }
- } while ((node = node.parentNode) && node != editableRoot);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // BR is needed in empty blocks on non IE browsers
- if (!isIE) {
- caretNode.innerHTML = '<br data-mce-bogus="1">';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var before = curry(beforeAfter, true);
+ var after = curry(beforeAfter, false);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return block;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function normalizeRange(direction, rootNode, range) {
+ var node, container, offset, location;
+ var leanLeft = curry(lean, true, rootNode);
+ var leanRight = curry(lean, false, rootNode);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Returns true/false if the caret is at the start/end of the parent block element
- function isCaretAtStartOrEndOfBlock(start) {
- var walker, node, name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = range.startContainer;
+ offset = range.startOffset;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Caret is in the middle of a text node like "a|b"
- if (container.nodeType == 3 && (start ? offset > 0 : offset < container.nodeValue.length)) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (CaretContainer.isCaretContainerBlock(container)) {
+ if (!isElement(container)) {
+ container = container.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If after the last element in block node edge case for #5091
- if (container.parentNode == parentBlock && isAfterLastNodeInContainer && !start) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ location = container.getAttribute('data-mce-caret');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If the caret if before the first element in parentBlock
- if (start && container.nodeType == 1 && container == parentBlock.firstChild) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (location == 'before') {
+ node = container.nextSibling;
+ if (isContentEditableFalse(node)) {
+ return before(node);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Caret can be before/after a table
- if (container.nodeName === "TABLE" || (container.previousSibling && container.previousSibling.nodeName == "TABLE")) {
- return (isAfterLastNodeInContainer && !start) || (!isAfterLastNodeInContainer && start);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (location == 'after') {
+ node = container.previousSibling;
+ if (isContentEditableFalse(node)) {
+ return after(node);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Walk the DOM and look for text nodes or non empty elements
- walker = new TreeWalker(container, parentBlock);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!range.collapsed) {
+ return range;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If caret is in beginning or end of a text block then jump to the next/previous node
- if (container.nodeType == 3) {
- if (start && offset === 0) {
- walker.prev();
- } else if (!start && offset == container.nodeValue.length) {
- walker.next();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (NodeType.isText(container)) {
+ if (isCaretContainer(container)) {
+ if (direction === 1) {
+ node = leanRight(container);
+ if (node) {
+ return before(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while ((node = walker.current())) {
- if (node.nodeType === 1) {
- // Ignore bogus elements
- if (!node.getAttribute('data-mce-bogus')) {
- // Keep empty elements like <img /> <input /> but not trailing br:s like <p>text|<br></p>
- name = node.nodeName.toLowerCase();
- if (nonEmptyElementsMap[name] && name !== 'br') {
- return false;
- }
- }
- } else if (node.nodeType === 3 && !/^[ \t\r\n]*$/.test(node.nodeValue)) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = leanLeft(container);
+ if (node) {
+ return after(node);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (start) {
- walker.prev();
- } else {
- walker.next();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (direction === -1) {
+ node = leanLeft(container);
+ if (node) {
+ return after(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = leanRight(container);
+ if (node) {
+ return before(node);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Wraps any text nodes or inline elements in the specified forced root block name
- function wrapSelfAndSiblingsInDefaultBlock(container, offset) {
- var newBlock, parentBlock, startNode, node, next, rootBlockName, blockName = newBlockName || 'P';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return range;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Not in a block element or in a table cell or caption
- parentBlock = dom.getParent(container, dom.isBlock);
- if (!parentBlock || !canSplitBlock(parentBlock)) {
- parentBlock = parentBlock || editableRoot;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (CaretContainer.endsWithCaretContainer(container) && offset >= container.data.length - 1) {
+ if (direction === 1) {
+ node = leanRight(container);
+ if (node) {
+ return before(node);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (parentBlock == editor.getBody() || isTableCell(parentBlock)) {
- rootBlockName = parentBlock.nodeName.toLowerCase();
- } else {
- rootBlockName = parentBlock.parentNode.nodeName.toLowerCase();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return range;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!parentBlock.hasChildNodes()) {
- newBlock = dom.create(blockName);
- setForcedBlockAttrs(newBlock);
- parentBlock.appendChild(newBlock);
- rng.setStart(newBlock, 0);
- rng.setEnd(newBlock, 0);
- return newBlock;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (CaretContainer.startsWithCaretContainer(container) && offset <= 1) {
+ if (direction === -1) {
+ node = leanLeft(container);
+ if (node) {
+ return after(node);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Find parent that is the first child of parentBlock
- node = container;
- while (node.parentNode != parentBlock) {
- node = node.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return range;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Loop left to find start node start wrapping at
- while (node && !dom.isBlock(node)) {
- startNode = node;
- node = node.previousSibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (offset === container.data.length) {
+ node = leanRight(container);
+ if (node) {
+ return before(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (startNode && schema.isValidChild(rootBlockName, blockName.toLowerCase())) {
- newBlock = dom.create(blockName);
- setForcedBlockAttrs(newBlock);
- startNode.parentNode.insertBefore(newBlock, startNode);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return range;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Start wrapping until we hit a block
- node = startNode;
- while (node && !dom.isBlock(node)) {
- next = node.nextSibling;
- newBlock.appendChild(node);
- node = next;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (offset === 0) {
+ node = leanLeft(container);
+ if (node) {
+ return after(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Restore range to it's past location
- rng.setStart(container, offset);
- rng.setEnd(container, offset);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return range;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return container;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return range;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Inserts a block or br before/after or in the middle of a split list of the LI is empty
- function handleEmptyListItem() {
- function isFirstOrLastLi(first) {
- var node = containerBlock[first ? 'firstChild' : 'lastChild'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isNextToContentEditableFalse(relativeOffset, caretPosition) {
+ return isContentEditableFalse(getChildNodeAtRelativeOffset(relativeOffset, caretPosition));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Find first/last element since there might be whitespace there
- while (node) {
- if (node.nodeType == 1) {
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ isForwards: isForwards,
+ isBackwards: isBackwards,
+ findNode: findNode,
+ getEditingHost: getEditingHost,
+ getParentBlock: getParentBlock,
+ isInSameBlock: isInSameBlock,
+ isInSameEditingHost: isInSameEditingHost,
+ isBeforeContentEditableFalse: curry(isNextToContentEditableFalse, 0),
+ isAfterContentEditableFalse: curry(isNextToContentEditableFalse, -1),
+ normalizeRange: normalizeRange
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node[first ? 'nextSibling' : 'previousSibling'];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * CaretWalker.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return node === parentBlock;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * This module contains logic for moving around a virtual caret in logical order within a DOM element.
+ *
+ * It ignores the most obvious invalid caret locations such as within a script element or within a
+ * contentEditable=false element but it will return locations that isn't possible to render visually.
+ *
+ * @private
+ * @class tinymce.caret.CaretWalker
+ * @example
+ * var caretWalker = new CaretWalker(rootElm);
+ *
+ * var prevLogicalCaretPosition = caretWalker.prev(CaretPosition.fromRangeStart(range));
+ * var nextLogicalCaretPosition = caretWalker.next(CaretPosition.fromRangeEnd(range));
+ */
+define(
+ 'tinymce.core.caret.CaretWalker',
+ [
+ "tinymce.core.dom.NodeType",
+ "tinymce.core.caret.CaretCandidate",
+ "tinymce.core.caret.CaretPosition",
+ "tinymce.core.caret.CaretUtils",
+ "tinymce.core.util.Arr",
+ "tinymce.core.util.Fun"
+ ],
+ function (NodeType, CaretCandidate, CaretPosition, CaretUtils, Arr, Fun) {
+ var isContentEditableFalse = NodeType.isContentEditableFalse,
+ isText = NodeType.isText,
+ isElement = NodeType.isElement,
+ isBr = NodeType.isBr,
+ isForwards = CaretUtils.isForwards,
+ isBackwards = CaretUtils.isBackwards,
+ isCaretCandidate = CaretCandidate.isCaretCandidate,
+ isAtomic = CaretCandidate.isAtomic,
+ isEditableCaretCandidate = CaretCandidate.isEditableCaretCandidate;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getContainerBlock() {
- var containerBlockParent = containerBlock.parentNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getParents(node, rootNode) {
+ var parents = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (/^(LI|DT|DD)$/.test(containerBlockParent.nodeName)) {
- return containerBlockParent;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (node && node != rootNode) {
+ parents.push(node);
+ node = node.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return containerBlock;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return parents;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (containerBlock == editor.getBody()) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function nodeAtIndex(container, offset) {
+ if (container.hasChildNodes() && offset < container.childNodes.length) {
+ return container.childNodes[offset];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if we are in an nested list
- var containerBlockParentName = containerBlock.parentNode.nodeName;
- if (/^(OL|UL|LI)$/.test(containerBlockParentName)) {
- newBlockName = 'LI';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- newBlock = newBlockName ? createNewBlock(newBlockName) : dom.create('BR');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getCaretCandidatePosition(direction, node) {
+ if (isForwards(direction)) {
+ if (isCaretCandidate(node.previousSibling) && !isText(node.previousSibling)) {
+ return CaretPosition.before(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isFirstOrLastLi(true) && isFirstOrLastLi()) {
- if (containerBlockParentName == 'LI') {
- // Nested list is inside a LI
- dom.insertAfter(newBlock, getContainerBlock());
- } else {
- // Is first and last list item then replace the OL/UL with a text block
- dom.replace(newBlock, containerBlock);
- }
- } else if (isFirstOrLastLi(true)) {
- if (containerBlockParentName == 'LI') {
- // List nested in an LI then move the list to a new sibling LI
- dom.insertAfter(newBlock, getContainerBlock());
- newBlock.appendChild(dom.doc.createTextNode(' ')); // Needed for IE so the caret can be placed
- newBlock.appendChild(containerBlock);
- } else {
- // First LI in list then remove LI and add text block before list
- containerBlock.parentNode.insertBefore(newBlock, containerBlock);
- }
- } else if (isFirstOrLastLi()) {
- // Last LI in list then remove LI and add text block after list
- dom.insertAfter(newBlock, getContainerBlock());
- renderBlockOnIE(newBlock);
- } else {
- // Middle LI in list the split the list and insert a text block in the middle
- // Extract after fragment and insert it after the current block
- containerBlock = getContainerBlock();
- tmpRng = rng.cloneRange();
- tmpRng.setStartAfter(parentBlock);
- tmpRng.setEndAfter(containerBlock);
- fragment = tmpRng.extractContents();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isText(node)) {
+ return CaretPosition(node, 0);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (newBlockName == 'LI' && fragment.firstChild.nodeName == 'LI') {
- newBlock = fragment.firstChild;
- dom.insertAfter(fragment, containerBlock);
- } else {
- dom.insertAfter(fragment, containerBlock);
- dom.insertAfter(newBlock, containerBlock);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isBackwards(direction)) {
+ if (isCaretCandidate(node.nextSibling) && !isText(node.nextSibling)) {
+ return CaretPosition.after(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.remove(parentBlock);
- moveToCaretPosition(newBlock);
- undoManager.add();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isText(node)) {
+ return CaretPosition(node, node.data.length);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Inserts a BR element if the forced_root_block option is set to false or empty string
- function insertBr() {
- editor.execCommand("InsertLineBreak", false, evt);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isBackwards(direction)) {
+ if (isBr(node)) {
+ return CaretPosition.before(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Trims any linebreaks at the beginning of node user for example when pressing enter in a PRE element
- function trimLeadingLineBreaks(node) {
- do {
- if (node.nodeType === 3) {
- node.nodeValue = node.nodeValue.replace(/^[\r\n]+/, '');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return CaretPosition.after(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.firstChild;
- } while (node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return CaretPosition.before(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getEditableRoot(node) {
- var root = dom.getRoot(), parent, editableRoot;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Jumps over BR elements <p>|<br></p><p>a</p> -> <p><br></p><p>|a</p>
+ function isBrBeforeBlock(node, rootNode) {
+ var next;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Get all parents until we hit a non editable parent or the root
- parent = node;
- while (parent !== root && dom.getContentEditable(parent) !== "false") {
- if (dom.getContentEditable(parent) === "true") {
- editableRoot = parent;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!NodeType.isBr(node)) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parent = parent.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ next = findCaretPosition(1, CaretPosition.after(node), rootNode);
+ if (!next) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return parent !== root ? editableRoot : root;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return !CaretUtils.isInSameBlock(CaretPosition.before(node), CaretPosition.before(next), rootNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Adds a BR at the end of blocks that only contains an IMG or INPUT since
- // these might be floated and then they won't expand the block
- function addBrToBlockIfNeeded(block) {
- var lastChild;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function findCaretPosition(direction, startCaretPosition, rootNode) {
+ var container, offset, node, nextNode, innerNode,
+ rootContentEditableFalseElm, caretPosition;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // IE will render the blocks correctly other browsers needs a BR
- if (!isIE) {
- block.normalize(); // Remove empty text nodes that got left behind by the extract
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isElement(rootNode) || !startCaretPosition) {
+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if the block is empty or contains a floated last child
- lastChild = block.lastChild;
- if (!lastChild || (/^(left|right)$/gi.test(dom.getStyle(lastChild, 'float', true)))) {
- dom.add(block, 'br');
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (startCaretPosition.isEqual(CaretPosition.after(rootNode)) && rootNode.lastChild) {
+ caretPosition = CaretPosition.after(rootNode.lastChild);
+ } else {
+ caretPosition = startCaretPosition;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function insertNewBlockAfter() {
- // If the caret is at the end of a header we produce a P tag after it similar to Word unless we are in a hgroup
- if (/^(H[1-6]|PRE|FIGURE)$/.test(parentBlockName) && containerBlockName != 'HGROUP') {
- newBlock = createNewBlock(newBlockName);
- } else {
- newBlock = createNewBlock();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = caretPosition.container();
+ offset = caretPosition.offset();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Split the current container block element if enter is pressed inside an empty inner block element
- if (settings.end_container_on_empty_block && canSplitBlock(containerBlock) && dom.isEmpty(parentBlock)) {
- // Split container block for example a BLOCKQUOTE at the current blockParent location for example a P
- newBlock = dom.split(containerBlock, parentBlock);
- } else {
- dom.insertAfter(newBlock, parentBlock);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isText(container)) {
+ if (isBackwards(direction) && offset > 0) {
+ return CaretPosition(container, --offset);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- moveToCaretPosition(newBlock);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isForwards(direction) && offset < container.length) {
+ return CaretPosition(container, ++offset);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng = selection.getRng(true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = container;
+ } else {
+ if (isBackwards(direction) && offset > 0) {
+ nextNode = nodeAtIndex(container, offset - 1);
+ if (isCaretCandidate(nextNode)) {
+ if (!isAtomic(nextNode)) {
+ innerNode = CaretUtils.findNode(nextNode, direction, isEditableCaretCandidate, nextNode);
+ if (innerNode) {
+ if (isText(innerNode)) {
+ return CaretPosition(innerNode, innerNode.data.length);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Event is blocked by some other handler for example the lists plugin
- if (evt.isDefaultPrevented()) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return CaretPosition.after(innerNode);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Delete any selected contents
- if (!rng.collapsed) {
- editor.execCommand('Delete');
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isText(nextNode)) {
+ return CaretPosition(nextNode, nextNode.data.length);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup range items and newBlockName
- new RangeUtils(dom).normalize(rng);
- container = rng.startContainer;
- offset = rng.startOffset;
- newBlockName = (settings.force_p_newlines ? 'p' : '') || settings.forced_root_block;
- newBlockName = newBlockName ? newBlockName.toUpperCase() : '';
- documentMode = dom.doc.documentMode;
- shiftKey = evt.shiftKey;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return CaretPosition.before(nextNode);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Resolve node index
- if (container.nodeType == 1 && container.hasChildNodes()) {
- isAfterLastNodeInContainer = offset > container.childNodes.length - 1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isForwards(direction) && offset < container.childNodes.length) {
+ nextNode = nodeAtIndex(container, offset);
+ if (isCaretCandidate(nextNode)) {
+ if (isBrBeforeBlock(nextNode, rootNode)) {
+ return findCaretPosition(direction, CaretPosition.after(nextNode), rootNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container;
- if (isAfterLastNodeInContainer && container.nodeType == 3) {
- offset = container.nodeValue.length;
- } else {
- offset = 0;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isAtomic(nextNode)) {
+ innerNode = CaretUtils.findNode(nextNode, direction, isEditableCaretCandidate, nextNode);
+ if (innerNode) {
+ if (isText(innerNode)) {
+ return CaretPosition(innerNode, 0);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Get editable root node, normally the body element but sometimes a div or span
- editableRoot = getEditableRoot(container);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return CaretPosition.before(innerNode);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If there is no editable root then enter is done inside a contentEditable false element
- if (!editableRoot) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isText(nextNode)) {
+ return CaretPosition(nextNode, 0);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- undoManager.beforeChange();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return CaretPosition.after(nextNode);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If editable root isn't block nor the root of the editor
- if (!dom.isBlock(editableRoot) && editableRoot != dom.getRoot()) {
- if (!newBlockName || shiftKey) {
- insertBr();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = caretPosition.getNode();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((isForwards(direction) && caretPosition.isAtEnd()) || (isBackwards(direction) && caretPosition.isAtStart())) {
+ node = CaretUtils.findNode(node, direction, Fun.constant(true), rootNode, true);
+ if (isEditableCaretCandidate(node)) {
+ return getCaretCandidatePosition(direction, node);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Wrap the current node and it's sibling in a default block if it's needed.
- // for example this <td>text|<b>text2</b></td> will become this <td><p>text|<b>text2</p></b></td>
- // This won't happen if root blocks are disabled or the shiftKey is pressed
- if ((newBlockName && !shiftKey) || (!newBlockName && shiftKey)) {
- container = wrapSelfAndSiblingsInDefaultBlock(container, offset);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ nextNode = CaretUtils.findNode(node, direction, isEditableCaretCandidate, rootNode);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Find parent block and setup empty block paddings
- parentBlock = dom.getParent(container, dom.isBlock);
- containerBlock = parentBlock ? dom.getParent(parentBlock.parentNode, dom.isBlock) : null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rootContentEditableFalseElm = Arr.last(Arr.filter(getParents(container, rootNode), isContentEditableFalse));
+ if (rootContentEditableFalseElm && (!nextNode || !rootContentEditableFalseElm.contains(nextNode))) {
+ if (isForwards(direction)) {
+ caretPosition = CaretPosition.after(rootContentEditableFalseElm);
+ } else {
+ caretPosition = CaretPosition.before(rootContentEditableFalseElm);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup block names
- parentBlockName = parentBlock ? parentBlock.nodeName.toUpperCase() : ''; // IE < 9 & HTML5
- containerBlockName = containerBlock ? containerBlock.nodeName.toUpperCase() : ''; // IE < 9 & HTML5
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return caretPosition;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Enter inside block contained within a LI then split or insert before/after LI
- if (containerBlockName == 'LI' && !evt.ctrlKey) {
- parentBlock = containerBlock;
- parentBlockName = containerBlockName;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (nextNode) {
+ return getCaretCandidatePosition(direction, nextNode);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.undoManager.typing) {
- editor.undoManager.typing = false;
- editor.undoManager.add();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle enter in list item
- if (/^(LI|DT|DD)$/.test(parentBlockName)) {
- if (!newBlockName && shiftKey) {
- insertBr();
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function (rootNode) {
+ return {
+ /**
+ * Returns the next logical caret position from the specificed input
+ * caretPoisiton or null if there isn't any more positions left for example
+ * at the end specified root element.
+ *
+ * @method next
+ * @param {tinymce.caret.CaretPosition} caretPosition Caret position to start from.
+ * @return {tinymce.caret.CaretPosition} CaretPosition or null if no position was found.
+ */
+ next: function (caretPosition) {
+ return findCaretPosition(1, caretPosition, rootNode);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle enter inside an empty list item
- if (dom.isEmpty(parentBlock)) {
- handleEmptyListItem();
- return;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the previous logical caret position from the specificed input
+ * caretPoisiton or null if there isn't any more positions left for example
+ * at the end specified root element.
+ *
+ * @method prev
+ * @param {tinymce.caret.CaretPosition} caretPosition Caret position to start from.
+ * @return {tinymce.caret.CaretPosition} CaretPosition or null if no position was found.
+ */
+ prev: function (caretPosition) {
+ return findCaretPosition(-1, caretPosition, rootNode);
+ }
+ };
+ };
+ }
+);
+/**
+ * CaretFinder.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Don't split PRE tags but insert a BR instead easier when writing code samples etc
- if (parentBlockName == 'PRE' && settings.br_in_pre !== false) {
- if (!shiftKey) {
- insertBr();
- return;
- }
- } else {
- // If no root block is configured then insert a BR by default or if the shiftKey is pressed
- if ((!newBlockName && !shiftKey && parentBlockName != 'LI') || (newBlockName && shiftKey)) {
- insertBr();
- return;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.caret.CaretFinder',
+ [
+ 'ephox.katamari.api.Fun',
+ 'ephox.katamari.api.Option',
+ 'tinymce.core.caret.CaretPosition',
+ 'tinymce.core.caret.CaretWalker'
+ ],
+ function (Fun, Option, CaretPosition, CaretWalker) {
+ var fromPosition = function (forward, rootElement, position) {
+ var walker = new CaretWalker(rootElement);
+ return Option.from(forward ? walker.next(position) : walker.prev(position));
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If parent block is root then never insert new blocks
- if (newBlockName && parentBlock === editor.getBody()) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var positionIn = function (forward, element) {
+ var caretWalker = new CaretWalker(element);
+ var startPos = forward ? CaretPosition.before(element) : CaretPosition.after(element);
+ return Option.from(forward ? caretWalker.next(startPos) : caretWalker.prev(startPos));
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Default block name if it's not configured
- newBlockName = newBlockName || 'P';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ fromPosition: fromPosition,
+ positionIn: positionIn
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Insert new block before/after the parent block depending on caret location
- if (CaretContainer.isCaretContainerBlock(parentBlock)) {
- newBlock = CaretContainer.showCaretContainerBlock(parentBlock);
- if (dom.isEmpty(parentBlock)) {
- emptyBlock(parentBlock);
- }
- moveToCaretPosition(newBlock);
- } else if (isCaretAtStartOrEndOfBlock()) {
- insertNewBlockAfter();
- } else if (isCaretAtStartOrEndOfBlock(true)) {
- // Insert new block before
- newBlock = parentBlock.parentNode.insertBefore(createNewBlock(), parentBlock);
- renderBlockOnIE(newBlock);
- moveToCaretPosition(parentBlock);
- } else {
- // Extract after fragment and insert it after the current block
- tmpRng = rng.cloneRange();
- tmpRng.setEndAfter(parentBlock);
- fragment = tmpRng.extractContents();
- trimLeadingLineBreaks(fragment);
- newBlock = fragment.firstChild;
- dom.insertAfter(fragment, parentBlock);
- trimInlineElementsOnLeftSideOfBlock(newBlock);
- addBrToBlockIfNeeded(parentBlock);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * DeleteUtils.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (dom.isEmpty(parentBlock)) {
- emptyBlock(parentBlock);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.delete.DeleteUtils',
+ [
+ 'ephox.katamari.api.Arr',
+ 'ephox.katamari.api.Option',
+ 'ephox.sugar.api.dom.Compare',
+ 'ephox.sugar.api.node.Element',
+ 'ephox.sugar.api.node.Node',
+ 'ephox.sugar.api.search.PredicateFind'
+ ],
+ function (Arr, Option, Compare, Element, Node, PredicateFind) {
+ var toLookup = function (names) {
+ var lookup = Arr.foldl(names, function (acc, name) {
+ acc[name] = true;
+ return acc;
+ }, { });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- newBlock.normalize();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function (elm) {
+ return lookup[Node.name(elm)] === true;
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // New block might become empty if it's <p><b>a |</b></p>
- if (dom.isEmpty(newBlock)) {
- dom.remove(newBlock);
- insertNewBlockAfter();
- } else {
- moveToCaretPosition(newBlock);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isTextBlock = toLookup([
+ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'div', 'address', 'pre', 'form', 'blockquote', 'center',
+ 'dir', 'fieldset', 'header', 'footer', 'article', 'section', 'hgroup', 'aside', 'nav', 'figure'
+ ]);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.setAttrib(newBlock, 'id', ''); // Remove ID since it needs to be document unique
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isBeforeRoot = function (rootNode) {
+ return function (elm) {
+ return Compare.eq(rootNode, Element.fromDom(elm.dom().parentNode));
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Allow custom handling of new blocks
- editor.fire('NewBlock', {newBlock: newBlock});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getParentTextBlock = function (rootNode, elm) {
+ return Compare.contains(rootNode, elm) ? PredicateFind.closest(elm, isTextBlock, isBeforeRoot(rootNode)) : Option.none();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- undoManager.typing = false;
- undoManager.add();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ getParentTextBlock: getParentTextBlock
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('keydown', function(evt) {
- if (evt.keyCode == 13) {
- if (handleEnterKey(evt) !== false) {
- evt.preventDefault();
- }
- }
- });
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'ephox.sugar.api.search.SelectorFind',
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ForceBlocks.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ [
+ 'ephox.sugar.api.search.PredicateFind',
+ 'ephox.sugar.api.search.Selectors',
+ 'ephox.sugar.impl.ClosestOrAncestor'
+ ],
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function (PredicateFind, Selectors, ClosestOrAncestor) {
+ // TODO: An internal SelectorFilter module that doesn't Element.fromDom() everything
+
+ var first = function (selector) {
+ return Selectors.one(selector);
+ };
+
+ var ancestor = function (scope, selector, isRoot) {
+ return PredicateFind.ancestor(scope, function (e) {
+ return Selectors.is(e, selector);
+ }, isRoot);
+ };
+
+ var sibling = function (scope, selector) {
+ return PredicateFind.sibling(scope, function (e) {
+ return Selectors.is(e, selector);
+ });
+ };
+
+ var child = function (scope, selector) {
+ return PredicateFind.child(scope, function (e) {
+ return Selectors.is(e, selector);
+ });
+ };
+
+ var descendant = function (scope, selector) {
+ return Selectors.one(selector, scope);
+ };
+
+ var closest = function (scope, selector, isRoot) {
+ return ClosestOrAncestor(Selectors.is, ancestor, scope, selector, isRoot);
+ };
+
+ return {
+ first: first,
+ ancestor: ancestor,
+ sibling: sibling,
+ child: child,
+ descendant: descendant,
+ closest: closest
+ };
+ }
+);
+
+define(
+ 'ephox.sugar.api.search.SelectorExists',
+
+ [
+ 'ephox.sugar.api.search.SelectorFind'
+ ],
+
+ function (SelectorFind) {
+ var any = function (selector) {
+ return SelectorFind.first(selector).isSome();
+ };
+
+ var ancestor = function (scope, selector, isRoot) {
+ return SelectorFind.ancestor(scope, selector, isRoot).isSome();
+ };
+
+ var sibling = function (scope, selector) {
+ return SelectorFind.sibling(scope, selector).isSome();
+ };
+
+ var child = function (scope, selector) {
+ return SelectorFind.child(scope, selector).isSome();
+ };
+
+ var descendant = function (scope, selector) {
+ return SelectorFind.descendant(scope, selector).isSome();
+ };
+
+ var closest = function (scope, selector, isRoot) {
+ return SelectorFind.closest(scope, selector, isRoot).isSome();
+ };
+
+ return {
+ any: any,
+ ancestor: ancestor,
+ sibling: sibling,
+ child: child,
+ descendant: descendant,
+ closest: closest
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * ForceBlocks.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Empty.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.Empty',
+ [
+ 'ephox.katamari.api.Fun',
+ 'ephox.sugar.api.dom.Compare',
+ 'ephox.sugar.api.node.Element',
+ 'ephox.sugar.api.search.SelectorExists',
+ 'tinymce.core.caret.CaretCandidate',
+ 'tinymce.core.dom.NodeType',
+ 'tinymce.core.dom.TreeWalker'
+ ],
+ function (Fun, Compare, Element, SelectorExists, CaretCandidate, NodeType, TreeWalker) {
+ var hasWhitespacePreserveParent = function (rootNode, node) {
+ var rootElement = Element.fromDom(rootNode);
+ var startNode = Element.fromDom(node);
+ return SelectorExists.ancestor(startNode, 'pre,code', Fun.curry(Compare.eq, rootElement));
+ };
+
+ var isWhitespace = function (rootNode, node) {
+ return NodeType.isText(node) && /^[ \t\r\n]*$/.test(node.data) && hasWhitespacePreserveParent(rootNode, node) === false;
+ };
+
+ var isNamedAnchor = function (node) {
+ return NodeType.isElement(node) && node.nodeName === 'A' && node.hasAttribute('name');
+ };
+
+ var isContent = function (rootNode, node) {
+ return (CaretCandidate.isCaretCandidate(node) && isWhitespace(rootNode, node) === false) || isNamedAnchor(node) || isBookmark(node);
+ };
+
+ var isBookmark = NodeType.hasAttribute('data-mce-bookmark');
+ var isBogus = NodeType.hasAttribute('data-mce-bogus');
+ var isBogusAll = NodeType.hasAttributeValue('data-mce-bogus', 'all');
+
+ var isEmptyNode = function (targetNode) {
+ var walker, node, brCount = 0;
+
+ if (isContent(targetNode, targetNode)) {
+ return false;
+ } else {
+ node = targetNode.firstChild;
+ if (!node) {
+ return true;
+ }
+
+ walker = new TreeWalker(node, targetNode);
+ do {
+ if (isBogusAll(node)) {
+ node = walker.next(true);
+ continue;
+ }
+
+ if (isBogus(node)) {
+ node = walker.next();
+ continue;
+ }
+
+ if (NodeType.isBr(node)) {
+ brCount++;
+ node = walker.next();
+ continue;
+ }
+
+ if (isContent(targetNode, node)) {
+ return false;
+ }
+
+ node = walker.next();
+ } while (node);
+
+ return brCount <= 1;
+ }
+ };
+
+ var isEmpty = function (elm) {
+ return isEmptyNode(elm.dom());
+ };
+
+ return {
+ isEmpty: isEmpty
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Makes sure that everything gets wrapped in paragraphs.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * BlockBoundary.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @private
- * @class tinymce.ForceBlocks
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ForceBlocks", [], function() {
- return function(editor) {
- var settings = editor.settings, dom = editor.dom, selection = editor.selection;
- var schema = editor.schema, blockElements = schema.getBlockElements();
</del><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function addRootBlocks() {
- var node = selection.getStart(), rootNode = editor.getBody(), rng;
- var startContainer, startOffset, endContainer, endOffset, rootBlockNode;
- var tempNode, offset = -0xFFFFFF, wrapped, restoreSelection;
- var tmpRng, rootNodeName, forcedRootBlock;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.delete.BlockBoundary',
+ [
+ 'ephox.katamari.api.Arr',
+ 'ephox.katamari.api.Fun',
+ 'ephox.katamari.api.Option',
+ 'ephox.katamari.api.Options',
+ 'ephox.katamari.api.Struct',
+ 'ephox.sugar.api.dom.Compare',
+ 'ephox.sugar.api.node.Element',
+ 'ephox.sugar.api.node.Node',
+ 'ephox.sugar.api.search.PredicateFind',
+ 'ephox.sugar.api.search.Traverse',
+ 'tinymce.core.caret.CaretFinder',
+ 'tinymce.core.caret.CaretPosition',
+ 'tinymce.core.delete.DeleteUtils',
+ 'tinymce.core.dom.Empty',
+ 'tinymce.core.dom.NodeType'
+ ],
+ function (Arr, Fun, Option, Options, Struct, Compare, Element, Node, PredicateFind, Traverse, CaretFinder, CaretPosition, DeleteUtils, Empty, NodeType) {
+ var BlockPosition = Struct.immutable('block', 'position');
+ var BlockBoundary = Struct.immutable('from', 'to');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- forcedRootBlock = settings.forced_root_block;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getBlockPosition = function (rootNode, pos) {
+ var rootElm = Element.fromDom(rootNode);
+ var containerElm = Element.fromDom(pos.container());
+ return DeleteUtils.getParentTextBlock(rootElm, containerElm).map(function (block) {
+ return BlockPosition(block, pos);
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!node || node.nodeType !== 1 || !forcedRootBlock) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isDifferentBlocks = function (blockBoundary) {
+ return Compare.eq(blockBoundary.from().block(), blockBoundary.to().block()) === false;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if node is wrapped in block
- while (node && node != rootNode) {
- if (blockElements[node.nodeName]) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var hasSameParent = function (blockBoundary) {
+ return Traverse.parent(blockBoundary.from().block()).bind(function (parent1) {
+ return Traverse.parent(blockBoundary.to().block()).filter(function (parent2) {
+ return Compare.eq(parent1, parent2);
+ });
+ }).isSome();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isEditable = function (blockBoundary) {
+ return NodeType.isContentEditableFalse(blockBoundary.from().block()) === false && NodeType.isContentEditableFalse(blockBoundary.to().block()) === false;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Get current selection
- rng = selection.getRng();
- if (rng.setStart) {
- startContainer = rng.startContainer;
- startOffset = rng.startOffset;
- endContainer = rng.endContainer;
- endOffset = rng.endOffset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var skipLastBr = function (rootNode, forward, blockPosition) {
+ if (NodeType.isBr(blockPosition.position().getNode()) && Empty.isEmpty(blockPosition.block()) === false) {
+ return CaretFinder.positionIn(false, blockPosition.block().dom()).bind(function (lastPositionInBlock) {
+ if (lastPositionInBlock.isEqual(blockPosition.position())) {
+ return CaretFinder.fromPosition(forward, rootNode, lastPositionInBlock).bind(function (to) {
+ return getBlockPosition(rootNode, to);
+ });
+ } else {
+ return Option.some(blockPosition);
+ }
+ }).getOr(blockPosition);
+ } else {
+ return blockPosition;
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- try {
- restoreSelection = editor.getDoc().activeElement === rootNode;
- } catch (ex) {
- // IE throws unspecified error here sometimes
- }
- } else {
- // Force control range into text range
- if (rng.item) {
- node = rng.item(0);
- rng = editor.getDoc().body.createTextRange();
- rng.moveToElementText(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var readFromRange = function (rootNode, forward, rng) {
+ var fromBlockPos = getBlockPosition(rootNode, CaretPosition.fromRangeStart(rng));
+ var toBlockPos = fromBlockPos.bind(function (blockPos) {
+ return CaretFinder.fromPosition(forward, rootNode, blockPos.position()).bind(function (to) {
+ return getBlockPosition(rootNode, to).map(function (blockPos) {
+ return skipLastBr(rootNode, forward, blockPos);
+ });
+ });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- restoreSelection = rng.parentElement().ownerDocument === editor.getDoc();
- tmpRng = rng.duplicate();
- tmpRng.collapse(true);
- startOffset = tmpRng.move('character', offset) * -1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Options.liftN([fromBlockPos, toBlockPos], BlockBoundary).filter(function (blockBoundary) {
+ return isDifferentBlocks(blockBoundary) && hasSameParent(blockBoundary) && isEditable(blockBoundary);
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!tmpRng.collapsed) {
- tmpRng = rng.duplicate();
- tmpRng.collapse(false);
- endOffset = (tmpRng.move('character', offset) * -1) - startOffset;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var read = function (rootNode, forward, rng) {
+ return rng.collapsed ? readFromRange(rootNode, forward, rng) : Option.none();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Wrap non block elements and text nodes
- node = rootNode.firstChild;
- rootNodeName = rootNode.nodeName.toLowerCase();
- while (node) {
- // TODO: Break this up, too complex
- if (((node.nodeType === 3 || (node.nodeType == 1 && !blockElements[node.nodeName]))) &&
- schema.isValidChild(rootNodeName, forcedRootBlock.toLowerCase())) {
- // Remove empty text nodes
- if (node.nodeType === 3 && node.nodeValue.length === 0) {
- tempNode = node;
- node = node.nextSibling;
- dom.remove(tempNode);
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ read: read
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!rootBlockNode) {
- rootBlockNode = dom.create(forcedRootBlock, editor.settings.forced_root_block_attrs);
- node.parentNode.insertBefore(rootBlockNode, node);
- wrapped = true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'ephox.sugar.api.dom.Insert',
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tempNode = node;
- node = node.nextSibling;
- rootBlockNode.appendChild(tempNode);
- } else {
- rootBlockNode = null;
- node = node.nextSibling;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ [
+ 'ephox.sugar.api.search.Traverse'
+ ],
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (wrapped && restoreSelection) {
- if (rng.setStart) {
- rng.setStart(startContainer, startOffset);
- rng.setEnd(endContainer, endOffset);
- selection.setRng(rng);
- } else {
- // Only select if the previous selection was inside the document to prevent auto focus in quirks mode
- try {
- rng = editor.getDoc().body.createTextRange();
- rng.moveToElementText(rootNode);
- rng.collapse(true);
- rng.moveStart('character', startOffset);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function (Traverse) {
+ var before = function (marker, element) {
+ var parent = Traverse.parent(marker);
+ parent.each(function (v) {
+ v.dom().insertBefore(element.dom(), marker.dom());
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (endOffset > 0) {
- rng.moveEnd('character', endOffset);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var after = function (marker, element) {
+ var sibling = Traverse.nextSibling(marker);
+ sibling.fold(function () {
+ var parent = Traverse.parent(marker);
+ parent.each(function (v) {
+ append(v, element);
+ });
+ }, function (v) {
+ before(v, element);
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng.select();
- } catch (ex) {
- // Ignore
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var prepend = function (parent, element) {
+ var firstChild = Traverse.firstChild(parent);
+ firstChild.fold(function () {
+ append(parent, element);
+ }, function (v) {
+ parent.dom().insertBefore(element.dom(), v.dom());
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.nodeChanged();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var append = function (parent, element) {
+ parent.dom().appendChild(element.dom());
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Force root blocks
- if (settings.forced_root_block) {
- editor.on('NodeChange', addRootBlocks);
- }
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var appendAt = function (parent, element, index) {
+ Traverse.child(parent, index).fold(function () {
+ append(parent, element);
+ }, function (v) {
+ before(v, element);
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/caret/CaretUtils.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var wrap = function (element, wrapper) {
+ before(element, wrapper);
+ append(wrapper, element);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ before: before,
+ after: after,
+ prepend: prepend,
+ append: append,
+ appendAt: appendAt,
+ wrap: wrap
+ };
+ }
+);
+
+define(
+ 'ephox.sugar.api.dom.InsertAll',
+
+ [
+ 'ephox.katamari.api.Arr',
+ 'ephox.sugar.api.dom.Insert'
+ ],
+
+ function (Arr, Insert) {
+ var before = function (marker, elements) {
+ Arr.each(elements, function (x) {
+ Insert.before(marker, x);
+ });
+ };
+
+ var after = function (marker, elements) {
+ Arr.each(elements, function (x, i) {
+ var e = i === 0 ? marker : elements[i - 1];
+ Insert.after(e, x);
+ });
+ };
+
+ var prepend = function (parent, elements) {
+ Arr.each(elements.slice().reverse(), function (x) {
+ Insert.prepend(parent, x);
+ });
+ };
+
+ var append = function (parent, elements) {
+ Arr.each(elements, function (x) {
+ Insert.append(parent, x);
+ });
+ };
+
+ return {
+ before: before,
+ after: after,
+ prepend: prepend,
+ append: append
+ };
+ }
+);
+
+define(
+ 'ephox.sugar.api.dom.Remove',
+
+ [
+ 'ephox.katamari.api.Arr',
+ 'ephox.sugar.api.dom.InsertAll',
+ 'ephox.sugar.api.search.Traverse'
+ ],
+
+ function (Arr, InsertAll, Traverse) {
+ var empty = function (element) {
+ // shortcut "empty node" trick. Requires IE 9.
+ element.dom().textContent = '';
+
+ // If the contents was a single empty text node, the above doesn't remove it. But, it's still faster in general
+ // than removing every child node manually.
+ // The following is (probably) safe for performance as 99.9% of the time the trick works and
+ // Traverse.children will return an empty array.
+ Arr.each(Traverse.children(element), function (rogue) {
+ remove(rogue);
+ });
+ };
+
+ var remove = function (element) {
+ var dom = element.dom();
+ if (dom.parentNode !== null)
+ dom.parentNode.removeChild(dom);
+ };
+
+ var unwrap = function (wrapper) {
+ var children = Traverse.children(wrapper);
+ if (children.length > 0)
+ InsertAll.before(wrapper, children);
+ remove(wrapper);
+ };
+
+ return {
+ empty: empty,
+ remove: remove,
+ unwrap: unwrap
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * CaretUtils.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * MergeBlocks.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.delete.MergeBlocks',
+ [
+ 'ephox.katamari.api.Arr',
+ 'ephox.katamari.api.Option',
+ 'ephox.sugar.api.dom.Insert',
+ 'ephox.sugar.api.dom.Remove',
+ 'ephox.sugar.api.node.Element',
+ 'ephox.sugar.api.search.Traverse',
+ 'tinymce.core.caret.CaretFinder',
+ 'tinymce.core.caret.CaretPosition',
+ 'tinymce.core.dom.Empty',
+ 'tinymce.core.dom.NodeType'
+ ],
+ function (Arr, Option, Insert, Remove, Element, Traverse, CaretFinder, CaretPosition, Empty, NodeType) {
+ var mergeBlocksAndReposition = function (fromBlock, toBlock, toPosition) {
+ var children = Traverse.children(fromBlock);
+
+ if (NodeType.isBr(toPosition.getNode())) {
+ Remove.remove(Element.fromDom(toPosition.getNode()));
+ }
+
+ Arr.each(children, function (node) {
+ Insert.append(toBlock, node);
+ });
+
+ if (Empty.isEmpty(fromBlock)) {
+ Remove.remove(fromBlock);
+ }
+
+ return children.length > 0 ? Option.some(toPosition) : Option.none();
+ };
+
+ var mergeBlocks = function (forward, block1, block2) {
+ if (forward) {
+ return CaretFinder.positionIn(false, block1.dom()).bind(function (toPosition) {
+ return mergeBlocksAndReposition(block2, block1, toPosition);
+ });
+ } else {
+ return CaretFinder.positionIn(false, block2.dom()).bind(function (toPosition) {
+ return mergeBlocksAndReposition(block1, block2, toPosition);
+ });
+ }
+ };
+
+ return {
+ mergeBlocks: mergeBlocks
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Utility functions shared by the caret logic.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * BlockBoundaryDelete.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @private
- * @class tinymce.caret.CaretUtils
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/caret/CaretUtils", [
- "tinymce/util/Fun",
- "tinymce/dom/TreeWalker",
- "tinymce/dom/NodeType",
- "tinymce/caret/CaretPosition",
- "tinymce/caret/CaretContainer",
- "tinymce/caret/CaretCandidate"
-], function(Fun, TreeWalker, NodeType, CaretPosition, CaretContainer, CaretCandidate) {
- var isContentEditableTrue = NodeType.isContentEditableTrue,
- isContentEditableFalse = NodeType.isContentEditableFalse,
- isBlockLike = NodeType.matchStyleValues('display', 'block table table-cell table-caption'),
- isCaretContainer = CaretContainer.isCaretContainer,
- isCaretContainerBlock = CaretContainer.isCaretContainerBlock,
- curry = Fun.curry,
- isElement = NodeType.isElement,
- isCaretCandidate = CaretCandidate.isCaretCandidate;
</del><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isForwards(direction) {
- return direction > 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.delete.BlockBoundaryDelete',
+ [
+ 'tinymce.core.delete.BlockBoundary',
+ 'tinymce.core.delete.MergeBlocks'
+ ],
+ function (BlockBoundary, MergeBlocks) {
+ var backspaceDelete = function (editor, forward) {
+ var position;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isBackwards(direction) {
- return direction < 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ position = BlockBoundary.read(editor.getBody(), forward, editor.selection.getRng()).bind(function (blockBoundary) {
+ return MergeBlocks.mergeBlocks(forward, blockBoundary.from().block(), blockBoundary.to().block());
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function skipCaretContainers(walk, shallow) {
- var node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ position.each(function (pos) {
+ editor.selection.setRng(pos.toRange());
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while ((node = walk(shallow))) {
- if (!isCaretContainerBlock(node)) {
- return node;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return position.isSome();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ backspaceDelete: backspaceDelete
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function findNode(node, direction, predicateFn, rootNode, shallow) {
- var walker = new TreeWalker(node, rootNode);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * BlockRangeDelete.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isBackwards(direction)) {
- if (isContentEditableFalse(node) || isCaretContainerBlock(node)) {
- node = skipCaretContainers(walker.prev, true);
- if (predicateFn(node)) {
- return node;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.delete.BlockRangeDelete',
+ [
+ 'ephox.katamari.api.Options',
+ 'ephox.sugar.api.dom.Compare',
+ 'ephox.sugar.api.node.Element',
+ 'tinymce.core.delete.DeleteUtils',
+ 'tinymce.core.delete.MergeBlocks'
+ ],
+ function (Options, Compare, Element, DeleteUtils, MergeBlocks) {
+ var deleteRange = function (rootNode, selection) {
+ var rng = selection.getRng();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while ((node = skipCaretContainers(walker.prev, shallow))) {
- if (predicateFn(node)) {
- return node;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Options.liftN([
+ DeleteUtils.getParentTextBlock(rootNode, Element.fromDom(rng.startContainer)),
+ DeleteUtils.getParentTextBlock(rootNode, Element.fromDom(rng.endContainer))
+ ], function (block1, block2) {
+ if (Compare.eq(block1, block2) === false) {
+ rng.deleteContents();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isForwards(direction)) {
- if (isContentEditableFalse(node) || isCaretContainerBlock(node)) {
- node = skipCaretContainers(walker.next, true);
- if (predicateFn(node)) {
- return node;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ MergeBlocks.mergeBlocks(true, block1, block2).each(function (pos) {
+ selection.setRng(pos.toRange());
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while ((node = skipCaretContainers(walker.next, shallow))) {
- if (predicateFn(node)) {
- return node;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ } else {
+ return false;
+ }
+ }).getOr(false);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var backspaceDelete = function (editor, forward) {
+ var rootNode = Element.fromDom(editor.getBody());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getEditingHost(node, rootNode) {
- for (node = node.parentNode; node && node != rootNode; node = node.parentNode) {
- if (isContentEditableTrue(node)) {
- return node;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.selection.isCollapsed() === false) {
+ return deleteRange(rootNode, editor.selection);
+ } else {
+ return false;
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return rootNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ backspaceDelete: backspaceDelete
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getParentBlock(node, rootNode) {
- while (node && node != rootNode) {
- if (isBlockLike(node)) {
- return node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'ephox.katamari.api.Adt',
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ [
+ 'ephox.katamari.api.Arr',
+ 'ephox.katamari.api.Obj',
+ 'ephox.katamari.api.Type',
+ 'global!Array',
+ 'global!Error',
+ 'global!console'
+ ],
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function (Arr, Obj, Type, Array, Error, console) {
+ /*
+ * Generates a church encoded ADT (https://en.wikipedia.org/wiki/Church_encoding)
+ * For syntax and use, look at the test code.
+ */
+ var generate = function (cases) {
+ // validation
+ if (!Type.isArray(cases)) {
+ throw new Error('cases must be an array');
+ }
+ if (cases.length === 0) {
+ throw new Error('there must be at least one case');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isInSameBlock(caretPosition1, caretPosition2, rootNode) {
- return getParentBlock(caretPosition1.container(), rootNode) == getParentBlock(caretPosition2.container(), rootNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var constructors = [ ];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isInSameEditingHost(caretPosition1, caretPosition2, rootNode) {
- return getEditingHost(caretPosition1.container(), rootNode) == getEditingHost(caretPosition2.container(), rootNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // adt is mutated to add the individual cases
+ var adt = {};
+ Arr.each(cases, function (acase, count) {
+ var keys = Obj.keys(acase);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getChildNodeAtRelativeOffset(relativeOffset, caretPosition) {
- var container, offset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // validation
+ if (keys.length !== 1) {
+ throw new Error('one and only one name per case');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!caretPosition) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var key = keys[0];
+ var value = acase[key];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = caretPosition.container();
- offset = caretPosition.offset();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // validation
+ if (adt[key] !== undefined) {
+ throw new Error('duplicate key detected:' + key);
+ } else if (key === 'cata') {
+ throw new Error('cannot have a case named cata (sorry)');
+ } else if (!Type.isArray(value)) {
+ // this implicitly checks if acase is an object
+ throw new Error('case arguments must be an array');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isElement(container)) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ constructors.push(key);
+ //
+ // constructor for key
+ //
+ adt[key] = function () {
+ var argLength = arguments.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return container.childNodes[offset + relativeOffset];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // validation
+ if (argLength !== value.length) {
+ throw new Error('Wrong number of arguments to case ' + key + '. Expected ' + value.length + ' (' + value + '), got ' + argLength);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function beforeAfter(before, node) {
- var range = node.ownerDocument.createRange();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't use array slice(arguments), makes the whole function unoptimisable on Chrome
+ var args = new Array(argLength);
+ for (var i = 0; i < args.length; i++) args[i] = arguments[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (before) {
- range.setStartBefore(node);
- range.setEndBefore(node);
- } else {
- range.setStartAfter(node);
- range.setEndAfter(node);
- }
</del><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return range;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var match = function (branches) {
+ var branchKeys = Obj.keys(branches);
+ if (constructors.length !== branchKeys.length) {
+ throw new Error('Wrong number of arguments to match. Expected: ' + constructors.join(',') + '\nActual: ' + branchKeys.join(','));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isNodesInSameBlock(rootNode, node1, node2) {
- return getParentBlock(node1, rootNode) == getParentBlock(node2, rootNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var allReqd = Arr.forall(constructors, function (reqKey) {
+ return Arr.contains(branchKeys, reqKey);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function lean(left, rootNode, node) {
- var sibling, siblingName;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!allReqd) throw new Error('Not all branches were specified when using match. Specified: ' + branchKeys.join(', ') + '\nRequired: ' + constructors.join(', '));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (left) {
- siblingName = 'previousSibling';
- } else {
- siblingName = 'nextSibling';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return branches[key].apply(null, args);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (node && node != rootNode) {
- sibling = node[siblingName];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ //
+ // the fold function for key
+ //
+ return {
+ fold: function (/* arguments */) {
+ // runtime validation
+ if (arguments.length !== cases.length) {
+ throw new Error('Wrong number of arguments to fold. Expected ' + cases.length + ', got ' + arguments.length);
+ }
+ var target = arguments[count];
+ return target.apply(null, args);
+ },
+ match: match,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isCaretContainer(sibling)) {
- sibling = sibling[siblingName];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // NOTE: Only for debugging.
+ log: function (label) {
+ console.log(label, {
+ constructors: constructors,
+ constructor: key,
+ params: args
+ });
+ }
+ };
+ };
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isContentEditableFalse(sibling)) {
- if (isNodesInSameBlock(rootNode, sibling, node)) {
- return sibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return adt;
+ };
+ return {
+ generate: generate
+ };
+ }
+);
+/**
+ * CefDeleteAction.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.delete.CefDeleteAction',
+ [
+ 'ephox.katamari.api.Adt',
+ 'ephox.katamari.api.Option',
+ 'tinymce.core.caret.CaretFinder',
+ 'tinymce.core.caret.CaretPosition',
+ 'tinymce.core.caret.CaretUtils',
+ 'tinymce.core.dom.NodeType'
+ ],
+ function (Adt, Option, CaretFinder, CaretPosition, CaretUtils, NodeType) {
+ var DeleteAction = Adt.generate([
+ { remove: [ 'element' ] },
+ { moveToElement: [ 'element' ] },
+ { moveToPosition: [ 'position' ] }
+ ]);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isCaretCandidate(sibling)) {
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isAtContentEditableBlockCaret = function (forward, from) {
+ var elm = from.getNode(forward === false);
+ var caretLocation = forward ? 'after' : 'before';
+ return NodeType.isElement(elm) && elm.getAttribute('data-mce-caret') === caretLocation;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var findCefPosition = function (rootNode, forward, from) {
+ return CaretFinder.fromPosition(forward, rootNode, from).bind(function (to) {
+ if (forward && NodeType.isContentEditableFalse(to.getNode())) {
+ return Option.some(DeleteAction.moveToElement(to.getNode()));
+ } else if (forward === false && NodeType.isContentEditableFalse(to.getNode(true))) {
+ return Option.some(DeleteAction.moveToElement(to.getNode(true)));
+ } else if (forward && CaretUtils.isAfterContentEditableFalse(from)) {
+ return Option.some(DeleteAction.moveToPosition(to));
+ } else if (forward === false && CaretUtils.isBeforeContentEditableFalse(from)) {
+ return Option.some(DeleteAction.moveToPosition(to));
+ } else {
+ return Option.none();
+ }
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getContentEditableBlockAction = function (forward, elm) {
+ if (forward && NodeType.isContentEditableFalse(elm.nextSibling)) {
+ return Option.some(DeleteAction.moveToElement(elm.nextSibling));
+ } else if (forward === false && NodeType.isContentEditableFalse(elm.previousSibling)) {
+ return Option.some(DeleteAction.moveToElement(elm.previousSibling));
+ } else {
+ return Option.none();
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var before = curry(beforeAfter, true);
- var after = curry(beforeAfter, false);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getContentEditableAction = function (rootNode, forward, from) {
+ if (isAtContentEditableBlockCaret(forward, from)) {
+ return getContentEditableBlockAction(forward, from.getNode(forward === false))
+ .fold(
+ function () {
+ return findCefPosition(rootNode, forward, from);
+ },
+ Option.some
+ );
+ } else {
+ return findCefPosition(rootNode, forward, from);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function normalizeRange(direction, rootNode, range) {
- var node, container, offset, location;
- var leanLeft = curry(lean, true, rootNode);
- var leanRight = curry(lean, false, rootNode);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var read = function (rootNode, forward, rng) {
+ var normalizedRange = CaretUtils.normalizeRange(forward ? 1 : -1, rootNode, rng);
+ var from = CaretPosition.fromRangeStart(normalizedRange);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = range.startContainer;
- offset = range.startOffset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (forward === false && CaretUtils.isAfterContentEditableFalse(from)) {
+ return Option.some(DeleteAction.remove(from.getNode(true)));
+ } else if (forward && CaretUtils.isBeforeContentEditableFalse(from)) {
+ return Option.some(DeleteAction.remove(from.getNode()));
+ } else {
+ return getContentEditableAction(rootNode, forward, from);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (CaretContainer.isCaretContainerBlock(container)) {
- if (!isElement(container)) {
- container = container.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ read: read
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- location = container.getAttribute('data-mce-caret');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Bidi.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (location == 'before') {
- node = container.nextSibling;
- if (isContentEditableFalse(node)) {
- return before(node);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.text.Bidi',
+ [
+ ],
+ function () {
+ var strongRtl = /[\u0591-\u07FF\uFB1D-\uFDFF\uFE70-\uFEFC]/;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (location == 'after') {
- node = container.previousSibling;
- if (isContentEditableFalse(node)) {
- return after(node);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var hasStrongRtl = function (text) {
+ return strongRtl.test(text);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!range.collapsed) {
- return range;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ hasStrongRtl: hasStrongRtl
+ };
+ }
+);
+/**
+ * InlineUtils.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (NodeType.isText(container)) {
- if (isCaretContainer(container)) {
- if (direction === 1) {
- node = leanRight(container);
- if (node) {
- return before(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.keyboard.InlineUtils',
+ [
+ 'ephox.katamari.api.Fun',
+ 'ephox.katamari.api.Option',
+ 'ephox.katamari.api.Options',
+ 'tinymce.core.caret.CaretContainer',
+ 'tinymce.core.caret.CaretFinder',
+ 'tinymce.core.caret.CaretPosition',
+ 'tinymce.core.caret.CaretUtils',
+ 'tinymce.core.caret.CaretWalker',
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.core.text.Bidi'
+ ],
+ function (Fun, Option, Options, CaretContainer, CaretFinder, CaretPosition, CaretUtils, CaretWalker, DOMUtils, Bidi) {
+ var isInlineTarget = function (elm) {
+ return DOMUtils.DOM.is(elm, 'a[href],code');
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = leanLeft(container);
- if (node) {
- return after(node);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isRtl = function (element) {
+ return DOMUtils.DOM.getStyle(element, 'direction', true) === 'rtl' || Bidi.hasStrongRtl(element.textContent);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (direction === -1) {
- node = leanLeft(container);
- if (node) {
- return after(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var findInline = function (rootNode, pos) {
+ return Option.from(DOMUtils.DOM.getParent(pos.container(), isInlineTarget, rootNode));
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = leanRight(container);
- if (node) {
- return before(node);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var hasSameParentBlock = function (rootNode, node1, node2) {
+ var block1 = CaretUtils.getParentBlock(node1, rootNode);
+ var block2 = CaretUtils.getParentBlock(node2, rootNode);
+ return block1 && block1 === block2;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return range;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isInInline = function (rootNode, pos) {
+ return pos ? findInline(rootNode, pos).isSome() : false;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (CaretContainer.endsWithCaretContainer(container) && offset >= container.data.length - 1) {
- if (direction === 1) {
- node = leanRight(container);
- if (node) {
- return before(node);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isAtInlineEndPoint = function (rootNode, pos) {
+ return findInline(rootNode, pos).map(function (inline) {
+ return findCaretPosition(inline, false, pos).isNone() || findCaretPosition(inline, true, pos).isNone();
+ }).getOr(false);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return range;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isAtZwsp = function (pos) {
+ return CaretContainer.isBeforeInline(pos) || CaretContainer.isAfterInline(pos);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (CaretContainer.startsWithCaretContainer(container) && offset <= 1) {
- if (direction === -1) {
- node = leanLeft(container);
- if (node) {
- return after(node);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var findCaretPositionIn = function (node, forward) {
+ return CaretFinder.positionIn(forward, node);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return range;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var findCaretPosition = function (rootNode, forward, from) {
+ return CaretFinder.fromPosition(forward, rootNode, from);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (offset === container.data.length) {
- node = leanRight(container);
- if (node) {
- return before(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var normalizePosition = function (forward, pos) {
+ var container = pos.container(), offset = pos.offset();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return range;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (forward) {
+ return CaretContainer.isBeforeInline(pos) ? new CaretPosition(container, offset + 1) : pos;
+ } else {
+ return CaretContainer.isAfterInline(pos) ? new CaretPosition(container, offset - 1) : pos;
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (offset === 0) {
- node = leanLeft(container);
- if (node) {
- return after(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var normalizeForwards = Fun.curry(normalizePosition, true);
+ var normalizeBackwards = Fun.curry(normalizePosition, false);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return range;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ isInlineTarget: isInlineTarget,
+ findInline: findInline,
+ isInInline: isInInline,
+ isRtl: isRtl,
+ isAtInlineEndPoint: isAtInlineEndPoint,
+ isAtZwsp: isAtZwsp,
+ findCaretPositionIn: findCaretPositionIn,
+ findCaretPosition: findCaretPosition,
+ normalizePosition: normalizePosition,
+ normalizeForwards: normalizeForwards,
+ normalizeBackwards: normalizeBackwards,
+ hasSameParentBlock: hasSameParentBlock
+ };
+ }
+);
+/**
+ * DeleteElement.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return range;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.delete.DeleteElement',
+ [
+ 'ephox.katamari.api.Fun',
+ 'ephox.katamari.api.Option',
+ 'ephox.sugar.api.dom.Insert',
+ 'ephox.sugar.api.dom.Remove',
+ 'ephox.sugar.api.node.Element',
+ 'ephox.sugar.api.node.Node',
+ 'ephox.sugar.api.search.PredicateFind',
+ 'tinymce.core.caret.CaretCandidate',
+ 'tinymce.core.caret.CaretPosition',
+ 'tinymce.core.dom.Empty',
+ 'tinymce.core.dom.NodeType',
+ 'tinymce.core.keyboard.InlineUtils'
+ ],
+ function (Fun, Option, Insert, Remove, Element, Node, PredicateFind, CaretCandidate, CaretPosition, Empty, NodeType, InlineUtils) {
+ var needsReposition = function (pos, elm) {
+ var container = pos.container();
+ var offset = pos.offset();
+ return CaretPosition.isTextPosition(pos) === false && container === elm.parentNode && offset > CaretPosition.before(elm).offset();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isNextToContentEditableFalse(relativeOffset, caretPosition) {
- return isContentEditableFalse(getChildNodeAtRelativeOffset(relativeOffset, caretPosition));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var reposition = function (elm, pos) {
+ return needsReposition(pos, elm) ? new CaretPosition(pos.container(), pos.offset() - 1) : pos;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- isForwards: isForwards,
- isBackwards: isBackwards,
- findNode: findNode,
- getEditingHost: getEditingHost,
- getParentBlock: getParentBlock,
- isInSameBlock: isInSameBlock,
- isInSameEditingHost: isInSameEditingHost,
- isBeforeContentEditableFalse: curry(isNextToContentEditableFalse, 0),
- isAfterContentEditableFalse: curry(isNextToContentEditableFalse, -1),
- normalizeRange: normalizeRange
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var beforeOrStartOf = function (node) {
+ return NodeType.isText(node) ? new CaretPosition(node, 0) : CaretPosition.before(node);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/caret/CaretWalker.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var afterOrEndOf = function (node) {
+ return NodeType.isText(node) ? new CaretPosition(node, node.data.length) : CaretPosition.after(node);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var findCaretPosition = function (forward, rootElement, elm) {
+ if (CaretCandidate.isCaretCandidate(elm.previousSibling)) {
+ return Option.some(afterOrEndOf(elm.previousSibling));
+ } else if (CaretCandidate.isCaretCandidate(elm.nextSibling)) {
+ return Option.some(beforeOrStartOf(elm));
+ } else {
+ return InlineUtils.findCaretPosition(rootElement, forward, CaretPosition.before(elm)).fold(
+ function () {
+ return InlineUtils.findCaretPosition(rootElement, !forward, CaretPosition.after(elm));
+ },
+ Option.some
+ );
+ }
+ };
+
+ var findCaretPosOutsideElmAfterDelete = function (forward, rootElement, elm) {
+ return findCaretPosition(forward, rootElement, elm).map(Fun.curry(reposition, elm));
+ };
+
+ var setSelection = function (editor, pos) {
+ pos.fold(
+ function () {
+ editor.focus();
+ },
+ function (pos) {
+ editor.selection.setRng(pos.toRange());
+ }
+ );
+ };
+
+ var eqRawNode = function (rawNode) {
+ return function (elm) {
+ return elm.dom() === rawNode;
+ };
+ };
+
+ var isBlock = function (editor, elm) {
+ return elm && editor.schema.getBlockElements().hasOwnProperty(Node.name(elm));
+ };
+
+ var paddEmptyBlock = function (elm) {
+ if (Empty.isEmpty(elm)) {
+ var br = Element.fromHtml('<br data-mce-bogus="1">');
+ Remove.empty(elm);
+ Insert.append(elm, br);
+ return Option.some(CaretPosition.before(br.dom()));
+ } else {
+ return Option.none();
+ }
+ };
+
+ var deleteElement = function (editor, forward, elm) {
+ var afterDeletePos = findCaretPosOutsideElmAfterDelete(forward, editor.getBody(), elm.dom());
+ var parentBlock = PredicateFind.ancestor(elm, Fun.curry(isBlock, editor), eqRawNode(editor.getBody()));
+
+ Remove.remove(elm);
+
+ parentBlock.bind(paddEmptyBlock).fold(
+ function () {
+ setSelection(editor, afterDeletePos);
+ },
+ function (paddPos) {
+ setSelection(editor, Option.some(paddPos));
+ }
+ );
+ };
+
+ return {
+ deleteElement: deleteElement
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * CaretWalker.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * CefDelete.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.delete.CefDelete',
+ [
+ 'ephox.sugar.api.node.Element',
+ 'tinymce.core.caret.CaretPosition',
+ 'tinymce.core.caret.CaretUtils',
+ 'tinymce.core.delete.BlockBoundary',
+ 'tinymce.core.delete.CefDeleteAction',
+ 'tinymce.core.delete.DeleteElement',
+ 'tinymce.core.delete.MergeBlocks',
+ 'tinymce.core.dom.NodeType'
+ ],
+ function (Element, CaretPosition, CaretUtils, BlockBoundary, CefDeleteAction, DeleteElement, MergeBlocks, NodeType) {
+ var deleteElement = function (editor, forward) {
+ return function (element) {
+ DeleteElement.deleteElement(editor, forward, Element.fromDom(element));
+ return true;
+ };
+ };
+
+ var moveToElement = function (editor, forward) {
+ return function (element) {
+ var pos = forward ? CaretPosition.before(element) : CaretPosition.after(element);
+ editor.selection.setRng(pos.toRange());
+ return true;
+ };
+ };
+
+ var moveToPosition = function (editor) {
+ return function (pos) {
+ editor.selection.setRng(pos.toRange());
+ return true;
+ };
+ };
+
+ var backspaceDeleteCaret = function (editor, forward) {
+ var result = CefDeleteAction.read(editor.getBody(), forward, editor.selection.getRng()).map(function (deleteAction) {
+ return deleteAction.fold(
+ deleteElement(editor, forward),
+ moveToElement(editor, forward),
+ moveToPosition(editor)
+ );
+ });
+
+ return result.getOr(false);
+ };
+
+ var backspaceDeleteRange = function (editor, forward) {
+ var selectedElement = editor.selection.getNode();
+ if (NodeType.isContentEditableFalse(selectedElement)) {
+ DeleteElement.deleteElement(editor, forward, Element.fromDom(editor.selection.getNode()));
+ return true;
+ } else {
+ return false;
+ }
+ };
+
+ var getContentEditableRoot = function (root, node) {
+ while (node && node !== root) {
+ if (NodeType.isContentEditableTrue(node) || NodeType.isContentEditableFalse(node)) {
+ return node;
+ }
+
+ node = node.parentNode;
+ }
+
+ return null;
+ };
+
+ var paddEmptyElement = function (editor) {
+ var br, ceRoot = getContentEditableRoot(editor.getBody(), editor.selection.getNode());
+
+ if (NodeType.isContentEditableTrue(ceRoot) && editor.dom.isBlock(ceRoot) && editor.dom.isEmpty(ceRoot)) {
+ br = editor.dom.create('br', { "data-mce-bogus": "1" });
+ editor.dom.setHTML(ceRoot, '');
+ ceRoot.appendChild(br);
+ editor.selection.setRng(CaretPosition.before(br).toRange());
+ }
+
+ return true;
+ };
+
+ var backspaceDelete = function (editor, forward) {
+ if (editor.selection.isCollapsed()) {
+ return backspaceDeleteCaret(editor, forward);
+ } else {
+ return backspaceDeleteRange(editor, forward);
+ }
+ };
+
+ return {
+ backspaceDelete: backspaceDelete,
+ paddEmptyElement: paddEmptyElement
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * This module contains logic for moving around a virtual caret in logical order within a DOM element.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * CaretContainerInline.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * It ignores the most obvious invalid caret locations such as within a script element or within a
- * contentEditable=false element but it will return locations that isn't possible to render visually.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @private
- * @class tinymce.caret.CaretWalker
- * @example
- * var caretWalker = new CaretWalker(rootElm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.core.caret.CaretContainerInline',
+ [
+ 'ephox.katamari.api.Fun',
+ 'tinymce.core.dom.NodeType',
+ 'tinymce.core.text.Zwsp'
+ ],
+ function (Fun, NodeType, Zwsp) {
+ var isText = NodeType.isText;
+
+ var startsWithCaretContainer = function (node) {
+ return isText(node) && node.data[0] === Zwsp.ZWSP;
+ };
+
+ var endsWithCaretContainer = function (node) {
+ return isText(node) && node.data[node.data.length - 1] === Zwsp.ZWSP;
+ };
+
+ var createZwsp = function (node) {
+ return node.ownerDocument.createTextNode(Zwsp.ZWSP);
+ };
+
+ var insertBefore = function (node) {
+ if (isText(node.previousSibling)) {
+ if (endsWithCaretContainer(node.previousSibling)) {
+ return node.previousSibling;
+ } else {
+ node.previousSibling.appendData(Zwsp.ZWSP);
+ return node.previousSibling;
+ }
+ } else if (isText(node)) {
+ if (startsWithCaretContainer(node)) {
+ return node;
+ } else {
+ node.insertData(0, Zwsp.ZWSP);
+ return node;
+ }
+ } else {
+ var newNode = createZwsp(node);
+ node.parentNode.insertBefore(newNode, node);
+ return newNode;
+ }
+ };
+
+ var insertAfter = function (node) {
+ if (isText(node.nextSibling)) {
+ if (startsWithCaretContainer(node.nextSibling)) {
+ return node.nextSibling;
+ } else {
+ node.nextSibling.insertData(0, Zwsp.ZWSP);
+ return node.nextSibling;
+ }
+ } else if (isText(node)) {
+ if (endsWithCaretContainer(node)) {
+ return node;
+ } else {
+ node.appendData(Zwsp.ZWSP);
+ return node;
+ }
+ } else {
+ var newNode = createZwsp(node);
+ if (node.nextSibling) {
+ node.parentNode.insertBefore(newNode, node.nextSibling);
+ } else {
+ node.parentNode.appendChild(newNode);
+ }
+ return newNode;
+ }
+ };
+
+ var insertInline = function (before, node) {
+ return before ? insertBefore(node) : insertAfter(node);
+ };
+
+ return {
+ insertInline: insertInline,
+ insertInlineBefore: Fun.curry(insertInline, true),
+ insertInlineAfter: Fun.curry(insertInline, false)
+ };
+ }
+);
+/**
+ * CaretContainerRemove.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * var prevLogicalCaretPosition = caretWalker.prev(CaretPosition.fromRangeStart(range));
- * var nextLogicalCaretPosition = caretWalker.next(CaretPosition.fromRangeEnd(range));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/caret/CaretWalker", [
- "tinymce/dom/NodeType",
- "tinymce/caret/CaretCandidate",
- "tinymce/caret/CaretPosition",
- "tinymce/caret/CaretUtils",
- "tinymce/util/Arr",
- "tinymce/util/Fun"
-], function(NodeType, CaretCandidate, CaretPosition, CaretUtils, Arr, Fun) {
- var isContentEditableFalse = NodeType.isContentEditableFalse,
- isText = NodeType.isText,
- isElement = NodeType.isElement,
- isBr = NodeType.isBr,
- isForwards = CaretUtils.isForwards,
- isBackwards = CaretUtils.isBackwards,
- isCaretCandidate = CaretCandidate.isCaretCandidate,
- isAtomic = CaretCandidate.isAtomic,
- isEditableCaretCandidate = CaretCandidate.isEditableCaretCandidate;
</del><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getParents(node, rootNode) {
- var parents = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.caret.CaretContainerRemove',
+ [
+ 'ephox.katamari.api.Arr',
+ 'tinymce.core.caret.CaretContainer',
+ 'tinymce.core.caret.CaretPosition',
+ 'tinymce.core.dom.NodeType',
+ 'tinymce.core.text.Zwsp',
+ 'tinymce.core.util.Tools'
+ ],
+ function (Arr, CaretContainer, CaretPosition, NodeType, Zwsp, Tools) {
+ var isElement = NodeType.isElement;
+ var isText = NodeType.isText;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (node && node != rootNode) {
- parents.push(node);
- node = node.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var removeNode = function (node) {
+ var parentNode = node.parentNode;
+ if (parentNode) {
+ parentNode.removeChild(node);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return parents;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getNodeValue = function (node) {
+ try {
+ return node.nodeValue;
+ } catch (ex) {
+ // IE sometimes produces "Invalid argument" on nodes
+ return "";
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function nodeAtIndex(container, offset) {
- if (container.hasChildNodes() && offset < container.childNodes.length) {
- return container.childNodes[offset];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var setNodeValue = function (node, text) {
+ if (text.length === 0) {
+ removeNode(node);
+ } else {
+ node.nodeValue = text;
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var trimCount = function (text) {
+ var trimmedText = Zwsp.trim(text);
+ return { count: text.length - trimmedText.length, text: trimmedText };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getCaretCandidatePosition(direction, node) {
- if (isForwards(direction)) {
- if (isCaretCandidate(node.previousSibling) && !isText(node.previousSibling)) {
- return CaretPosition.before(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var removeUnchanged = function (caretContainer, pos) {
+ remove(caretContainer);
+ return pos;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isText(node)) {
- return CaretPosition(node, 0);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var removeTextAndReposition = function (caretContainer, pos) {
+ var before = trimCount(caretContainer.data.substr(0, pos.offset()));
+ var after = trimCount(caretContainer.data.substr(pos.offset()));
+ var text = before.text + after.text;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isBackwards(direction)) {
- if (isCaretCandidate(node.nextSibling) && !isText(node.nextSibling)) {
- return CaretPosition.after(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (text.length > 0) {
+ setNodeValue(caretContainer, text);
+ return new CaretPosition(caretContainer, pos.offset() - before.count);
+ } else {
+ return pos;
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isText(node)) {
- return CaretPosition(node, node.data.length);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var removeElementAndReposition = function (caretContainer, pos) {
+ var parentNode = pos.container();
+ var newPosition = Arr.indexOf(parentNode.childNodes, caretContainer).map(function (index) {
+ return index < pos.offset() ? new CaretPosition(parentNode, pos.offset() - 1) : pos;
+ }).getOr(pos);
+ remove(caretContainer);
+ return newPosition;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isBackwards(direction)) {
- if (isBr(node)) {
- return CaretPosition.before(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var removeTextCaretContainer = function (caretContainer, pos) {
+ return pos.container() === caretContainer ? removeTextAndReposition(caretContainer, pos) : removeUnchanged(caretContainer, pos);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return CaretPosition.after(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var removeElementCaretContainer = function (caretContainer, pos) {
+ return pos.container() === caretContainer.parentNode ? removeElementAndReposition(caretContainer, pos) : removeUnchanged(caretContainer, pos);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return CaretPosition.before(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var removeAndReposition = function (container, pos) {
+ return CaretPosition.isTextPosition(pos) ? removeTextCaretContainer(container, pos) : removeElementCaretContainer(container, pos);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Jumps over BR elements <p>|<br></p><p>a</p> -> <p><br></p><p>|a</p>
- function isBrBeforeBlock(node, rootNode) {
- var next;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var remove = function (caretContainerNode) {
+ if (isElement(caretContainerNode) && CaretContainer.isCaretContainer(caretContainerNode)) {
+ if (CaretContainer.hasContent(caretContainerNode)) {
+ caretContainerNode.removeAttribute('data-mce-caret');
+ } else {
+ removeNode(caretContainerNode);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!NodeType.isBr(node)) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isText(caretContainerNode)) {
+ var text = Zwsp.trim(getNodeValue(caretContainerNode));
+ setNodeValue(caretContainerNode, text);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- next = findCaretPosition(1, CaretPosition.after(node), rootNode);
- if (!next) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ removeAndReposition: removeAndReposition,
+ remove: remove
+ };
+ }
+);
+/**
+ * BoundaryCaret.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return !CaretUtils.isInSameBlock(CaretPosition.before(node), CaretPosition.before(next), rootNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.keyboard.BoundaryCaret',
+ [
+ 'ephox.katamari.api.Option',
+ 'tinymce.core.caret.CaretContainer',
+ 'tinymce.core.caret.CaretContainerInline',
+ 'tinymce.core.caret.CaretContainerRemove',
+ 'tinymce.core.caret.CaretPosition',
+ 'tinymce.core.dom.NodeType',
+ 'tinymce.core.keyboard.InlineUtils'
+ ],
+ function (Option, CaretContainer, CaretContainerInline, CaretContainerRemove, CaretPosition, NodeType, InlineUtils) {
+ var insertInlinePos = function (pos, before) {
+ if (NodeType.isText(pos.container())) {
+ return CaretContainerInline.insertInline(before, pos.container());
+ } else {
+ return CaretContainerInline.insertInline(before, pos.getNode());
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function findCaretPosition(direction, startCaretPosition, rootNode) {
- var container, offset, node, nextNode, innerNode,
- rootContentEditableFalseElm, caretPosition;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var renderCaret = function (caret, location) {
+ return location.fold(
+ function (element) { // Before
+ CaretContainerRemove.remove(caret.get());
+ var text = CaretContainerInline.insertInlineBefore(element);
+ caret.set(text);
+ return Option.some(new CaretPosition(text, text.length - 1));
+ },
+ function (element) { // Start
+ return InlineUtils.findCaretPositionIn(element, true).map(function (pos) {
+ CaretContainerRemove.remove(caret.get());
+ var text = insertInlinePos(pos, true);
+ caret.set(text);
+ return new CaretPosition(text, 1);
+ });
+ },
+ function (element) { // End
+ return InlineUtils.findCaretPositionIn(element, false).map(function (pos) {
+ CaretContainerRemove.remove(caret.get());
+ var text = insertInlinePos(pos, false);
+ caret.set(text);
+ return new CaretPosition(text, text.length - 1);
+ });
+ },
+ function (element) { // After
+ CaretContainerRemove.remove(caret.get());
+ var text = CaretContainerInline.insertInlineAfter(element);
+ caret.set(text);
+ return Option.some(new CaretPosition(text, 1));
+ }
+ );
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isElement(rootNode) || !startCaretPosition) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ renderCaret: renderCaret
+ };
+ }
+);
+/**
+ * LazyEvaluator.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- caretPosition = startCaretPosition;
- container = caretPosition.container();
- offset = caretPosition.offset();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.LazyEvaluator',
+ [
+ 'ephox.katamari.api.Option'
+ ],
+ function (Option) {
+ var evaluateUntil = function (fns, args) {
+ for (var i = 0; i < fns.length; i++) {
+ var result = fns[i].apply(null, args);
+ if (result.isSome()) {
+ return result;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isText(container)) {
- if (isBackwards(direction) && offset > 0) {
- return CaretPosition(container, --offset);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Option.none();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isForwards(direction) && offset < container.length) {
- return CaretPosition(container, ++offset);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ evaluateUntil: evaluateUntil
+ };
+ }
+);
+/**
+ * BoundaryLocation.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = container;
- } else {
- if (isBackwards(direction) && offset > 0) {
- nextNode = nodeAtIndex(container, offset - 1);
- if (isCaretCandidate(nextNode)) {
- if (!isAtomic(nextNode)) {
- innerNode = CaretUtils.findNode(nextNode, direction, isEditableCaretCandidate, nextNode);
- if (innerNode) {
- if (isText(innerNode)) {
- return CaretPosition(innerNode, innerNode.data.length);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.keyboard.BoundaryLocation',
+ [
+ 'ephox.katamari.api.Adt',
+ 'ephox.katamari.api.Fun',
+ 'ephox.katamari.api.Option',
+ 'ephox.katamari.api.Options',
+ 'tinymce.core.caret.CaretContainer',
+ 'tinymce.core.caret.CaretPosition',
+ 'tinymce.core.caret.CaretUtils',
+ 'tinymce.core.dom.NodeType',
+ 'tinymce.core.keyboard.InlineUtils',
+ 'tinymce.core.util.LazyEvaluator'
+ ],
+ function (Adt, Fun, Option, Options, CaretContainer, CaretPosition, CaretUtils, NodeType, InlineUtils, LazyEvaluator) {
+ var Location = Adt.generate([
+ { before: [ 'element' ] },
+ { start: [ 'element' ] },
+ { end: [ 'element' ] },
+ { after: [ 'element' ] }
+ ]);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return CaretPosition.after(innerNode);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var before = function (rootNode, pos) {
+ var nPos = InlineUtils.normalizeForwards(pos);
+ return InlineUtils.findInline(rootNode, nPos).fold(
+ function () {
+ return InlineUtils.findCaretPosition(rootNode, true, nPos)
+ .bind(Fun.curry(InlineUtils.findInline, rootNode))
+ .map(function (inline) {
+ return Location.before(inline);
+ });
+ },
+ Option.none
+ );
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isText(nextNode)) {
- return CaretPosition(nextNode, nextNode.data.length);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var start = function (rootNode, pos) {
+ var nPos = InlineUtils.normalizeBackwards(pos);
+ return InlineUtils.findInline(rootNode, nPos).bind(function (inline) {
+ var prevPos = InlineUtils.findCaretPosition(inline, false, nPos);
+ return prevPos.isNone() ? Option.some(Location.start(inline)) : Option.none();
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return CaretPosition.before(nextNode);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var end = function (rootNode, pos) {
+ var nPos = InlineUtils.normalizeForwards(pos);
+ return InlineUtils.findInline(rootNode, nPos).bind(function (inline) {
+ var nextPos = InlineUtils.findCaretPosition(inline, true, nPos);
+ return nextPos.isNone() ? Option.some(Location.end(inline)) : Option.none();
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isForwards(direction) && offset < container.childNodes.length) {
- nextNode = nodeAtIndex(container, offset);
- if (isCaretCandidate(nextNode)) {
- if (isBrBeforeBlock(nextNode, rootNode)) {
- return findCaretPosition(direction, CaretPosition.after(nextNode), rootNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var after = function (rootNode, pos) {
+ var nPos = InlineUtils.normalizeBackwards(pos);
+ return InlineUtils.findInline(rootNode, nPos).fold(
+ function () {
+ return InlineUtils.findCaretPosition(rootNode, false, nPos)
+ .bind(Fun.curry(InlineUtils.findInline, rootNode))
+ .map(function (inline) {
+ return Location.after(inline);
+ });
+ },
+ Option.none
+ );
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isAtomic(nextNode)) {
- innerNode = CaretUtils.findNode(nextNode, direction, isEditableCaretCandidate, nextNode);
- if (innerNode) {
- if (isText(innerNode)) {
- return CaretPosition(innerNode, 0);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isValidLocation = function (location) {
+ return InlineUtils.isRtl(getElement(location)) === false;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return CaretPosition.before(innerNode);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var readLocation = function (rootNode, pos) {
+ var location = LazyEvaluator.evaluateUntil([
+ before,
+ start,
+ end,
+ after
+ ], [rootNode, pos]);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isText(nextNode)) {
- return CaretPosition(nextNode, 0);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return location.filter(isValidLocation);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return CaretPosition.after(nextNode);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getElement = function (location) {
+ return location.fold(
+ Fun.identity, // Before
+ Fun.identity, // Start
+ Fun.identity, // End
+ Fun.identity // After
+ );
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = caretPosition.getNode();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var outside = function (location) {
+ return location.fold(
+ Location.before, // Before
+ Location.before, // Start
+ Location.after, // End
+ Location.after // After
+ );
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ((isForwards(direction) && caretPosition.isAtEnd()) || (isBackwards(direction) && caretPosition.isAtStart())) {
- node = CaretUtils.findNode(node, direction, Fun.constant(true), rootNode, true);
- if (isEditableCaretCandidate(node)) {
- return getCaretCandidatePosition(direction, node);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var inside = function (location) {
+ return location.fold(
+ Location.start, // Before
+ Location.start, // Start
+ Location.end, // End
+ Location.end // After
+ );
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- nextNode = CaretUtils.findNode(node, direction, isEditableCaretCandidate, rootNode);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isInside = function (location) {
+ return location.fold(
+ Fun.constant(false), // Before
+ Fun.constant(true), // Start
+ Fun.constant(true), // End
+ Fun.constant(false) // After
+ );
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rootContentEditableFalseElm = Arr.last(Arr.filter(getParents(container, rootNode), isContentEditableFalse));
- if (rootContentEditableFalseElm && (!nextNode || !rootContentEditableFalseElm.contains(nextNode))) {
- if (isForwards(direction)) {
- caretPosition = CaretPosition.after(rootContentEditableFalseElm);
- } else {
- caretPosition = CaretPosition.before(rootContentEditableFalseElm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var betweenInlines = function (forward, rootNode, from, to, location) {
+ return Options.liftN([
+ InlineUtils.findInline(rootNode, from),
+ InlineUtils.findInline(rootNode, to)
+ ], function (fromInline, toInline) {
+ if (fromInline !== toInline && InlineUtils.hasSameParentBlock(rootNode, fromInline, toInline)) {
+ // Force after since some browsers normalize and lean left into the closest inline
+ return Location.after(forward ? fromInline : toInline);
+ } else {
+ return location;
+ }
+ }).getOr(location);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return caretPosition;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isFirstPositionInBlock = function (rootBlock, pos) {
+ return InlineUtils.findCaretPosition(rootBlock, false, pos).isNone();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (nextNode) {
- return getCaretCandidatePosition(direction, nextNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isLastPositionInBlock = function (rootBlock, pos) {
+ return InlineUtils.findCaretPosition(rootBlock, true, pos).bind(function (nextPos) {
+ if (NodeType.isBr(nextPos.getNode())) {
+ return InlineUtils.findCaretPosition(rootBlock, true, CaretPosition.after(nextPos.getNode()));
+ } else {
+ return Option.some(nextPos);
+ }
+ }).isNone();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isEndPositionInBlock = function (forward, rootBlock, pos) {
+ return forward ? isLastPositionInBlock(rootBlock, pos) : isFirstPositionInBlock(rootBlock, pos);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function(rootNode) {
- return {
- /**
- * Returns the next logical caret position from the specificed input
- * caretPoisiton or null if there isn't any more positions left for example
- * at the end specified root element.
- *
- * @method next
- * @param {tinymce.caret.CaretPosition} caretPosition Caret position to start from.
- * @return {tinymce.caret.CaretPosition} CaretPosition or null if no position was found.
- */
- next: function(caretPosition) {
- return findCaretPosition(1, caretPosition, rootNode);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var onlyOutside = function (location) {
+ if (isInside(location)) {
+ return Option.some(outside(location));
+ } else {
+ return Option.none();
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the previous logical caret position from the specificed input
- * caretPoisiton or null if there isn't any more positions left for example
- * at the end specified root element.
- *
- * @method prev
- * @param {tinymce.caret.CaretPosition} caretPosition Caret position to start from.
- * @return {tinymce.caret.CaretPosition} CaretPosition or null if no position was found.
- */
- prev: function(caretPosition) {
- return findCaretPosition(-1, caretPosition, rootNode);
- }
- };
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var findFirstOrLastLocationInBlock = function (rootNode, forward, toBlock) {
+ return InlineUtils.findCaretPositionIn(toBlock, forward).bind(function (lastPosition) {
+ return readLocation(toBlock, lastPosition).map(outside);
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/InsertList.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var betweenBlocks = function (forward, rootNode, from, to, location) {
+ var fromBlock = CaretUtils.getParentBlock(from.container(), rootNode);
+ if (isEndPositionInBlock(forward, fromBlock, to) && isInside(location) === false) {
+ return readLocation(rootNode, from).bind(onlyOutside);
+ } else if (isEndPositionInBlock(forward, fromBlock, from)) {
+ return readLocation(rootNode, from)
+ .bind(onlyOutside)
+ .orThunk(function () {
+ return Option.from(CaretUtils.getParentBlock(to.container(), rootNode)).bind(function (toBlock) {
+ return findFirstOrLastLocationInBlock(rootNode, forward, toBlock);
+ });
+ });
+ } else {
+ return Option.some(location);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var findLocation = function (forward, rootNode, pos) {
+ var from = InlineUtils.normalizePosition(forward, pos);
+ var to = InlineUtils.findCaretPosition(rootNode, forward, from).map(Fun.curry(InlineUtils.normalizePosition, forward));
+ var location = to.fold(
+ function () {
+ return readLocation(rootNode, from).map(outside);
+ },
+ function (to) {
+ return readLocation(rootNode, to)
+ .bind(Fun.curry(betweenBlocks, forward, rootNode, from, to))
+ .map(Fun.curry(betweenInlines, forward, rootNode, from, to));
+ }
+ );
+
+ return location.filter(isValidLocation);
+ };
+
+ return {
+ readLocation: readLocation,
+ prevLocation: Fun.curry(findLocation, false),
+ nextLocation: Fun.curry(findLocation, true),
+ getElement: getElement,
+ outside: outside,
+ inside: inside
+ };
+ }
+);
+define(
+ 'ephox.katamari.api.Cell',
+
+ [
+ ],
+
+ function () {
+ var Cell = function (initial) {
+ var value = initial;
+
+ var get = function () {
+ return value;
+ };
+
+ var set = function (v) {
+ value = v;
+ };
+
+ var clone = function () {
+ return Cell(get());
+ };
+
+ return {
+ get: get,
+ set: set,
+ clone: clone
+ };
+ };
+
+ return Cell;
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * BoundarySelection.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.core.keyboard.BoundarySelection',
+ [
+ 'ephox.katamari.api.Arr',
+ 'ephox.katamari.api.Cell',
+ 'ephox.katamari.api.Fun',
+ 'tinymce.core.caret.CaretContainerRemove',
+ 'tinymce.core.caret.CaretPosition',
+ 'tinymce.core.keyboard.BoundaryCaret',
+ 'tinymce.core.keyboard.BoundaryLocation',
+ 'tinymce.core.keyboard.InlineUtils'
+ ],
+ function (Arr, Cell, Fun, CaretContainerRemove, CaretPosition, BoundaryCaret, BoundaryLocation, InlineUtils) {
+ var setCaretPosition = function (editor, pos) {
+ var rng = editor.dom.createRng();
+ rng.setStart(pos.container(), pos.offset());
+ rng.setEnd(pos.container(), pos.offset());
+ editor.selection.setRng(rng);
+ };
+
+ var isFeatureEnabled = function (editor) {
+ return editor.settings.inline_boundaries !== false;
+ };
+
+ var setSelected = function (state, elm) {
+ if (state) {
+ elm.setAttribute('data-mce-selected', '1');
+ } else {
+ elm.removeAttribute('data-mce-selected', '1');
+ }
+ };
+
+ var renderCaretLocation = function (editor, caret, location) {
+ return BoundaryCaret.renderCaret(caret, location).map(function (pos) {
+ setCaretPosition(editor, pos);
+ return location;
+ });
+ };
+
+ var findLocation = function (editor, caret, forward) {
+ var rootNode = editor.getBody();
+ var from = CaretPosition.fromRangeStart(editor.selection.getRng());
+ var location = forward ? BoundaryLocation.nextLocation(rootNode, from) : BoundaryLocation.prevLocation(rootNode, from);
+ return location.bind(function (location) {
+ return renderCaretLocation(editor, caret, location);
+ });
+ };
+
+ var toggleInlines = function (dom, elms) {
+ var selectedInlines = dom.select('a[href][data-mce-selected],code[data-mce-selected]');
+ var targetInlines = Arr.filter(elms, InlineUtils.isInlineTarget);
+ Arr.each(Arr.difference(selectedInlines, targetInlines), Fun.curry(setSelected, false));
+ Arr.each(Arr.difference(targetInlines, selectedInlines), Fun.curry(setSelected, true));
+ };
+
+ var safeRemoveCaretContainer = function (editor, caret) {
+ if (editor.selection.isCollapsed() && editor.composing !== true && caret.get()) {
+ var pos = CaretPosition.fromRangeStart(editor.selection.getRng());
+ if (CaretPosition.isTextPosition(pos) && InlineUtils.isAtZwsp(pos) === false) {
+ setCaretPosition(editor, CaretContainerRemove.removeAndReposition(caret.get(), pos));
+ caret.set(null);
+ }
+ }
+ };
+
+ var renderInsideInlineCaret = function (editor, caret, elms) {
+ if (editor.selection.isCollapsed()) {
+ var inlines = Arr.filter(elms, InlineUtils.isInlineTarget);
+ Arr.each(inlines, function (inline) {
+ var pos = CaretPosition.fromRangeStart(editor.selection.getRng());
+ BoundaryLocation.readLocation(editor.getBody(), pos).bind(function (location) {
+ return renderCaretLocation(editor, caret, location);
+ });
+ });
+ }
+ };
+
+ var move = function (editor, caret, forward) {
+ return function () {
+ return isFeatureEnabled(editor) ? findLocation(editor, caret, forward).isSome() : false;
+ };
+ };
+
+ var setupSelectedState = function (editor) {
+ var caret = new Cell(null);
+
+ editor.on('NodeChange', function (e) {
+ if (isFeatureEnabled(editor)) {
+ toggleInlines(editor.dom, e.parents);
+ safeRemoveCaretContainer(editor, caret);
+ renderInsideInlineCaret(editor, caret, e.parents);
+ }
+ });
+
+ return caret;
+ };
+
+ return {
+ move: move,
+ setupSelectedState: setupSelectedState,
+ setCaretPosition: setCaretPosition
+ };
+ }
+);
+/**
+ * InlineBoundaryDelete.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.core.delete.InlineBoundaryDelete',
+ [
+ 'ephox.katamari.api.Fun',
+ 'ephox.katamari.api.Option',
+ 'ephox.katamari.api.Options',
+ 'ephox.sugar.api.node.Element',
+ 'tinymce.core.caret.CaretContainer',
+ 'tinymce.core.caret.CaretPosition',
+ 'tinymce.core.delete.DeleteElement',
+ 'tinymce.core.keyboard.BoundaryCaret',
+ 'tinymce.core.keyboard.BoundaryLocation',
+ 'tinymce.core.keyboard.BoundarySelection',
+ 'tinymce.core.keyboard.InlineUtils'
+ ],
+ function (Fun, Option, Options, Element, CaretContainer, CaretPosition, DeleteElement, BoundaryCaret, BoundaryLocation, BoundarySelection, InlineUtils) {
+ var rangeFromPositions = function (from, to) {
+ var range = document.createRange();
+
+ range.setStart(from.container(), from.offset());
+ range.setEnd(to.container(), to.offset());
+
+ return range;
+ };
+
+ var setCaretLocation = function (editor, caret) {
+ return function (location) {
+ return BoundaryCaret.renderCaret(caret, location).map(function (pos) {
+ BoundarySelection.setCaretPosition(editor, pos);
+ return true;
+ }).getOr(false);
+ };
+ };
+
+ var deleteFromTo = function (editor, caret, from, to) {
+ var rootNode = editor.getBody();
+
+ editor.undoManager.ignore(function () {
+ editor.selection.setRng(rangeFromPositions(from, to));
+ editor.execCommand('Delete');
+
+ BoundaryLocation.readLocation(rootNode, CaretPosition.fromRangeStart(editor.selection.getRng()))
+ .map(BoundaryLocation.inside)
+ .map(setCaretLocation(editor, caret));
+ });
+
+ editor.nodeChanged();
+ };
+
+ var backspaceDeleteCollapsed = function (editor, caret, forward, from) {
+ var rootNode = editor.getBody();
+ var fromLocation = BoundaryLocation.readLocation(rootNode, from);
+
+ return fromLocation.bind(function (location) {
+ if (forward) {
+ return location.fold(
+ Fun.constant(Option.some(BoundaryLocation.inside(location))), // Before
+ Option.none, // Start
+ Fun.constant(Option.some(BoundaryLocation.outside(location))), // End
+ Option.none // After
+ );
+ } else {
+ return location.fold(
+ Option.none, // Before
+ Fun.constant(Option.some(BoundaryLocation.outside(location))), // Start
+ Option.none, // End
+ Fun.constant(Option.some(BoundaryLocation.inside(location))) // After
+ );
+ }
+ })
+ .map(setCaretLocation(editor, caret))
+ .getOrThunk(function () {
+ var toPosition = InlineUtils.findCaretPosition(rootNode, forward, from);
+ var toLocation = toPosition.bind(function (pos) {
+ return BoundaryLocation.readLocation(rootNode, pos);
+ });
+
+ if (fromLocation.isSome() && toLocation.isSome()) {
+ InlineUtils.findInline(rootNode, from).bind(function (elm) {
+ return DeleteElement.deleteElement(editor, forward, Element.fromDom(elm));
+ });
+ return true;
+ } else {
+ return toLocation.map(function (_) {
+ toPosition.map(function (to) {
+ if (forward) {
+ deleteFromTo(editor, caret, from, to);
+ } else {
+ deleteFromTo(editor, caret, to, from);
+ }
+ });
+
+ return true;
+ }).getOr(false);
+ }
+ });
+ };
+
+ var backspaceDelete = function (editor, caret, forward) {
+ if (editor.selection.isCollapsed()) {
+ var from = CaretPosition.fromRangeStart(editor.selection.getRng());
+ return backspaceDeleteCollapsed(editor, caret, forward, from);
+ }
+
+ return false;
+ };
+
+ return {
+ backspaceDelete: backspaceDelete
+ };
+ }
+);
+/**
+ * Commands.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.core.delete.DeleteCommands',
+ [
+ 'tinymce.core.delete.BlockBoundaryDelete',
+ 'tinymce.core.delete.BlockRangeDelete',
+ 'tinymce.core.delete.CefDelete',
+ 'tinymce.core.delete.InlineBoundaryDelete'
+ ],
+ function (BlockBoundaryDelete, BlockRangeDelete, CefDelete, BoundaryDelete) {
+ var nativeCommand = function (editor, command) {
+ editor.getDoc().execCommand(command, false, null);
+ };
+
+ var paddEmptyBody = function (editor) {
+ var dom = editor.dom;
+
+ // Check if body is empty after the delete call if so then set the contents
+ // to an empty string and move the caret to any block produced by that operation
+ // this fixes the issue with root blocks not being properly produced after a delete call on IE
+ var body = editor.getBody();
+
+ if (dom.isEmpty(body)) {
+ editor.setContent('');
+
+ if (body.firstChild && dom.isBlock(body.firstChild)) {
+ editor.selection.setCursorLocation(body.firstChild, 0);
+ } else {
+ editor.selection.setCursorLocation(body, 0);
+ }
+ }
+ };
+
+ var deleteCommand = function (editor) {
+ if (CefDelete.backspaceDelete(editor, false)) {
+ return;
+ } else if (BoundaryDelete.backspaceDelete(editor, false)) {
+ return;
+ } else if (BlockBoundaryDelete.backspaceDelete(editor, false)) {
+ return;
+ } else if (BlockRangeDelete.backspaceDelete(editor, false)) {
+ return;
+ } else {
+ nativeCommand(editor, 'Delete');
+ paddEmptyBody(editor);
+ }
+ };
+
+ var forwardDeleteCommand = function (editor) {
+ if (CefDelete.backspaceDelete(editor, true)) {
+ return;
+ } else if (BoundaryDelete.backspaceDelete(editor, true)) {
+ return;
+ } else if (BlockBoundaryDelete.backspaceDelete(editor, true)) {
+ return;
+ } else if (BlockRangeDelete.backspaceDelete(editor, true)) {
+ return;
+ } else {
+ nativeCommand(editor, 'ForwardDelete');
+ }
+ };
+
+ return {
+ deleteCommand: deleteCommand,
+ forwardDeleteCommand: forwardDeleteCommand
+ };
+ }
+);
+/**
+ * RangeNormalizer.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.core.dom.RangeNormalizer',
+ [
+ 'tinymce.core.caret.CaretFinder',
+ 'tinymce.core.caret.CaretPosition',
+ 'tinymce.core.caret.CaretUtils',
+ 'tinymce.core.dom.NodeType'
+ ],
+ function (CaretFinder, CaretPosition, CaretUtils, NodeType) {
+ var isTextBlock = function (elm) {
+ return NodeType.isElement(elm) && /^(P|H[1-6]|DIV)$/.test(elm.nodeName);
+ };
+
+ var matchEndContainer = function (rng, predicate) {
+ return predicate(rng.endContainer);
+ };
+
+ var createRange = function (sc, so, ec, eo) {
+ var rng = document.createRange();
+ rng.setStart(sc, so);
+ rng.setEnd(ec, eo);
+ return rng;
+ };
+
+ // If you tripple click a paragraph in this case:
+ // <blockquote><p>a</p></blockquote><p>b</p>
+ // It would become this range in webkit:
+ // <blockquote><p>[a</p></blockquote><p>]b</p>
+ // We would want it to be:
+ // <blockquote><p>[a]</p></blockquote><p>b</p>
+ // Since it would otherwise produces spans out of thin air on insertContent for example.
+ var normalizeBlockSelection = function (rng) {
+ var startPos = CaretPosition.fromRangeStart(rng);
+ var endPos = CaretPosition.fromRangeEnd(rng);
+ var rootNode = rng.commonAncestorContainer;
+
+ if (rng.collapsed === false && matchEndContainer(rng, isTextBlock) && rng.endOffset === 0) {
+ return CaretFinder.fromPosition(false, rootNode, endPos)
+ .map(function (newEndPos) {
+ if (!CaretUtils.isInSameBlock(startPos, endPos, rootNode) && CaretUtils.isInSameBlock(startPos, newEndPos, rootNode)) {
+ return createRange(startPos.container(), startPos.offset(), newEndPos.container(), newEndPos.offset());
+ } else {
+ return rng;
+ }
+ }).getOr(rng);
+ } else {
+ return rng;
+ }
+ };
+
+ var normalize = function (rng) {
+ return normalizeBlockSelection(rng);
+ };
+
+ return {
+ normalize: normalize
+ };
+ }
+);
+/**
</ins><span class="cx" style="display: block; padding: 0 10px"> * InsertList.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -23891,176 +27985,177 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.InsertList
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/InsertList", [
- "tinymce/util/Tools",
- "tinymce/caret/CaretWalker",
- "tinymce/caret/CaretPosition"
-], function(Tools, CaretWalker, CaretPosition) {
- var isListFragment = function(fragment) {
- var firstChild = fragment.firstChild;
- var lastChild = fragment.lastChild;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.InsertList',
+ [
+ "tinymce.core.util.Tools",
+ "tinymce.core.caret.CaretWalker",
+ "tinymce.core.caret.CaretPosition"
+ ],
+ function (Tools, CaretWalker, CaretPosition) {
+ var isListFragment = function (fragment) {
+ var firstChild = fragment.firstChild;
+ var lastChild = fragment.lastChild;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Skip meta since it's likely <meta><ul>..</ul>
- if (firstChild && firstChild.name === 'meta') {
- firstChild = firstChild.next;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Skip meta since it's likely <meta><ul>..</ul>
+ if (firstChild && firstChild.name === 'meta') {
+ firstChild = firstChild.next;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Skip mce_marker since it's likely <ul>..</ul><span id="mce_marker"></span>
- if (lastChild && lastChild.attr('id') === 'mce_marker') {
- lastChild = lastChild.prev;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Skip mce_marker since it's likely <ul>..</ul><span id="mce_marker"></span>
+ if (lastChild && lastChild.attr('id') === 'mce_marker') {
+ lastChild = lastChild.prev;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!firstChild || firstChild !== lastChild) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!firstChild || firstChild !== lastChild) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return firstChild.name === 'ul' || firstChild.name === 'ol';
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return firstChild.name === 'ul' || firstChild.name === 'ol';
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var cleanupDomFragment = function (domFragment) {
- var firstChild = domFragment.firstChild;
- var lastChild = domFragment.lastChild;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var cleanupDomFragment = function (domFragment) {
+ var firstChild = domFragment.firstChild;
+ var lastChild = domFragment.lastChild;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // TODO: remove the meta tag from paste logic
- if (firstChild && firstChild.nodeName === 'META') {
- firstChild.parentNode.removeChild(firstChild);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // TODO: remove the meta tag from paste logic
+ if (firstChild && firstChild.nodeName === 'META') {
+ firstChild.parentNode.removeChild(firstChild);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (lastChild && lastChild.id === 'mce_marker') {
- lastChild.parentNode.removeChild(lastChild);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (lastChild && lastChild.id === 'mce_marker') {
+ lastChild.parentNode.removeChild(lastChild);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return domFragment;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return domFragment;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var toDomFragment = function(dom, serializer, fragment) {
- var html = serializer.serialize(fragment);
- var domFragment = dom.createFragment(html);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var toDomFragment = function (dom, serializer, fragment) {
+ var html = serializer.serialize(fragment);
+ var domFragment = dom.createFragment(html);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return cleanupDomFragment(domFragment);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return cleanupDomFragment(domFragment);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var listItems = function(elm) {
- return Tools.grep(elm.childNodes, function(child) {
- return child.nodeName === 'LI';
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var listItems = function (elm) {
+ return Tools.grep(elm.childNodes, function (child) {
+ return child.nodeName === 'LI';
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isEmpty = function (elm) {
- return !elm.firstChild;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isEmpty = function (elm) {
+ return !elm.firstChild;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var trimListItems = function(elms) {
- return elms.length > 0 && isEmpty(elms[elms.length - 1]) ? elms.slice(0, -1) : elms;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var trimListItems = function (elms) {
+ return elms.length > 0 && isEmpty(elms[elms.length - 1]) ? elms.slice(0, -1) : elms;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getParentLi = function(dom, node) {
- var parentBlock = dom.getParent(node, dom.isBlock);
- return parentBlock && parentBlock.nodeName === 'LI' ? parentBlock : null;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getParentLi = function (dom, node) {
+ var parentBlock = dom.getParent(node, dom.isBlock);
+ return parentBlock && parentBlock.nodeName === 'LI' ? parentBlock : null;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isParentBlockLi = function(dom, node) {
- return !!getParentLi(dom, node);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isParentBlockLi = function (dom, node) {
+ return !!getParentLi(dom, node);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getSplit = function(parentNode, rng) {
- var beforeRng = rng.cloneRange();
- var afterRng = rng.cloneRange();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getSplit = function (parentNode, rng) {
+ var beforeRng = rng.cloneRange();
+ var afterRng = rng.cloneRange();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- beforeRng.setStartBefore(parentNode);
- afterRng.setEndAfter(parentNode);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ beforeRng.setStartBefore(parentNode);
+ afterRng.setEndAfter(parentNode);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return [
- beforeRng.cloneContents(),
- afterRng.cloneContents()
- ];
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return [
+ beforeRng.cloneContents(),
+ afterRng.cloneContents()
+ ];
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var findFirstIn = function(node, rootNode) {
- var caretPos = CaretPosition.before(node);
- var caretWalker = new CaretWalker(rootNode);
- var newCaretPos = caretWalker.next(caretPos);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var findFirstIn = function (node, rootNode) {
+ var caretPos = CaretPosition.before(node);
+ var caretWalker = new CaretWalker(rootNode);
+ var newCaretPos = caretWalker.next(caretPos);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return newCaretPos ? newCaretPos.toRange() : null;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return newCaretPos ? newCaretPos.toRange() : null;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var findLastOf = function(node, rootNode) {
- var caretPos = CaretPosition.after(node);
- var caretWalker = new CaretWalker(rootNode);
- var newCaretPos = caretWalker.prev(caretPos);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var findLastOf = function (node, rootNode) {
+ var caretPos = CaretPosition.after(node);
+ var caretWalker = new CaretWalker(rootNode);
+ var newCaretPos = caretWalker.prev(caretPos);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return newCaretPos ? newCaretPos.toRange() : null;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return newCaretPos ? newCaretPos.toRange() : null;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var insertMiddle = function(target, elms, rootNode, rng) {
- var parts = getSplit(target, rng);
- var parentElm = target.parentNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var insertMiddle = function (target, elms, rootNode, rng) {
+ var parts = getSplit(target, rng);
+ var parentElm = target.parentNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parentElm.insertBefore(parts[0], target);
- Tools.each(elms, function(li) {
- parentElm.insertBefore(li, target);
- });
- parentElm.insertBefore(parts[1], target);
- parentElm.removeChild(target);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parentElm.insertBefore(parts[0], target);
+ Tools.each(elms, function (li) {
+ parentElm.insertBefore(li, target);
+ });
+ parentElm.insertBefore(parts[1], target);
+ parentElm.removeChild(target);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return findLastOf(elms[elms.length - 1], rootNode);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return findLastOf(elms[elms.length - 1], rootNode);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var insertBefore = function(target, elms, rootNode) {
- var parentElm = target.parentNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var insertBefore = function (target, elms, rootNode) {
+ var parentElm = target.parentNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(elms, function(elm) {
- parentElm.insertBefore(elm, target);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(elms, function (elm) {
+ parentElm.insertBefore(elm, target);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return findFirstIn(target, rootNode);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return findFirstIn(target, rootNode);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var insertAfter = function(target, elms, rootNode, dom) {
- dom.insertAfter(elms.reverse(), target);
- return findLastOf(elms[0], rootNode);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var insertAfter = function (target, elms, rootNode, dom) {
+ dom.insertAfter(elms.reverse(), target);
+ return findLastOf(elms[0], rootNode);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var insertAtCaret = function(serializer, dom, rng, fragment) {
- var domFragment = toDomFragment(dom, serializer, fragment);
- var liTarget = getParentLi(dom, rng.startContainer);
- var liElms = trimListItems(listItems(domFragment.firstChild));
- var BEGINNING = 1, END = 2;
- var rootNode = dom.getRoot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var insertAtCaret = function (serializer, dom, rng, fragment) {
+ var domFragment = toDomFragment(dom, serializer, fragment);
+ var liTarget = getParentLi(dom, rng.startContainer);
+ var liElms = trimListItems(listItems(domFragment.firstChild));
+ var BEGINNING = 1, END = 2;
+ var rootNode = dom.getRoot();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isAt = function(location) {
- var caretPos = CaretPosition.fromRangeStart(rng);
- var caretWalker = new CaretWalker(dom.getRoot());
- var newPos = location === BEGINNING ? caretWalker.prev(caretPos) : caretWalker.next(caretPos);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isAt = function (location) {
+ var caretPos = CaretPosition.fromRangeStart(rng);
+ var caretWalker = new CaretWalker(dom.getRoot());
+ var newPos = location === BEGINNING ? caretWalker.prev(caretPos) : caretWalker.next(caretPos);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return newPos ? getParentLi(dom, newPos.getNode()) !== liTarget : true;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return newPos ? getParentLi(dom, newPos.getNode()) !== liTarget : true;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isAt(BEGINNING)) {
- return insertBefore(liTarget, liElms, rootNode);
- } else if (isAt(END)) {
- return insertAfter(liTarget, liElms, rootNode, dom);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isAt(BEGINNING)) {
+ return insertBefore(liTarget, liElms, rootNode);
+ } else if (isAt(END)) {
+ return insertAfter(liTarget, liElms, rootNode, dom);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return insertMiddle(liTarget, liElms, rootNode, rng);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return insertMiddle(liTarget, liElms, rootNode, rng);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- isListFragment: isListFragment,
- insertAtCaret: insertAtCaret,
- isParentBlockLi: isParentBlockLi,
- trimListItems: trimListItems,
- listItems: listItems
- };
-});
-
-// Included from: js/tinymce/classes/InsertContent.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ isListFragment: isListFragment,
+ insertAtCaret: insertAtCaret,
+ isParentBlockLi: isParentBlockLi,
+ trimListItems: trimListItems,
+ listItems: listItems
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * InsertContent.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -24072,388 +28167,390 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.InsertContent
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/InsertContent", [
- "tinymce/Env",
- "tinymce/util/Tools",
- "tinymce/html/Serializer",
- "tinymce/caret/CaretWalker",
- "tinymce/caret/CaretPosition",
- "tinymce/dom/ElementUtils",
- "tinymce/dom/NodeType",
- "tinymce/InsertList"
-], function(Env, Tools, Serializer, CaretWalker, CaretPosition, ElementUtils, NodeType, InsertList) {
- var isTableCell = NodeType.matchNodeNames('td th');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.InsertContent',
+ [
+ 'tinymce.core.caret.CaretPosition',
+ 'tinymce.core.caret.CaretWalker',
+ 'tinymce.core.dom.ElementUtils',
+ 'tinymce.core.dom.NodeType',
+ 'tinymce.core.dom.RangeNormalizer',
+ 'tinymce.core.Env',
+ 'tinymce.core.html.Serializer',
+ 'tinymce.core.InsertList',
+ 'tinymce.core.util.Tools'
+ ],
+ function (CaretPosition, CaretWalker, ElementUtils, NodeType, RangeNormalizer, Env, Serializer, InsertList, Tools) {
+ var isTableCell = NodeType.matchNodeNames('td th');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var validInsertion = function (editor, value, parentNode) {
- // Should never insert content into bogus elements, since these can
- // be resize handles or similar
- if (parentNode.getAttribute('data-mce-bogus') === 'all') {
- parentNode.parentNode.insertBefore(editor.dom.createFragment(value), parentNode);
- } else {
- // Check if parent is empty or only has one BR element then set the innerHTML of that parent
- var node = parentNode.firstChild;
- var node2 = parentNode.lastChild;
- if (!node || (node === node2 && node.nodeName === 'BR')) {///
- editor.dom.setHTML(parentNode, value);
- } else {
- editor.selection.setContent(value);
- }
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var validInsertion = function (editor, value, parentNode) {
+ // Should never insert content into bogus elements, since these can
+ // be resize handles or similar
+ if (parentNode.getAttribute('data-mce-bogus') === 'all') {
+ parentNode.parentNode.insertBefore(editor.dom.createFragment(value), parentNode);
+ } else {
+ // Check if parent is empty or only has one BR element then set the innerHTML of that parent
+ var node = parentNode.firstChild;
+ var node2 = parentNode.lastChild;
+ if (!node || (node === node2 && node.nodeName === 'BR')) {///
+ editor.dom.setHTML(parentNode, value);
+ } else {
+ editor.selection.setContent(value);
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var insertHtmlAtCaret = function(editor, value, details) {
- var parser, serializer, parentNode, rootNode, fragment, args;
- var marker, rng, node, node2, bookmarkHtml, merge;
- var textInlineElements = editor.schema.getTextInlineElements();
- var selection = editor.selection, dom = editor.dom;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var insertHtmlAtCaret = function (editor, value, details) {
+ var parser, serializer, parentNode, rootNode, fragment, args;
+ var marker, rng, node, node2, bookmarkHtml, merge;
+ var textInlineElements = editor.schema.getTextInlineElements();
+ var selection = editor.selection, dom = editor.dom;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function trimOrPaddLeftRight(html) {
- var rng, container, offset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function trimOrPaddLeftRight(html) {
+ var rng, container, offset;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng = selection.getRng(true);
- container = rng.startContainer;
- offset = rng.startOffset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng = selection.getRng(true);
+ container = rng.startContainer;
+ offset = rng.startOffset;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hasSiblingText(siblingName) {
- return container[siblingName] && container[siblingName].nodeType == 3;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hasSiblingText(siblingName) {
+ return container[siblingName] && container[siblingName].nodeType == 3;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (container.nodeType == 3) {
- if (offset > 0) {
- html = html.replace(/^ /, ' ');
- } else if (!hasSiblingText('previousSibling')) {
- html = html.replace(/^ /, ' ');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (container.nodeType == 3) {
+ if (offset > 0) {
+ html = html.replace(/^ /, ' ');
+ } else if (!hasSiblingText('previousSibling')) {
+ html = html.replace(/^ /, ' ');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (offset < container.length) {
- html = html.replace(/ (<br>|)$/, ' ');
- } else if (!hasSiblingText('nextSibling')) {
- html = html.replace(/( | )(<br>|)$/, ' ');
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (offset < container.length) {
+ html = html.replace(/ (<br>|)$/, ' ');
+ } else if (!hasSiblingText('nextSibling')) {
+ html = html.replace(/( | )(<br>|)$/, ' ');
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return html;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return html;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Removes from a [b] c -> a c -> a c
- function trimNbspAfterDeleteAndPaddValue() {
- var rng, container, offset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Removes from a [b] c -> a c -> a c
+ function trimNbspAfterDeleteAndPaddValue() {
+ var rng, container, offset;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng = selection.getRng(true);
- container = rng.startContainer;
- offset = rng.startOffset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng = selection.getRng(true);
+ container = rng.startContainer;
+ offset = rng.startOffset;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (container.nodeType == 3 && rng.collapsed) {
- if (container.data[offset] === '\u00a0') {
- container.deleteData(offset, 1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (container.nodeType == 3 && rng.collapsed) {
+ if (container.data[offset] === '\u00a0') {
+ container.deleteData(offset, 1);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!/[\u00a0| ]$/.test(value)) {
- value += ' ';
- }
- } else if (container.data[offset - 1] === '\u00a0') {
- container.deleteData(offset - 1, 1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!/[\u00a0| ]$/.test(value)) {
+ value += ' ';
+ }
+ } else if (container.data[offset - 1] === '\u00a0') {
+ container.deleteData(offset - 1, 1);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!/[\u00a0| ]$/.test(value)) {
- value = ' ' + value;
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!/[\u00a0| ]$/.test(value)) {
+ value = ' ' + value;
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function reduceInlineTextElements() {
- if (merge) {
- var root = editor.getBody(), elementUtils = new ElementUtils(dom);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function reduceInlineTextElements() {
+ if (merge) {
+ var root = editor.getBody(), elementUtils = new ElementUtils(dom);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(dom.select('*[data-mce-fragment]'), function(node) {
- for (var testNode = node.parentNode; testNode && testNode != root; testNode = testNode.parentNode) {
- if (textInlineElements[node.nodeName.toLowerCase()] && elementUtils.compare(testNode, node)) {
- dom.remove(node, true);
- }
- }
- });
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(dom.select('*[data-mce-fragment]'), function (node) {
+ for (var testNode = node.parentNode; testNode && testNode != root; testNode = testNode.parentNode) {
+ if (textInlineElements[node.nodeName.toLowerCase()] && elementUtils.compare(testNode, node)) {
+ dom.remove(node, true);
+ }
+ }
+ });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function markFragmentElements(fragment) {
- var node = fragment;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function markFragmentElements(fragment) {
+ var node = fragment;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while ((node = node.walk())) {
- if (node.type === 1) {
- node.attr('data-mce-fragment', '1');
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while ((node = node.walk())) {
+ if (node.type === 1) {
+ node.attr('data-mce-fragment', '1');
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function umarkFragmentElements(elm) {
- Tools.each(elm.getElementsByTagName('*'), function(elm) {
- elm.removeAttribute('data-mce-fragment');
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function umarkFragmentElements(elm) {
+ Tools.each(elm.getElementsByTagName('*'), function (elm) {
+ elm.removeAttribute('data-mce-fragment');
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isPartOfFragment(node) {
- return !!node.getAttribute('data-mce-fragment');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isPartOfFragment(node) {
+ return !!node.getAttribute('data-mce-fragment');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function canHaveChildren(node) {
- return node && !editor.schema.getShortEndedElements()[node.nodeName];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function canHaveChildren(node) {
+ return node && !editor.schema.getShortEndedElements()[node.nodeName];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function moveSelectionToMarker(marker) {
- var parentEditableFalseElm, parentBlock, nextRng;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function moveSelectionToMarker(marker) {
+ var parentEditableFalseElm, parentBlock, nextRng;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getContentEditableFalseParent(node) {
- var root = editor.getBody();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getContentEditableFalseParent(node) {
+ var root = editor.getBody();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (; node && node !== root; node = node.parentNode) {
- if (editor.dom.getContentEditable(node) === 'false') {
- return node;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (; node && node !== root; node = node.parentNode) {
+ if (editor.dom.getContentEditable(node) === 'false') {
+ return node;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!marker) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!marker) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- selection.scrollIntoView(marker);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ selection.scrollIntoView(marker);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If marker is in cE=false then move selection to that element instead
- parentEditableFalseElm = getContentEditableFalseParent(marker);
- if (parentEditableFalseElm) {
- dom.remove(marker);
- selection.select(parentEditableFalseElm);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If marker is in cE=false then move selection to that element instead
+ parentEditableFalseElm = getContentEditableFalseParent(marker);
+ if (parentEditableFalseElm) {
+ dom.remove(marker);
+ selection.select(parentEditableFalseElm);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move selection before marker and remove it
- rng = dom.createRng();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move selection before marker and remove it
+ rng = dom.createRng();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If previous sibling is a text node set the selection to the end of that node
- node = marker.previousSibling;
- if (node && node.nodeType == 3) {
- rng.setStart(node, node.nodeValue.length);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If previous sibling is a text node set the selection to the end of that node
+ node = marker.previousSibling;
+ if (node && node.nodeType == 3) {
+ rng.setStart(node, node.nodeValue.length);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // TODO: Why can't we normalize on IE
- if (!Env.ie) {
- node2 = marker.nextSibling;
- if (node2 && node2.nodeType == 3) {
- node.appendData(node2.data);
- node2.parentNode.removeChild(node2);
- }
- }
- } else {
- // If the previous sibling isn't a text node or doesn't exist set the selection before the marker node
- rng.setStartBefore(marker);
- rng.setEndBefore(marker);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // TODO: Why can't we normalize on IE
+ if (!Env.ie) {
+ node2 = marker.nextSibling;
+ if (node2 && node2.nodeType == 3) {
+ node.appendData(node2.data);
+ node2.parentNode.removeChild(node2);
+ }
+ }
+ } else {
+ // If the previous sibling isn't a text node or doesn't exist set the selection before the marker node
+ rng.setStartBefore(marker);
+ rng.setEndBefore(marker);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function findNextCaretRng(rng) {
- var caretPos = CaretPosition.fromRangeStart(rng);
- var caretWalker = new CaretWalker(editor.getBody());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function findNextCaretRng(rng) {
+ var caretPos = CaretPosition.fromRangeStart(rng);
+ var caretWalker = new CaretWalker(editor.getBody());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- caretPos = caretWalker.next(caretPos);
- if (caretPos) {
- return caretPos.toRange();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ caretPos = caretWalker.next(caretPos);
+ if (caretPos) {
+ return caretPos.toRange();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove the marker node and set the new range
- parentBlock = dom.getParent(marker, dom.isBlock);
- dom.remove(marker);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove the marker node and set the new range
+ parentBlock = dom.getParent(marker, dom.isBlock);
+ dom.remove(marker);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (parentBlock && dom.isEmpty(parentBlock)) {
- editor.$(parentBlock).empty();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parentBlock && dom.isEmpty(parentBlock)) {
+ editor.$(parentBlock).empty();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng.setStart(parentBlock, 0);
- rng.setEnd(parentBlock, 0);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng.setStart(parentBlock, 0);
+ rng.setEnd(parentBlock, 0);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isTableCell(parentBlock) && !isPartOfFragment(parentBlock) && (nextRng = findNextCaretRng(rng))) {
- rng = nextRng;
- dom.remove(parentBlock);
- } else {
- dom.add(parentBlock, dom.create('br', {'data-mce-bogus': '1'}));
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isTableCell(parentBlock) && !isPartOfFragment(parentBlock) && (nextRng = findNextCaretRng(rng))) {
+ rng = nextRng;
+ dom.remove(parentBlock);
+ } else {
+ dom.add(parentBlock, dom.create('br', { 'data-mce-bogus': '1' }));
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- selection.setRng(rng);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ selection.setRng(rng);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check for whitespace before/after value
- if (/^ | $/.test(value)) {
- value = trimOrPaddLeftRight(value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check for whitespace before/after value
+ if (/^ | $/.test(value)) {
+ value = trimOrPaddLeftRight(value);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup parser and serializer
- parser = editor.parser;
- merge = details.merge;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup parser and serializer
+ parser = editor.parser;
+ merge = details.merge;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- serializer = new Serializer({
- validate: editor.settings.validate
- }, editor.schema);
- bookmarkHtml = '<span id="mce_marker" data-mce-type="bookmark">​</span>';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ serializer = new Serializer({
+ validate: editor.settings.validate
+ }, editor.schema);
+ bookmarkHtml = '<span id="mce_marker" data-mce-type="bookmark">​</span>';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Run beforeSetContent handlers on the HTML to be inserted
- args = {content: value, format: 'html', selection: true};
- editor.fire('BeforeSetContent', args);
- value = args.content;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Run beforeSetContent handlers on the HTML to be inserted
+ args = { content: value, format: 'html', selection: true };
+ editor.fire('BeforeSetContent', args);
+ value = args.content;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add caret at end of contents if it's missing
- if (value.indexOf('{$caret}') == -1) {
- value += '{$caret}';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add caret at end of contents if it's missing
+ if (value.indexOf('{$caret}') == -1) {
+ value += '{$caret}';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Replace the caret marker with a span bookmark element
- value = value.replace(/\{\$caret\}/, bookmarkHtml);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Replace the caret marker with a span bookmark element
+ value = value.replace(/\{\$caret\}/, bookmarkHtml);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If selection is at <body>|<p></p> then move it into <body><p>|</p>
- rng = selection.getRng();
- var caretElement = rng.startContainer || (rng.parentElement ? rng.parentElement() : null);
- var body = editor.getBody();
- if (caretElement === body && selection.isCollapsed()) {
- if (dom.isBlock(body.firstChild) && canHaveChildren(body.firstChild) && dom.isEmpty(body.firstChild)) {
- rng = dom.createRng();
- rng.setStart(body.firstChild, 0);
- rng.setEnd(body.firstChild, 0);
- selection.setRng(rng);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If selection is at <body>|<p></p> then move it into <body><p>|</p>
+ rng = selection.getRng();
+ var caretElement = rng.startContainer || (rng.parentElement ? rng.parentElement() : null);
+ var body = editor.getBody();
+ if (caretElement === body && selection.isCollapsed()) {
+ if (dom.isBlock(body.firstChild) && canHaveChildren(body.firstChild) && dom.isEmpty(body.firstChild)) {
+ rng = dom.createRng();
+ rng.setStart(body.firstChild, 0);
+ rng.setEnd(body.firstChild, 0);
+ selection.setRng(rng);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Insert node maker where we will insert the new HTML and get it's parent
- if (!selection.isCollapsed()) {
- // Fix for #2595 seems that delete removes one extra character on
- // WebKit for some odd reason if you double click select a word
- editor.selection.setRng(editor.selection.getRng());
- editor.getDoc().execCommand('Delete', false, null);
- trimNbspAfterDeleteAndPaddValue();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Insert node maker where we will insert the new HTML and get it's parent
+ if (!selection.isCollapsed()) {
+ // Fix for #2595 seems that delete removes one extra character on
+ // WebKit for some odd reason if you double click select a word
+ editor.selection.setRng(RangeNormalizer.normalize(editor.selection.getRng()));
+ editor.getDoc().execCommand('Delete', false, null);
+ trimNbspAfterDeleteAndPaddValue();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parentNode = selection.getNode();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parentNode = selection.getNode();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Parse the fragment within the context of the parent node
- var parserArgs = {context: parentNode.nodeName.toLowerCase(), data: details.data};
- fragment = parser.parse(value, parserArgs);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Parse the fragment within the context of the parent node
+ var parserArgs = { context: parentNode.nodeName.toLowerCase(), data: details.data };
+ fragment = parser.parse(value, parserArgs);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Custom handling of lists
- if (details.paste === true && InsertList.isListFragment(fragment) && InsertList.isParentBlockLi(dom, parentNode)) {
- rng = InsertList.insertAtCaret(serializer, dom, editor.selection.getRng(true), fragment);
- editor.selection.setRng(rng);
- editor.fire('SetContent', args);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Custom handling of lists
+ if (details.paste === true && InsertList.isListFragment(fragment) && InsertList.isParentBlockLi(dom, parentNode)) {
+ rng = InsertList.insertAtCaret(serializer, dom, editor.selection.getRng(true), fragment);
+ editor.selection.setRng(rng);
+ editor.fire('SetContent', args);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- markFragmentElements(fragment);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ markFragmentElements(fragment);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move the caret to a more suitable location
- node = fragment.lastChild;
- if (node.attr('id') == 'mce_marker') {
- marker = node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move the caret to a more suitable location
+ node = fragment.lastChild;
+ if (node.attr('id') == 'mce_marker') {
+ marker = node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (node = node.prev; node; node = node.walk(true)) {
- if (node.type == 3 || !dom.isBlock(node.name)) {
- if (editor.schema.isValidChild(node.parent.name, 'span')) {
- node.parent.insert(marker, node, node.name === 'br');
- }
- break;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (node = node.prev; node; node = node.walk(true)) {
+ if (node.type == 3 || !dom.isBlock(node.name)) {
+ if (editor.schema.isValidChild(node.parent.name, 'span')) {
+ node.parent.insert(marker, node, node.name === 'br');
+ }
+ break;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor._selectionOverrides.showBlockCaretContainer(parentNode);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor._selectionOverrides.showBlockCaretContainer(parentNode);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If parser says valid we can insert the contents into that parent
- if (!parserArgs.invalid) {
- value = serializer.serialize(fragment);
- validInsertion(editor, value, parentNode);
- } else {
- // If the fragment was invalid within that context then we need
- // to parse and process the parent it's inserted into
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If parser says valid we can insert the contents into that parent
+ if (!parserArgs.invalid) {
+ value = serializer.serialize(fragment);
+ validInsertion(editor, value, parentNode);
+ } else {
+ // If the fragment was invalid within that context then we need
+ // to parse and process the parent it's inserted into
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Insert bookmark node and get the parent
- selection.setContent(bookmarkHtml);
- parentNode = selection.getNode();
- rootNode = editor.getBody();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Insert bookmark node and get the parent
+ selection.setContent(bookmarkHtml);
+ parentNode = selection.getNode();
+ rootNode = editor.getBody();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Opera will return the document node when selection is in root
- if (parentNode.nodeType == 9) {
- parentNode = node = rootNode;
- } else {
- node = parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Opera will return the document node when selection is in root
+ if (parentNode.nodeType == 9) {
+ parentNode = node = rootNode;
+ } else {
+ node = parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Find the ancestor just before the root element
- while (node !== rootNode) {
- parentNode = node;
- node = node.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find the ancestor just before the root element
+ while (node !== rootNode) {
+ parentNode = node;
+ node = node.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Get the outer/inner HTML depending on if we are in the root and parser and serialize that
- value = parentNode == rootNode ? rootNode.innerHTML : dom.getOuterHTML(parentNode);
- value = serializer.serialize(
- parser.parse(
- // Need to replace by using a function since $ in the contents would otherwise be a problem
- value.replace(/<span (id="mce_marker"|id=mce_marker).+?<\/span>/i, function() {
- return serializer.serialize(fragment);
- })
- )
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get the outer/inner HTML depending on if we are in the root and parser and serialize that
+ value = parentNode == rootNode ? rootNode.innerHTML : dom.getOuterHTML(parentNode);
+ value = serializer.serialize(
+ parser.parse(
+ // Need to replace by using a function since $ in the contents would otherwise be a problem
+ value.replace(/<span (id="mce_marker"|id=mce_marker).+?<\/span>/i, function () {
+ return serializer.serialize(fragment);
+ })
+ )
+ );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set the inner/outer HTML depending on if we are in the root or not
- if (parentNode == rootNode) {
- dom.setHTML(rootNode, value);
- } else {
- dom.setOuterHTML(parentNode, value);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set the inner/outer HTML depending on if we are in the root or not
+ if (parentNode == rootNode) {
+ dom.setHTML(rootNode, value);
+ } else {
+ dom.setOuterHTML(parentNode, value);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- reduceInlineTextElements();
- moveSelectionToMarker(dom.get('mce_marker'));
- umarkFragmentElements(editor.getBody());
- editor.fire('SetContent', args);
- editor.addVisual();
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ reduceInlineTextElements();
+ moveSelectionToMarker(dom.get('mce_marker'));
+ umarkFragmentElements(editor.getBody());
+ editor.fire('SetContent', args);
+ editor.addVisual();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var processValue = function (value) {
- var details;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var processValue = function (value) {
+ var details;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof value !== 'string') {
- details = Tools.extend({
- paste: value.paste,
- data: {
- paste: value.paste
- }
- }, value);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof value !== 'string') {
+ details = Tools.extend({
+ paste: value.paste,
+ data: {
+ paste: value.paste
+ }
+ }, value);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- content: value.content,
- details: details
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ content: value.content,
+ details: details
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- content: value,
- details: {}
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ content: value,
+ details: {}
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var insertAtCaret = function (editor, value) {
- var result = processValue(value);
- insertHtmlAtCaret(editor, result.content, result.details);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var insertAtCaret = function (editor, value) {
+ var result = processValue(value);
+ insertHtmlAtCaret(editor, result.content, result.details);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- insertAtCaret: insertAtCaret
- };
-});
-
-// Included from: js/tinymce/classes/EditorCommands.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ insertAtCaret: insertAtCaret
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * EditorCommands.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -24465,756 +28562,748 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.EditorCommands
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/EditorCommands", [
- "tinymce/Env",
- "tinymce/util/Tools",
- "tinymce/dom/RangeUtils",
- "tinymce/dom/TreeWalker",
- "tinymce/InsertContent",
- "tinymce/dom/NodeType"
-], function(Env, Tools, RangeUtils, TreeWalker, InsertContent, NodeType) {
- // Added for compression purposes
- var each = Tools.each, extend = Tools.extend;
- var map = Tools.map, inArray = Tools.inArray, explode = Tools.explode;
- var isOldIE = Env.ie && Env.ie < 11;
- var TRUE = true, FALSE = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.EditorCommands',
+ [
+ 'tinymce.core.delete.DeleteCommands',
+ 'tinymce.core.dom.NodeType',
+ 'tinymce.core.dom.RangeUtils',
+ 'tinymce.core.dom.TreeWalker',
+ 'tinymce.core.Env',
+ 'tinymce.core.InsertContent',
+ 'tinymce.core.util.Tools'
+ ],
+ function (DeleteCommands, NodeType, RangeUtils, TreeWalker, Env, InsertContent, Tools) {
+ // Added for compression purposes
+ var each = Tools.each, extend = Tools.extend;
+ var map = Tools.map, inArray = Tools.inArray, explode = Tools.explode;
+ var isOldIE = Env.ie && Env.ie < 11;
+ var TRUE = true, FALSE = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function(editor) {
- var dom, selection, formatter,
- commands = {state: {}, exec: {}, value: {}},
- settings = editor.settings,
- bookmark;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function (editor) {
+ var dom, selection, formatter,
+ commands = { state: {}, exec: {}, value: {} },
+ settings = editor.settings,
+ bookmark;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('PreInit', function() {
- dom = editor.dom;
- selection = editor.selection;
- settings = editor.settings;
- formatter = editor.formatter;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('PreInit', function () {
+ dom = editor.dom;
+ selection = editor.selection;
+ settings = editor.settings;
+ formatter = editor.formatter;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Executes the specified command.
- *
- * @method execCommand
- * @param {String} command Command to execute.
- * @param {Boolean} ui Optional user interface state.
- * @param {Object} value Optional value for command.
- * @param {Object} args Optional extra arguments to the execCommand.
- * @return {Boolean} true/false if the command was found or not.
- */
- function execCommand(command, ui, value, args) {
- var func, customCommand, state = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Executes the specified command.
+ *
+ * @method execCommand
+ * @param {String} command Command to execute.
+ * @param {Boolean} ui Optional user interface state.
+ * @param {Object} value Optional value for command.
+ * @param {Object} args Optional extra arguments to the execCommand.
+ * @return {Boolean} true/false if the command was found or not.
+ */
+ function execCommand(command, ui, value, args) {
+ var func, customCommand, state = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint)$/.test(command) && (!args || !args.skip_focus)) {
- editor.focus();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint)$/.test(command) && (!args || !args.skip_focus)) {
+ editor.focus();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args = editor.fire('BeforeExecCommand', {command: command, ui: ui, value: value});
- if (args.isDefaultPrevented()) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args = editor.fire('BeforeExecCommand', { command: command, ui: ui, value: value });
+ if (args.isDefaultPrevented()) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- customCommand = command.toLowerCase();
- if ((func = commands.exec[customCommand])) {
- func(customCommand, ui, value);
- editor.fire('ExecCommand', {command: command, ui: ui, value: value});
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ customCommand = command.toLowerCase();
+ if ((func = commands.exec[customCommand])) {
+ func(customCommand, ui, value);
+ editor.fire('ExecCommand', { command: command, ui: ui, value: value });
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Plugin commands
- each(editor.plugins, function(p) {
- if (p.execCommand && p.execCommand(command, ui, value)) {
- editor.fire('ExecCommand', {command: command, ui: ui, value: value});
- state = true;
- return false;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Plugin commands
+ each(editor.plugins, function (p) {
+ if (p.execCommand && p.execCommand(command, ui, value)) {
+ editor.fire('ExecCommand', { command: command, ui: ui, value: value });
+ state = true;
+ return false;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (state) {
- return state;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (state) {
+ return state;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Theme commands
- if (editor.theme && editor.theme.execCommand && editor.theme.execCommand(command, ui, value)) {
- editor.fire('ExecCommand', {command: command, ui: ui, value: value});
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Theme commands
+ if (editor.theme && editor.theme.execCommand && editor.theme.execCommand(command, ui, value)) {
+ editor.fire('ExecCommand', { command: command, ui: ui, value: value });
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Browser commands
- try {
- state = editor.getDoc().execCommand(command, ui, value);
- } catch (ex) {
- // Ignore old IE errors
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Browser commands
+ try {
+ state = editor.getDoc().execCommand(command, ui, value);
+ } catch (ex) {
+ // Ignore old IE errors
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (state) {
- editor.fire('ExecCommand', {command: command, ui: ui, value: value});
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (state) {
+ editor.fire('ExecCommand', { command: command, ui: ui, value: value });
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Queries the current state for a command for example if the current selection is "bold".
- *
- * @method queryCommandState
- * @param {String} command Command to check the state of.
- * @return {Boolean/Number} true/false if the selected contents is bold or not, -1 if it's not found.
- */
- function queryCommandState(command) {
- var func;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Queries the current state for a command for example if the current selection is "bold".
+ *
+ * @method queryCommandState
+ * @param {String} command Command to check the state of.
+ * @return {Boolean/Number} true/false if the selected contents is bold or not, -1 if it's not found.
+ */
+ function queryCommandState(command) {
+ var func;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Is hidden then return undefined
- if (editor.quirks.isHidden()) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Is hidden then return undefined
+ if (editor.quirks.isHidden()) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- command = command.toLowerCase();
- if ((func = commands.state[command])) {
- return func(command);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ command = command.toLowerCase();
+ if ((func = commands.state[command])) {
+ return func(command);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Browser commands
- try {
- return editor.getDoc().queryCommandState(command);
- } catch (ex) {
- // Fails sometimes see bug: 1896577
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Browser commands
+ try {
+ return editor.getDoc().queryCommandState(command);
+ } catch (ex) {
+ // Fails sometimes see bug: 1896577
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Queries the command value for example the current fontsize.
- *
- * @method queryCommandValue
- * @param {String} command Command to check the value of.
- * @return {Object} Command value of false if it's not found.
- */
- function queryCommandValue(command) {
- var func;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Queries the command value for example the current fontsize.
+ *
+ * @method queryCommandValue
+ * @param {String} command Command to check the value of.
+ * @return {Object} Command value of false if it's not found.
+ */
+ function queryCommandValue(command) {
+ var func;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Is hidden then return undefined
- if (editor.quirks.isHidden()) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Is hidden then return undefined
+ if (editor.quirks.isHidden()) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- command = command.toLowerCase();
- if ((func = commands.value[command])) {
- return func(command);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ command = command.toLowerCase();
+ if ((func = commands.value[command])) {
+ return func(command);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Browser commands
- try {
- return editor.getDoc().queryCommandValue(command);
- } catch (ex) {
- // Fails sometimes see bug: 1896577
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Browser commands
+ try {
+ return editor.getDoc().queryCommandValue(command);
+ } catch (ex) {
+ // Fails sometimes see bug: 1896577
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds commands to the command collection.
- *
- * @method addCommands
- * @param {Object} command_list Name/value collection with commands to add, the names can also be comma separated.
- * @param {String} type Optional type to add, defaults to exec. Can be value or state as well.
- */
- function addCommands(command_list, type) {
- type = type || 'exec';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds commands to the command collection.
+ *
+ * @method addCommands
+ * @param {Object} commandList Name/value collection with commands to add, the names can also be comma separated.
+ * @param {String} type Optional type to add, defaults to exec. Can be value or state as well.
+ */
+ function addCommands(commandList, type) {
+ type = type || 'exec';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(command_list, function(callback, command) {
- each(command.toLowerCase().split(','), function(command) {
- commands[type][command] = callback;
- });
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(commandList, function (callback, command) {
+ each(command.toLowerCase().split(','), function (command) {
+ commands[type][command] = callback;
+ });
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function addCommand(command, callback, scope) {
- command = command.toLowerCase();
- commands.exec[command] = function(command, ui, value, args) {
- return callback.call(scope || editor, ui, value, args);
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function addCommand(command, callback, scope) {
+ command = command.toLowerCase();
+ commands.exec[command] = function (command, ui, value, args) {
+ return callback.call(scope || editor, ui, value, args);
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the command is supported or not.
- *
- * @method queryCommandSupported
- * @param {String} command Command that we check support for.
- * @return {Boolean} true/false if the command is supported or not.
- */
- function queryCommandSupported(command) {
- command = command.toLowerCase();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the command is supported or not.
+ *
+ * @method queryCommandSupported
+ * @param {String} command Command that we check support for.
+ * @return {Boolean} true/false if the command is supported or not.
+ */
+ function queryCommandSupported(command) {
+ command = command.toLowerCase();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (commands.exec[command]) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (commands.exec[command]) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Browser commands
- try {
- return editor.getDoc().queryCommandSupported(command);
- } catch (ex) {
- // Fails sometimes see bug: 1896577
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Browser commands
+ try {
+ return editor.getDoc().queryCommandSupported(command);
+ } catch (ex) {
+ // Fails sometimes see bug: 1896577
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function addQueryStateHandler(command, callback, scope) {
- command = command.toLowerCase();
- commands.state[command] = function() {
- return callback.call(scope || editor);
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function addQueryStateHandler(command, callback, scope) {
+ command = command.toLowerCase();
+ commands.state[command] = function () {
+ return callback.call(scope || editor);
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function addQueryValueHandler(command, callback, scope) {
- command = command.toLowerCase();
- commands.value[command] = function() {
- return callback.call(scope || editor);
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function addQueryValueHandler(command, callback, scope) {
+ command = command.toLowerCase();
+ commands.value[command] = function () {
+ return callback.call(scope || editor);
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hasCustomCommand(command) {
- command = command.toLowerCase();
- return !!commands.exec[command];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hasCustomCommand(command) {
+ command = command.toLowerCase();
+ return !!commands.exec[command];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Expose public methods
- extend(this, {
- execCommand: execCommand,
- queryCommandState: queryCommandState,
- queryCommandValue: queryCommandValue,
- queryCommandSupported: queryCommandSupported,
- addCommands: addCommands,
- addCommand: addCommand,
- addQueryStateHandler: addQueryStateHandler,
- addQueryValueHandler: addQueryValueHandler,
- hasCustomCommand: hasCustomCommand
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Expose public methods
+ extend(this, {
+ execCommand: execCommand,
+ queryCommandState: queryCommandState,
+ queryCommandValue: queryCommandValue,
+ queryCommandSupported: queryCommandSupported,
+ addCommands: addCommands,
+ addCommand: addCommand,
+ addQueryStateHandler: addQueryStateHandler,
+ addQueryValueHandler: addQueryValueHandler,
+ hasCustomCommand: hasCustomCommand
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Private methods
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Private methods
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function execNativeCommand(command, ui, value) {
- if (ui === undefined) {
- ui = FALSE;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function execNativeCommand(command, ui, value) {
+ if (ui === undefined) {
+ ui = FALSE;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value === undefined) {
- value = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value === undefined) {
+ value = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return editor.getDoc().execCommand(command, ui, value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return editor.getDoc().execCommand(command, ui, value);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isFormatMatch(name) {
- return formatter.match(name);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isFormatMatch(name) {
+ return formatter.match(name);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function toggleFormat(name, value) {
- formatter.toggle(name, value ? {value: value} : undefined);
- editor.nodeChanged();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function toggleFormat(name, value) {
+ formatter.toggle(name, value ? { value: value } : undefined);
+ editor.nodeChanged();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function storeSelection(type) {
- bookmark = selection.getBookmark(type);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function storeSelection(type) {
+ bookmark = selection.getBookmark(type);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function restoreSelection() {
- selection.moveToBookmark(bookmark);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function restoreSelection() {
+ selection.moveToBookmark(bookmark);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add execCommand overrides
- addCommands({
- // Ignore these, added for compatibility
- 'mceResetDesignMode,mceBeginUndoLevel': function() {},
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add execCommand overrides
+ addCommands({
+ // Ignore these, added for compatibility
+ 'mceResetDesignMode,mceBeginUndoLevel': function () { },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add undo manager logic
- 'mceEndUndoLevel,mceAddUndoLevel': function() {
- editor.undoManager.add();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add undo manager logic
+ 'mceEndUndoLevel,mceAddUndoLevel': function () {
+ editor.undoManager.add();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'Cut,Copy,Paste': function(command) {
- var doc = editor.getDoc(), failed;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'Cut,Copy,Paste': function (command) {
+ var doc = editor.getDoc(), failed;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Try executing the native command
- try {
- execNativeCommand(command);
- } catch (ex) {
- // Command failed
- failed = TRUE;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Try executing the native command
+ try {
+ execNativeCommand(command);
+ } catch (ex) {
+ // Command failed
+ failed = TRUE;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Chrome reports the paste command as supported however older IE:s will return false for cut/paste
- if (command === 'paste' && !doc.queryCommandEnabled(command)) {
- failed = true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Chrome reports the paste command as supported however older IE:s will return false for cut/paste
+ if (command === 'paste' && !doc.queryCommandEnabled(command)) {
+ failed = true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Present alert message about clipboard access not being available
- if (failed || !doc.queryCommandSupported(command)) {
- var msg = editor.translate(
- "Your browser doesn't support direct access to the clipboard. " +
- "Please use the Ctrl+X/C/V keyboard shortcuts instead."
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Present alert message about clipboard access not being available
+ if (failed || !doc.queryCommandSupported(command)) {
+ var msg = editor.translate(
+ "Your browser doesn't support direct access to the clipboard. " +
+ "Please use the Ctrl+X/C/V keyboard shortcuts instead."
+ );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (Env.mac) {
- msg = msg.replace(/Ctrl\+/g, '\u2318+');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (Env.mac) {
+ msg = msg.replace(/Ctrl\+/g, '\u2318+');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.notificationManager.open({text: msg, type: 'error'});
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.notificationManager.open({ text: msg, type: 'error' });
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Override unlink command
- unlink: function() {
- if (selection.isCollapsed()) {
- var elm = editor.dom.getParent(editor.selection.getStart(), 'a');
- if (elm) {
- editor.dom.remove(elm, true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Override unlink command
+ unlink: function () {
+ if (selection.isCollapsed()) {
+ var elm = editor.dom.getParent(editor.selection.getStart(), 'a');
+ if (elm) {
+ editor.dom.remove(elm, true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- formatter.remove("link");
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ formatter.remove("link");
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Override justify commands to use the text formatter engine
- 'JustifyLeft,JustifyCenter,JustifyRight,JustifyFull,JustifyNone': function(command) {
- var align = command.substring(7);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Override justify commands to use the text formatter engine
+ 'JustifyLeft,JustifyCenter,JustifyRight,JustifyFull,JustifyNone': function (command) {
+ var align = command.substring(7);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (align == 'full') {
- align = 'justify';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (align == 'full') {
+ align = 'justify';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove all other alignments first
- each('left,center,right,justify'.split(','), function(name) {
- if (align != name) {
- formatter.remove('align' + name);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove all other alignments first
+ each('left,center,right,justify'.split(','), function (name) {
+ if (align != name) {
+ formatter.remove('align' + name);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (align != 'none') {
- toggleFormat('align' + align);
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (align != 'none') {
+ toggleFormat('align' + align);
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Override list commands to fix WebKit bug
- 'InsertUnorderedList,InsertOrderedList': function(command) {
- var listElm, listParent;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Override list commands to fix WebKit bug
+ 'InsertUnorderedList,InsertOrderedList': function (command) {
+ var listElm, listParent;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- execNativeCommand(command);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ execNativeCommand(command);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // WebKit produces lists within block elements so we need to split them
- // we will replace the native list creation logic to custom logic later on
- // TODO: Remove this when the list creation logic is removed
- listElm = dom.getParent(selection.getNode(), 'ol,ul');
- if (listElm) {
- listParent = listElm.parentNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // WebKit produces lists within block elements so we need to split them
+ // we will replace the native list creation logic to custom logic later on
+ // TODO: Remove this when the list creation logic is removed
+ listElm = dom.getParent(selection.getNode(), 'ol,ul');
+ if (listElm) {
+ listParent = listElm.parentNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If list is within a text block then split that block
- if (/^(H[1-6]|P|ADDRESS|PRE)$/.test(listParent.nodeName)) {
- storeSelection();
- dom.split(listParent, listElm);
- restoreSelection();
- }
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If list is within a text block then split that block
+ if (/^(H[1-6]|P|ADDRESS|PRE)$/.test(listParent.nodeName)) {
+ storeSelection();
+ dom.split(listParent, listElm);
+ restoreSelection();
+ }
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Override commands to use the text formatter engine
- 'Bold,Italic,Underline,Strikethrough,Superscript,Subscript': function(command) {
- toggleFormat(command);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Override commands to use the text formatter engine
+ 'Bold,Italic,Underline,Strikethrough,Superscript,Subscript': function (command) {
+ toggleFormat(command);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Override commands to use the text formatter engine
- 'ForeColor,HiliteColor,FontName': function(command, ui, value) {
- toggleFormat(command, value);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Override commands to use the text formatter engine
+ 'ForeColor,HiliteColor,FontName': function (command, ui, value) {
+ toggleFormat(command, value);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- FontSize: function(command, ui, value) {
- var fontClasses, fontSizes;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ FontSize: function (command, ui, value) {
+ var fontClasses, fontSizes;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Convert font size 1-7 to styles
- if (value >= 1 && value <= 7) {
- fontSizes = explode(settings.font_size_style_values);
- fontClasses = explode(settings.font_size_classes);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Convert font size 1-7 to styles
+ if (value >= 1 && value <= 7) {
+ fontSizes = explode(settings.font_size_style_values);
+ fontClasses = explode(settings.font_size_classes);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (fontClasses) {
- value = fontClasses[value - 1] || value;
- } else {
- value = fontSizes[value - 1] || value;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (fontClasses) {
+ value = fontClasses[value - 1] || value;
+ } else {
+ value = fontSizes[value - 1] || value;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- toggleFormat(command, value);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ toggleFormat(command, value);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- RemoveFormat: function(command) {
- formatter.remove(command);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ RemoveFormat: function (command) {
+ formatter.remove(command);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- mceBlockQuote: function() {
- toggleFormat('blockquote');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ mceBlockQuote: function () {
+ toggleFormat('blockquote');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- FormatBlock: function(command, ui, value) {
- return toggleFormat(value || 'p');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ FormatBlock: function (command, ui, value) {
+ return toggleFormat(value || 'p');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- mceCleanup: function() {
- var bookmark = selection.getBookmark();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ mceCleanup: function () {
+ var bookmark = selection.getBookmark();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.setContent(editor.getContent({cleanup: TRUE}), {cleanup: TRUE});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.setContent(editor.getContent({ cleanup: TRUE }), { cleanup: TRUE });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- selection.moveToBookmark(bookmark);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ selection.moveToBookmark(bookmark);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- mceRemoveNode: function(command, ui, value) {
- var node = value || selection.getNode();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ mceRemoveNode: function (command, ui, value) {
+ var node = value || selection.getNode();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Make sure that the body node isn't removed
- if (node != editor.getBody()) {
- storeSelection();
- editor.dom.remove(node, TRUE);
- restoreSelection();
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Make sure that the body node isn't removed
+ if (node != editor.getBody()) {
+ storeSelection();
+ editor.dom.remove(node, TRUE);
+ restoreSelection();
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- mceSelectNodeDepth: function(command, ui, value) {
- var counter = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ mceSelectNodeDepth: function (command, ui, value) {
+ var counter = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.getParent(selection.getNode(), function(node) {
- if (node.nodeType == 1 && counter++ == value) {
- selection.select(node);
- return FALSE;
- }
- }, editor.getBody());
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.getParent(selection.getNode(), function (node) {
+ if (node.nodeType == 1 && counter++ == value) {
+ selection.select(node);
+ return FALSE;
+ }
+ }, editor.getBody());
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- mceSelectNode: function(command, ui, value) {
- selection.select(value);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ mceSelectNode: function (command, ui, value) {
+ selection.select(value);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- mceInsertContent: function(command, ui, value) {
- InsertContent.insertAtCaret(editor, value);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ mceInsertContent: function (command, ui, value) {
+ InsertContent.insertAtCaret(editor, value);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- mceInsertRawHTML: function(command, ui, value) {
- selection.setContent('tiny_mce_marker');
- editor.setContent(
- editor.getContent().replace(/tiny_mce_marker/g, function() {
- return value;
- })
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ mceInsertRawHTML: function (command, ui, value) {
+ selection.setContent('tiny_mce_marker');
+ editor.setContent(
+ editor.getContent().replace(/tiny_mce_marker/g, function () {
+ return value;
+ })
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- mceToggleFormat: function(command, ui, value) {
- toggleFormat(value);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ mceToggleFormat: function (command, ui, value) {
+ toggleFormat(value);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- mceSetContent: function(command, ui, value) {
- editor.setContent(value);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ mceSetContent: function (command, ui, value) {
+ editor.setContent(value);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'Indent,Outdent': function(command) {
- var intentValue, indentUnit, value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'Indent,Outdent': function (command) {
+ var intentValue, indentUnit, value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup indent level
- intentValue = settings.indentation;
- indentUnit = /[a-z%]+$/i.exec(intentValue);
- intentValue = parseInt(intentValue, 10);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup indent level
+ intentValue = settings.indentation;
+ indentUnit = /[a-z%]+$/i.exec(intentValue);
+ intentValue = parseInt(intentValue, 10);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!queryCommandState('InsertUnorderedList') && !queryCommandState('InsertOrderedList')) {
- // If forced_root_blocks is set to false we don't have a block to indent so lets create a div
- if (!settings.forced_root_block && !dom.getParent(selection.getNode(), dom.isBlock)) {
- formatter.apply('div');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!queryCommandState('InsertUnorderedList') && !queryCommandState('InsertOrderedList')) {
+ // If forced_root_blocks is set to false we don't have a block to indent so lets create a div
+ if (!settings.forced_root_block && !dom.getParent(selection.getNode(), dom.isBlock)) {
+ formatter.apply('div');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(selection.getSelectedBlocks(), function(element) {
- if (dom.getContentEditable(element) === "false") {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(selection.getSelectedBlocks(), function (element) {
+ if (dom.getContentEditable(element) === "false") {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (element.nodeName !== "LI") {
- var indentStyleName = editor.getParam('indent_use_margin', false) ? 'margin' : 'padding';
- indentStyleName = element.nodeName === 'TABLE' ? 'margin' : indentStyleName;
- indentStyleName += dom.getStyle(element, 'direction', true) == 'rtl' ? 'Right' : 'Left';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (element.nodeName !== "LI") {
+ var indentStyleName = editor.getParam('indent_use_margin', false) ? 'margin' : 'padding';
+ indentStyleName = element.nodeName === 'TABLE' ? 'margin' : indentStyleName;
+ indentStyleName += dom.getStyle(element, 'direction', true) == 'rtl' ? 'Right' : 'Left';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (command == 'outdent') {
- value = Math.max(0, parseInt(element.style[indentStyleName] || 0, 10) - intentValue);
- dom.setStyle(element, indentStyleName, value ? value + indentUnit : '');
- } else {
- value = (parseInt(element.style[indentStyleName] || 0, 10) + intentValue) + indentUnit;
- dom.setStyle(element, indentStyleName, value);
- }
- }
- });
- } else {
- execNativeCommand(command);
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (command == 'outdent') {
+ value = Math.max(0, parseInt(element.style[indentStyleName] || 0, 10) - intentValue);
+ dom.setStyle(element, indentStyleName, value ? value + indentUnit : '');
+ } else {
+ value = (parseInt(element.style[indentStyleName] || 0, 10) + intentValue) + indentUnit;
+ dom.setStyle(element, indentStyleName, value);
+ }
+ }
+ });
+ } else {
+ execNativeCommand(command);
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- mceRepaint: function() {
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ mceRepaint: function () {
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- InsertHorizontalRule: function() {
- editor.execCommand('mceInsertContent', false, '<hr />');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ InsertHorizontalRule: function () {
+ editor.execCommand('mceInsertContent', false, '<hr />');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- mceToggleVisualAid: function() {
- editor.hasVisual = !editor.hasVisual;
- editor.addVisual();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ mceToggleVisualAid: function () {
+ editor.hasVisual = !editor.hasVisual;
+ editor.addVisual();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- mceReplaceContent: function(command, ui, value) {
- editor.execCommand('mceInsertContent', false, value.replace(/\{\$selection\}/g, selection.getContent({format: 'text'})));
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ mceReplaceContent: function (command, ui, value) {
+ editor.execCommand('mceInsertContent', false, value.replace(/\{\$selection\}/g, selection.getContent({ format: 'text' })));
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- mceInsertLink: function(command, ui, value) {
- var anchor;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ mceInsertLink: function (command, ui, value) {
+ var anchor;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof value == 'string') {
- value = {href: value};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof value == 'string') {
+ value = { href: value };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- anchor = dom.getParent(selection.getNode(), 'a');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ anchor = dom.getParent(selection.getNode(), 'a');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Spaces are never valid in URLs and it's a very common mistake for people to make so we fix it here.
- value.href = value.href.replace(' ', '%20');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Spaces are never valid in URLs and it's a very common mistake for people to make so we fix it here.
+ value.href = value.href.replace(' ', '%20');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove existing links if there could be child links or that the href isn't specified
- if (!anchor || !value.href) {
- formatter.remove('link');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove existing links if there could be child links or that the href isn't specified
+ if (!anchor || !value.href) {
+ formatter.remove('link');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Apply new link to selection
- if (value.href) {
- formatter.apply('link', value, anchor);
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Apply new link to selection
+ if (value.href) {
+ formatter.apply('link', value, anchor);
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- selectAll: function() {
- var root = dom.getRoot(), rng;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ selectAll: function () {
+ var root = dom.getRoot(), rng;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (selection.getRng().setStart) {
- var editingHost = dom.getParent(selection.getStart(), NodeType.isContentEditableTrue);
- if (editingHost) {
- rng = dom.createRng();
- rng.selectNodeContents(editingHost);
- selection.setRng(rng);
- }
- } else {
- // IE will render it's own root level block elements and sometimes
- // even put font elements in them when the user starts typing. So we need to
- // move the selection to a more suitable element from this:
- // <body>|<p></p></body> to this: <body><p>|</p></body>
- rng = selection.getRng();
- if (!rng.item) {
- rng.moveToElementText(root);
- rng.select();
- }
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (selection.getRng().setStart) {
+ var editingHost = dom.getParent(selection.getStart(), NodeType.isContentEditableTrue);
+ if (editingHost) {
+ rng = dom.createRng();
+ rng.selectNodeContents(editingHost);
+ selection.setRng(rng);
+ }
+ } else {
+ // IE will render it's own root level block elements and sometimes
+ // even put font elements in them when the user starts typing. So we need to
+ // move the selection to a more suitable element from this:
+ // <body>|<p></p></body> to this: <body><p>|</p></body>
+ rng = selection.getRng();
+ if (!rng.item) {
+ rng.moveToElementText(root);
+ rng.select();
+ }
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "delete": function() {
- execNativeCommand("Delete");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "delete": function () {
+ DeleteCommands.deleteCommand(editor);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if body is empty after the delete call if so then set the contents
- // to an empty string and move the caret to any block produced by that operation
- // this fixes the issue with root blocks not being properly produced after a delete call on IE
- var body = editor.getBody();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "forwardDelete": function () {
+ DeleteCommands.forwardDeleteCommand(editor);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (dom.isEmpty(body)) {
- editor.setContent('');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ mceNewDocument: function () {
+ editor.setContent('');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (body.firstChild && dom.isBlock(body.firstChild)) {
- editor.selection.setCursorLocation(body.firstChild, 0);
- } else {
- editor.selection.setCursorLocation(body, 0);
- }
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ InsertLineBreak: function (command, ui, value) {
+ // We load the current event in from EnterKey.js when appropriate to heed
+ // certain event-specific variations such as ctrl-enter in a list
+ var evt = value;
+ var brElm, extraBr, marker;
+ var rng = selection.getRng(true);
+ new RangeUtils(dom).normalize(rng);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- mceNewDocument: function() {
- editor.setContent('');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var offset = rng.startOffset;
+ var container = rng.startContainer;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- InsertLineBreak: function(command, ui, value) {
- // We load the current event in from EnterKey.js when appropriate to heed
- // certain event-specific variations such as ctrl-enter in a list
- var evt = value;
- var brElm, extraBr, marker;
- var rng = selection.getRng(true);
- new RangeUtils(dom).normalize(rng);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Resolve node index
+ if (container.nodeType == 1 && container.hasChildNodes()) {
+ var isAfterLastNodeInContainer = offset > container.childNodes.length - 1;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var offset = rng.startOffset;
- var container = rng.startContainer;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container;
+ if (isAfterLastNodeInContainer && container.nodeType == 3) {
+ offset = container.nodeValue.length;
+ } else {
+ offset = 0;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Resolve node index
- if (container.nodeType == 1 && container.hasChildNodes()) {
- var isAfterLastNodeInContainer = offset > container.childNodes.length - 1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var parentBlock = dom.getParent(container, dom.isBlock);
+ var parentBlockName = parentBlock ? parentBlock.nodeName.toUpperCase() : ''; // IE < 9 & HTML5
+ var containerBlock = parentBlock ? dom.getParent(parentBlock.parentNode, dom.isBlock) : null;
+ var containerBlockName = containerBlock ? containerBlock.nodeName.toUpperCase() : ''; // IE < 9 & HTML5
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container;
- if (isAfterLastNodeInContainer && container.nodeType == 3) {
- offset = container.nodeValue.length;
- } else {
- offset = 0;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Enter inside block contained within a LI then split or insert before/after LI
+ var isControlKey = evt && evt.ctrlKey;
+ if (containerBlockName == 'LI' && !isControlKey) {
+ parentBlock = containerBlock;
+ parentBlockName = containerBlockName;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var parentBlock = dom.getParent(container, dom.isBlock);
- var parentBlockName = parentBlock ? parentBlock.nodeName.toUpperCase() : ''; // IE < 9 & HTML5
- var containerBlock = parentBlock ? dom.getParent(parentBlock.parentNode, dom.isBlock) : null;
- var containerBlockName = containerBlock ? containerBlock.nodeName.toUpperCase() : ''; // IE < 9 & HTML5
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Walks the parent block to the right and look for BR elements
+ function hasRightSideContent() {
+ var walker = new TreeWalker(container, parentBlock), node;
+ var nonEmptyElementsMap = editor.schema.getNonEmptyElements();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Enter inside block contained within a LI then split or insert before/after LI
- var isControlKey = evt && evt.ctrlKey;
- if (containerBlockName == 'LI' && !isControlKey) {
- parentBlock = containerBlock;
- parentBlockName = containerBlockName;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while ((node = walker.next())) {
+ if (nonEmptyElementsMap[node.nodeName.toLowerCase()] || node.length > 0) {
+ return true;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Walks the parent block to the right and look for BR elements
- function hasRightSideContent() {
- var walker = new TreeWalker(container, parentBlock), node;
- var nonEmptyElementsMap = editor.schema.getNonEmptyElements();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (container && container.nodeType == 3 && offset >= container.nodeValue.length) {
+ // Insert extra BR element at the end block elements
+ if (!isOldIE && !hasRightSideContent()) {
+ brElm = dom.create('br');
+ rng.insertNode(brElm);
+ rng.setStartAfter(brElm);
+ rng.setEndAfter(brElm);
+ extraBr = true;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while ((node = walker.next())) {
- if (nonEmptyElementsMap[node.nodeName.toLowerCase()] || node.length > 0) {
- return true;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ brElm = dom.create('br');
+ rng.insertNode(brElm);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (container && container.nodeType == 3 && offset >= container.nodeValue.length) {
- // Insert extra BR element at the end block elements
- if (!isOldIE && !hasRightSideContent()) {
- brElm = dom.create('br');
- rng.insertNode(brElm);
- rng.setStartAfter(brElm);
- rng.setEndAfter(brElm);
- extraBr = true;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Rendering modes below IE8 doesn't display BR elements in PRE unless we have a \n before it
+ var documentMode = dom.doc.documentMode;
+ if (isOldIE && parentBlockName == 'PRE' && (!documentMode || documentMode < 8)) {
+ brElm.parentNode.insertBefore(dom.doc.createTextNode('\r'), brElm);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- brElm = dom.create('br');
- rng.insertNode(brElm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Insert temp marker and scroll to that
+ marker = dom.create('span', {}, ' ');
+ brElm.parentNode.insertBefore(marker, brElm);
+ selection.scrollIntoView(marker);
+ dom.remove(marker);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Rendering modes below IE8 doesn't display BR elements in PRE unless we have a \n before it
- var documentMode = dom.doc.documentMode;
- if (isOldIE && parentBlockName == 'PRE' && (!documentMode || documentMode < 8)) {
- brElm.parentNode.insertBefore(dom.doc.createTextNode('\r'), brElm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!extraBr) {
+ rng.setStartAfter(brElm);
+ rng.setEndAfter(brElm);
+ } else {
+ rng.setStartBefore(brElm);
+ rng.setEndBefore(brElm);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Insert temp marker and scroll to that
- marker = dom.create('span', {}, ' ');
- brElm.parentNode.insertBefore(marker, brElm);
- selection.scrollIntoView(marker);
- dom.remove(marker);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ selection.setRng(rng);
+ editor.undoManager.add();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!extraBr) {
- rng.setStartAfter(brElm);
- rng.setEndAfter(brElm);
- } else {
- rng.setStartBefore(brElm);
- rng.setEndBefore(brElm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return TRUE;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- selection.setRng(rng);
- editor.undoManager.add();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add queryCommandState overrides
+ addCommands({
+ // Override justify commands
+ 'JustifyLeft,JustifyCenter,JustifyRight,JustifyFull': function (command) {
+ var name = 'align' + command.substring(7);
+ var nodes = selection.isCollapsed() ? [dom.getParent(selection.getNode(), dom.isBlock)] : selection.getSelectedBlocks();
+ var matches = map(nodes, function (node) {
+ return !!formatter.matchNode(node, name);
+ });
+ return inArray(matches, TRUE) !== -1;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return TRUE;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'Bold,Italic,Underline,Strikethrough,Superscript,Subscript': function (command) {
+ return isFormatMatch(command);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add queryCommandState overrides
- addCommands({
- // Override justify commands
- 'JustifyLeft,JustifyCenter,JustifyRight,JustifyFull': function(command) {
- var name = 'align' + command.substring(7);
- var nodes = selection.isCollapsed() ? [dom.getParent(selection.getNode(), dom.isBlock)] : selection.getSelectedBlocks();
- var matches = map(nodes, function(node) {
- return !!formatter.matchNode(node, name);
- });
- return inArray(matches, TRUE) !== -1;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ mceBlockQuote: function () {
+ return isFormatMatch('blockquote');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'Bold,Italic,Underline,Strikethrough,Superscript,Subscript': function(command) {
- return isFormatMatch(command);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Outdent: function () {
+ var node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- mceBlockQuote: function() {
- return isFormatMatch('blockquote');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.inline_styles) {
+ if ((node = dom.getParent(selection.getStart(), dom.isBlock)) && parseInt(node.style.paddingLeft, 10) > 0) {
+ return TRUE;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Outdent: function() {
- var node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((node = dom.getParent(selection.getEnd(), dom.isBlock)) && parseInt(node.style.paddingLeft, 10) > 0) {
+ return TRUE;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.inline_styles) {
- if ((node = dom.getParent(selection.getStart(), dom.isBlock)) && parseInt(node.style.paddingLeft, 10) > 0) {
- return TRUE;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ queryCommandState('InsertUnorderedList') ||
+ queryCommandState('InsertOrderedList') ||
+ (!settings.inline_styles && !!dom.getParent(selection.getNode(), 'BLOCKQUOTE'))
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ((node = dom.getParent(selection.getEnd(), dom.isBlock)) && parseInt(node.style.paddingLeft, 10) > 0) {
- return TRUE;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'InsertUnorderedList,InsertOrderedList': function (command) {
+ var list = dom.getParent(selection.getNode(), 'ul,ol');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- queryCommandState('InsertUnorderedList') ||
- queryCommandState('InsertOrderedList') ||
- (!settings.inline_styles && !!dom.getParent(selection.getNode(), 'BLOCKQUOTE'))
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return list &&
+ (
+ command === 'insertunorderedlist' && list.tagName === 'UL' ||
+ command === 'insertorderedlist' && list.tagName === 'OL'
+ );
+ }
+ }, 'state');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'InsertUnorderedList,InsertOrderedList': function(command) {
- var list = dom.getParent(selection.getNode(), 'ul,ol');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add queryCommandValue overrides
+ addCommands({
+ 'FontSize,FontName': function (command) {
+ var value = 0, parent;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return list &&
- (
- command === 'insertunorderedlist' && list.tagName === 'UL' ||
- command === 'insertorderedlist' && list.tagName === 'OL'
- );
- }
- }, 'state');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((parent = dom.getParent(selection.getNode(), 'span'))) {
+ if (command == 'fontsize') {
+ value = parent.style.fontSize;
+ } else {
+ value = parent.style.fontFamily.replace(/, /g, ',').replace(/[\'\"]/g, '').toLowerCase();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add queryCommandValue overrides
- addCommands({
- 'FontSize,FontName': function(command) {
- var value = 0, parent;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return value;
+ }
+ }, 'value');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ((parent = dom.getParent(selection.getNode(), 'span'))) {
- if (command == 'fontsize') {
- value = parent.style.fontSize;
- } else {
- value = parent.style.fontFamily.replace(/, /g, ',').replace(/[\'\"]/g, '').toLowerCase();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add undo manager logic
+ addCommands({
+ Undo: function () {
+ editor.undoManager.undo();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return value;
- }
- }, 'value');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Redo: function () {
+ editor.undoManager.redo();
+ }
+ });
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add undo manager logic
- addCommands({
- Undo: function() {
- editor.undoManager.undo();
- },
-
- Redo: function() {
- editor.undoManager.redo();
- }
- });
- };
-});
-
-// Included from: js/tinymce/classes/util/URI.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * URI.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -25224,432 +29313,435 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * This class handles parsing, modification and serialization of URI/URL strings.
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.util.URI
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/util/URI", [
- "tinymce/util/Tools"
-], function(Tools) {
- var each = Tools.each, trim = Tools.trim;
- var queryParts = "source protocol authority userInfo user password host port relative path directory file query anchor".split(' ');
- var DEFAULT_PORTS = {
- 'ftp': 21,
- 'http': 80,
- 'https': 443,
- 'mailto': 25
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.URI',
+ [
+ 'global!document',
+ 'tinymce.core.util.Tools'
+ ],
+ function (document, Tools) {
+ var each = Tools.each, trim = Tools.trim;
+ var queryParts = "source protocol authority userInfo user password host port relative path directory file query anchor".split(' ');
+ var DEFAULT_PORTS = {
+ 'ftp': 21,
+ 'http': 80,
+ 'https': 443,
+ 'mailto': 25
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a new URI instance.
- *
- * @constructor
- * @method URI
- * @param {String} url URI string to parse.
- * @param {Object} settings Optional settings object.
- */
- function URI(url, settings) {
- var self = this, baseUri, base_url;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a new URI instance.
+ *
+ * @constructor
+ * @method URI
+ * @param {String} url URI string to parse.
+ * @param {Object} settings Optional settings object.
+ */
+ function URI(url, settings) {
+ var self = this, baseUri, baseUrl;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- url = trim(url);
- settings = self.settings = settings || {};
- baseUri = settings.base_uri;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ url = trim(url);
+ settings = self.settings = settings || {};
+ baseUri = settings.base_uri;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Strange app protocol that isn't http/https or local anchor
- // For example: mailto,skype,tel etc.
- if (/^([\w\-]+):([^\/]{2})/i.test(url) || /^\s*#/.test(url)) {
- self.source = url;
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Strange app protocol that isn't http/https or local anchor
+ // For example: mailto,skype,tel etc.
+ if (/^([\w\-]+):([^\/]{2})/i.test(url) || /^\s*#/.test(url)) {
+ self.source = url;
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isProtocolRelative = url.indexOf('//') === 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isProtocolRelative = url.indexOf('//') === 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Absolute path with no host, fake host and protocol
- if (url.indexOf('/') === 0 && !isProtocolRelative) {
- url = (baseUri ? baseUri.protocol || 'http' : 'http') + '://mce_host' + url;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Absolute path with no host, fake host and protocol
+ if (url.indexOf('/') === 0 && !isProtocolRelative) {
+ url = (baseUri ? baseUri.protocol || 'http' : 'http') + '://mce_host' + url;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Relative path http:// or protocol relative //path
- if (!/^[\w\-]*:?\/\//.test(url)) {
- base_url = settings.base_uri ? settings.base_uri.path : new URI(location.href).directory;
- if (settings.base_uri.protocol === "") {
- url = '//mce_host' + self.toAbsPath(base_url, url);
- } else {
- url = /([^#?]*)([#?]?.*)/.exec(url);
- url = ((baseUri && baseUri.protocol) || 'http') + '://mce_host' + self.toAbsPath(base_url, url[1]) + url[2];
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Relative path http:// or protocol relative //path
+ if (!/^[\w\-]*:?\/\//.test(url)) {
+ baseUrl = settings.base_uri ? settings.base_uri.path : new URI(document.location.href).directory;
+ if (settings.base_uri.protocol === "") {
+ url = '//mce_host' + self.toAbsPath(baseUrl, url);
+ } else {
+ url = /([^#?]*)([#?]?.*)/.exec(url);
+ url = ((baseUri && baseUri.protocol) || 'http') + '://mce_host' + self.toAbsPath(baseUrl, url[1]) + url[2];
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Parse URL (Credits goes to Steave, http://blog.stevenlevithan.com/archives/parseuri)
- url = url.replace(/@@/g, '(mce_at)'); // Zope 3 workaround, they use @@something
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Parse URL (Credits goes to Steave, http://blog.stevenlevithan.com/archives/parseuri)
+ url = url.replace(/@@/g, '(mce_at)'); // Zope 3 workaround, they use @@something
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /*jshint maxlen: 255 */
- /*eslint max-len: 0 */
- url = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(url);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /*jshint maxlen: 255 */
+ /*eslint max-len: 0 */
+ url = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(url);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(queryParts, function(v, i) {
- var part = url[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(queryParts, function (v, i) {
+ var part = url[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Zope 3 workaround, they use @@something
- if (part) {
- part = part.replace(/\(mce_at\)/g, '@@');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Zope 3 workaround, they use @@something
+ if (part) {
+ part = part.replace(/\(mce_at\)/g, '@@');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self[v] = part;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self[v] = part;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (baseUri) {
- if (!self.protocol) {
- self.protocol = baseUri.protocol;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (baseUri) {
+ if (!self.protocol) {
+ self.protocol = baseUri.protocol;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.userInfo) {
- self.userInfo = baseUri.userInfo;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.userInfo) {
+ self.userInfo = baseUri.userInfo;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.port && self.host === 'mce_host') {
- self.port = baseUri.port;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.port && self.host === 'mce_host') {
+ self.port = baseUri.port;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.host || self.host === 'mce_host') {
- self.host = baseUri.host;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.host || self.host === 'mce_host') {
+ self.host = baseUri.host;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.source = '';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.source = '';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isProtocolRelative) {
- self.protocol = '';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isProtocolRelative) {
+ self.protocol = '';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- //t.path = t.path || '/';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ //t.path = t.path || '/';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- URI.prototype = {
- /**
- * Sets the internal path part of the URI.
- *
- * @method setPath
- * @param {string} path Path string to set.
- */
- setPath: function(path) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ URI.prototype = {
+ /**
+ * Sets the internal path part of the URI.
+ *
+ * @method setPath
+ * @param {string} path Path string to set.
+ */
+ setPath: function (path) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- path = /^(.*?)\/?(\w+)?$/.exec(path);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ path = /^(.*?)\/?(\w+)?$/.exec(path);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Update path parts
- self.path = path[0];
- self.directory = path[1];
- self.file = path[2];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Update path parts
+ self.path = path[0];
+ self.directory = path[1];
+ self.file = path[2];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Rebuild source
- self.source = '';
- self.getURI();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Rebuild source
+ self.source = '';
+ self.getURI();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Converts the specified URI into a relative URI based on the current URI instance location.
- *
- * @method toRelative
- * @param {String} uri URI to convert into a relative path/URI.
- * @return {String} Relative URI from the point specified in the current URI instance.
- * @example
- * // Converts an absolute URL to an relative URL url will be somedir/somefile.htm
- * var url = new tinymce.util.URI('http://www.site.com/dir/').toRelative('http://www.site.com/dir/somedir/somefile.htm');
- */
- toRelative: function(uri) {
- var self = this, output;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Converts the specified URI into a relative URI based on the current URI instance location.
+ *
+ * @method toRelative
+ * @param {String} uri URI to convert into a relative path/URI.
+ * @return {String} Relative URI from the point specified in the current URI instance.
+ * @example
+ * // Converts an absolute URL to an relative URL url will be somedir/somefile.htm
+ * var url = new tinymce.util.URI('http://www.site.com/dir/').toRelative('http://www.site.com/dir/somedir/somefile.htm');
+ */
+ toRelative: function (uri) {
+ var self = this, output;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (uri === "./") {
- return uri;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (uri === "./") {
+ return uri;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- uri = new URI(uri, {base_uri: self});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ uri = new URI(uri, { base_uri: self });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Not on same domain/port or protocol
- if ((uri.host != 'mce_host' && self.host != uri.host && uri.host) || self.port != uri.port ||
- (self.protocol != uri.protocol && uri.protocol !== "")) {
- return uri.getURI();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Not on same domain/port or protocol
+ if ((uri.host != 'mce_host' && self.host != uri.host && uri.host) || self.port != uri.port ||
+ (self.protocol != uri.protocol && uri.protocol !== "")) {
+ return uri.getURI();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var tu = self.getURI(), uu = uri.getURI();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var tu = self.getURI(), uu = uri.getURI();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Allow usage of the base_uri when relative_urls = true
- if (tu == uu || (tu.charAt(tu.length - 1) == "/" && tu.substr(0, tu.length - 1) == uu)) {
- return tu;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Allow usage of the base_uri when relative_urls = true
+ if (tu == uu || (tu.charAt(tu.length - 1) == "/" && tu.substr(0, tu.length - 1) == uu)) {
+ return tu;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- output = self.toRelPath(self.path, uri.path);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ output = self.toRelPath(self.path, uri.path);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add query
- if (uri.query) {
- output += '?' + uri.query;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add query
+ if (uri.query) {
+ output += '?' + uri.query;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add anchor
- if (uri.anchor) {
- output += '#' + uri.anchor;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add anchor
+ if (uri.anchor) {
+ output += '#' + uri.anchor;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return output;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return output;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Converts the specified URI into a absolute URI based on the current URI instance location.
- *
- * @method toAbsolute
- * @param {String} uri URI to convert into a relative path/URI.
- * @param {Boolean} noHost No host and protocol prefix.
- * @return {String} Absolute URI from the point specified in the current URI instance.
- * @example
- * // Converts an relative URL to an absolute URL url will be http://www.site.com/dir/somedir/somefile.htm
- * var url = new tinymce.util.URI('http://www.site.com/dir/').toAbsolute('somedir/somefile.htm');
- */
- toAbsolute: function(uri, noHost) {
- uri = new URI(uri, {base_uri: this});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Converts the specified URI into a absolute URI based on the current URI instance location.
+ *
+ * @method toAbsolute
+ * @param {String} uri URI to convert into a relative path/URI.
+ * @param {Boolean} noHost No host and protocol prefix.
+ * @return {String} Absolute URI from the point specified in the current URI instance.
+ * @example
+ * // Converts an relative URL to an absolute URL url will be http://www.site.com/dir/somedir/somefile.htm
+ * var url = new tinymce.util.URI('http://www.site.com/dir/').toAbsolute('somedir/somefile.htm');
+ */
+ toAbsolute: function (uri, noHost) {
+ uri = new URI(uri, { base_uri: this });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return uri.getURI(noHost && this.isSameOrigin(uri));
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return uri.getURI(noHost && this.isSameOrigin(uri));
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Determine whether the given URI has the same origin as this URI. Based on RFC-6454.
- * Supports default ports for protocols listed in DEFAULT_PORTS. Unsupported protocols will fail safe: they
- * won't match, if the port specifications differ.
- *
- * @method isSameOrigin
- * @param {tinymce.util.URI} uri Uri instance to compare.
- * @returns {Boolean} True if the origins are the same.
- */
- isSameOrigin: function(uri) {
- if (this.host == uri.host && this.protocol == uri.protocol) {
- if (this.port == uri.port) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Determine whether the given URI has the same origin as this URI. Based on RFC-6454.
+ * Supports default ports for protocols listed in DEFAULT_PORTS. Unsupported protocols will fail safe: they
+ * won't match, if the port specifications differ.
+ *
+ * @method isSameOrigin
+ * @param {tinymce.util.URI} uri Uri instance to compare.
+ * @returns {Boolean} True if the origins are the same.
+ */
+ isSameOrigin: function (uri) {
+ if (this.host == uri.host && this.protocol == uri.protocol) {
+ if (this.port == uri.port) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var defaultPort = DEFAULT_PORTS[this.protocol];
- if (defaultPort && ((this.port || defaultPort) == (uri.port || defaultPort))) {
- return true;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var defaultPort = DEFAULT_PORTS[this.protocol];
+ if (defaultPort && ((this.port || defaultPort) == (uri.port || defaultPort))) {
+ return true;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Converts a absolute path into a relative path.
- *
- * @method toRelPath
- * @param {String} base Base point to convert the path from.
- * @param {String} path Absolute path to convert into a relative path.
- */
- toRelPath: function(base, path) {
- var items, breakPoint = 0, out = '', i, l;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Converts a absolute path into a relative path.
+ *
+ * @method toRelPath
+ * @param {String} base Base point to convert the path from.
+ * @param {String} path Absolute path to convert into a relative path.
+ */
+ toRelPath: function (base, path) {
+ var items, breakPoint = 0, out = '', i, l;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Split the paths
- base = base.substring(0, base.lastIndexOf('/'));
- base = base.split('/');
- items = path.split('/');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Split the paths
+ base = base.substring(0, base.lastIndexOf('/'));
+ base = base.split('/');
+ items = path.split('/');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (base.length >= items.length) {
- for (i = 0, l = base.length; i < l; i++) {
- if (i >= items.length || base[i] != items[i]) {
- breakPoint = i + 1;
- break;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (base.length >= items.length) {
+ for (i = 0, l = base.length; i < l; i++) {
+ if (i >= items.length || base[i] != items[i]) {
+ breakPoint = i + 1;
+ break;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (base.length < items.length) {
- for (i = 0, l = items.length; i < l; i++) {
- if (i >= base.length || base[i] != items[i]) {
- breakPoint = i + 1;
- break;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (base.length < items.length) {
+ for (i = 0, l = items.length; i < l; i++) {
+ if (i >= base.length || base[i] != items[i]) {
+ breakPoint = i + 1;
+ break;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (breakPoint === 1) {
- return path;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (breakPoint === 1) {
+ return path;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0, l = base.length - (breakPoint - 1); i < l; i++) {
- out += "../";
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0, l = base.length - (breakPoint - 1); i < l; i++) {
+ out += "../";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = breakPoint - 1, l = items.length; i < l; i++) {
- if (i != breakPoint - 1) {
- out += "/" + items[i];
- } else {
- out += items[i];
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = breakPoint - 1, l = items.length; i < l; i++) {
+ if (i != breakPoint - 1) {
+ out += "/" + items[i];
+ } else {
+ out += items[i];
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return out;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return out;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Converts a relative path into a absolute path.
- *
- * @method toAbsPath
- * @param {String} base Base point to convert the path from.
- * @param {String} path Relative path to convert into an absolute path.
- */
- toAbsPath: function(base, path) {
- var i, nb = 0, o = [], tr, outPath;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Converts a relative path into a absolute path.
+ *
+ * @method toAbsPath
+ * @param {String} base Base point to convert the path from.
+ * @param {String} path Relative path to convert into an absolute path.
+ */
+ toAbsPath: function (base, path) {
+ var i, nb = 0, o = [], tr, outPath;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Split paths
- tr = /\/$/.test(path) ? '/' : '';
- base = base.split('/');
- path = path.split('/');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Split paths
+ tr = /\/$/.test(path) ? '/' : '';
+ base = base.split('/');
+ path = path.split('/');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove empty chunks
- each(base, function(k) {
- if (k) {
- o.push(k);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove empty chunks
+ each(base, function (k) {
+ if (k) {
+ o.push(k);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- base = o;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ base = o;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Merge relURLParts chunks
- for (i = path.length - 1, o = []; i >= 0; i--) {
- // Ignore empty or .
- if (path[i].length === 0 || path[i] === ".") {
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Merge relURLParts chunks
+ for (i = path.length - 1, o = []; i >= 0; i--) {
+ // Ignore empty or .
+ if (path[i].length === 0 || path[i] === ".") {
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Is parent
- if (path[i] === '..') {
- nb++;
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Is parent
+ if (path[i] === '..') {
+ nb++;
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move up
- if (nb > 0) {
- nb--;
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move up
+ if (nb > 0) {
+ nb--;
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- o.push(path[i]);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ o.push(path[i]);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- i = base.length - nb;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ i = base.length - nb;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If /a/b/c or /
- if (i <= 0) {
- outPath = o.reverse().join('/');
- } else {
- outPath = base.slice(0, i).join('/') + '/' + o.reverse().join('/');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If /a/b/c or /
+ if (i <= 0) {
+ outPath = o.reverse().join('/');
+ } else {
+ outPath = base.slice(0, i).join('/') + '/' + o.reverse().join('/');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add front / if it's needed
- if (outPath.indexOf('/') !== 0) {
- outPath = '/' + outPath;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add front / if it's needed
+ if (outPath.indexOf('/') !== 0) {
+ outPath = '/' + outPath;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add traling / if it's needed
- if (tr && outPath.lastIndexOf('/') !== outPath.length - 1) {
- outPath += tr;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add traling / if it's needed
+ if (tr && outPath.lastIndexOf('/') !== outPath.length - 1) {
+ outPath += tr;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return outPath;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return outPath;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the full URI of the internal structure.
- *
- * @method getURI
- * @param {Boolean} noProtoHost Optional no host and protocol part. Defaults to false.
- */
- getURI: function(noProtoHost) {
- var s, self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the full URI of the internal structure.
+ *
+ * @method getURI
+ * @param {Boolean} noProtoHost Optional no host and protocol part. Defaults to false.
+ */
+ getURI: function (noProtoHost) {
+ var s, self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Rebuild source
- if (!self.source || noProtoHost) {
- s = '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Rebuild source
+ if (!self.source || noProtoHost) {
+ s = '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!noProtoHost) {
- if (self.protocol) {
- s += self.protocol + '://';
- } else {
- s += '//';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!noProtoHost) {
+ if (self.protocol) {
+ s += self.protocol + '://';
+ } else {
+ s += '//';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.userInfo) {
- s += self.userInfo + '@';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.userInfo) {
+ s += self.userInfo + '@';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.host) {
- s += self.host;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.host) {
+ s += self.host;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.port) {
- s += ':' + self.port;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.port) {
+ s += ':' + self.port;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.path) {
- s += self.path;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.path) {
+ s += self.path;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.query) {
- s += '?' + self.query;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.query) {
+ s += '?' + self.query;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.anchor) {
- s += '#' + self.anchor;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.anchor) {
+ s += '#' + self.anchor;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.source = s;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.source = s;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self.source;
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self.source;
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- URI.parseDataUri = function(uri) {
- var type, matches;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ URI.parseDataUri = function (uri) {
+ var type, matches;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- uri = decodeURIComponent(uri).split(',');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ uri = decodeURIComponent(uri).split(',');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- matches = /data:([^;]+)/.exec(uri[0]);
- if (matches) {
- type = matches[1];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ matches = /data:([^;]+)/.exec(uri[0]);
+ if (matches) {
+ type = matches[1];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- type: type,
- data: uri[1]
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ type: type,
+ data: uri[1]
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- URI.getDocumentBaseUrl = function(loc) {
- var baseUrl;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ URI.getDocumentBaseUrl = function (loc) {
+ var baseUrl;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Pass applewebdata:// and other non web protocols though
- if (loc.protocol.indexOf('http') !== 0 && loc.protocol !== 'file:') {
- baseUrl = loc.href;
- } else {
- baseUrl = loc.protocol + '//' + loc.host + loc.pathname;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Pass applewebdata:// and other non web protocols though
+ if (loc.protocol.indexOf('http') !== 0 && loc.protocol !== 'file:') {
+ baseUrl = loc.href;
+ } else {
+ baseUrl = loc.protocol + '//' + loc.host + loc.pathname;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (/^[^:]+:\/\/\/?[^\/]+\//.test(baseUrl)) {
- baseUrl = baseUrl.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (/^[^:]+:\/\/\/?[^\/]+\//.test(baseUrl)) {
+ baseUrl = baseUrl.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!/[\/\\]$/.test(baseUrl)) {
- baseUrl += '/';
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!/[\/\\]$/.test(baseUrl)) {
+ baseUrl += '/';
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return baseUrl;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return baseUrl;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return URI;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return URI;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/util/Class.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Class.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -25666,160 +29758,161 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * * Static functions
</span><span class="cx" style="display: block; padding: 0 10px"> * * Defaults settings
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/util/Class", [
- "tinymce/util/Tools"
-], function(Tools) {
- var each = Tools.each, extend = Tools.extend;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.Class',
+ [
+ "tinymce.core.util.Tools"
+ ],
+ function (Tools) {
+ var each = Tools.each, extend = Tools.extend;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var extendClass, initializing;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var extendClass, initializing;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function Class() {
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function Class() {
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Provides classical inheritance, based on code made by John Resig
- Class.extend = extendClass = function(prop) {
- var self = this, _super = self.prototype, prototype, name, member;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Provides classical inheritance, based on code made by John Resig
+ Class.extend = extendClass = function (prop) {
+ var self = this, _super = self.prototype, prototype, name, member;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // The dummy class constructor
- function Class() {
- var i, mixins, mixin, self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // The dummy class constructor
+ function Class() {
+ var i, mixins, mixin, self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // All construction is actually done in the init method
- if (!initializing) {
- // Run class constuctor
- if (self.init) {
- self.init.apply(self, arguments);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // All construction is actually done in the init method
+ if (!initializing) {
+ // Run class constuctor
+ if (self.init) {
+ self.init.apply(self, arguments);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Run mixin constructors
- mixins = self.Mixins;
- if (mixins) {
- i = mixins.length;
- while (i--) {
- mixin = mixins[i];
- if (mixin.init) {
- mixin.init.apply(self, arguments);
- }
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Run mixin constructors
+ mixins = self.Mixins;
+ if (mixins) {
+ i = mixins.length;
+ while (i--) {
+ mixin = mixins[i];
+ if (mixin.init) {
+ mixin.init.apply(self, arguments);
+ }
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Dummy function, needs to be extended in order to provide functionality
- function dummy() {
- return this;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Dummy function, needs to be extended in order to provide functionality
+ function dummy() {
+ return this;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Creates a overloaded method for the class
- // this enables you to use this._super(); to call the super function
- function createMethod(name, fn) {
- return function() {
- var self = this, tmp = self._super, ret;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Creates a overloaded method for the class
+ // this enables you to use this._super(); to call the super function
+ function createMethod(name, fn) {
+ return function () {
+ var self = this, tmp = self._super, ret;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super = _super[name];
- ret = fn.apply(self, arguments);
- self._super = tmp;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super = _super[name];
+ ret = fn.apply(self, arguments);
+ self._super = tmp;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return ret;
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return ret;
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Instantiate a base class (but only create the instance,
- // don't run the init constructor)
- initializing = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Instantiate a base class (but only create the instance,
+ // don't run the init constructor)
+ initializing = true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /*eslint new-cap:0 */
- prototype = new self();
- initializing = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /*eslint new-cap:0 */
+ prototype = new self();
+ initializing = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add mixins
- if (prop.Mixins) {
- each(prop.Mixins, function(mixin) {
- for (var name in mixin) {
- if (name !== "init") {
- prop[name] = mixin[name];
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add mixins
+ if (prop.Mixins) {
+ each(prop.Mixins, function (mixin) {
+ for (var name in mixin) {
+ if (name !== "init") {
+ prop[name] = mixin[name];
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (_super.Mixins) {
- prop.Mixins = _super.Mixins.concat(prop.Mixins);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (_super.Mixins) {
+ prop.Mixins = _super.Mixins.concat(prop.Mixins);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Generate dummy methods
- if (prop.Methods) {
- each(prop.Methods.split(','), function(name) {
- prop[name] = dummy;
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Generate dummy methods
+ if (prop.Methods) {
+ each(prop.Methods.split(','), function (name) {
+ prop[name] = dummy;
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Generate property methods
- if (prop.Properties) {
- each(prop.Properties.split(','), function(name) {
- var fieldName = '_' + name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Generate property methods
+ if (prop.Properties) {
+ each(prop.Properties.split(','), function (name) {
+ var fieldName = '_' + name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- prop[name] = function(value) {
- var self = this, undef;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ prop[name] = function (value) {
+ var self = this, undef;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set value
- if (value !== undef) {
- self[fieldName] = value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set value
+ if (value !== undef) {
+ self[fieldName] = value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Get value
- return self[fieldName];
- };
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get value
+ return self[fieldName];
+ };
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Static functions
- if (prop.Statics) {
- each(prop.Statics, function(func, name) {
- Class[name] = func;
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Static functions
+ if (prop.Statics) {
+ each(prop.Statics, function (func, name) {
+ Class[name] = func;
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Default settings
- if (prop.Defaults && _super.Defaults) {
- prop.Defaults = extend({}, _super.Defaults, prop.Defaults);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Default settings
+ if (prop.Defaults && _super.Defaults) {
+ prop.Defaults = extend({}, _super.Defaults, prop.Defaults);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Copy the properties over onto the new prototype
- for (name in prop) {
- member = prop[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Copy the properties over onto the new prototype
+ for (name in prop) {
+ member = prop[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof member == "function" && _super[name]) {
- prototype[name] = createMethod(name, member);
- } else {
- prototype[name] = member;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof member == "function" && _super[name]) {
+ prototype[name] = createMethod(name, member);
+ } else {
+ prototype[name] = member;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Populate our constructed prototype object
- Class.prototype = prototype;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Populate our constructed prototype object
+ Class.prototype = prototype;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Enforce the constructor to be what we expect
- Class.constructor = Class;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Enforce the constructor to be what we expect
+ Class.constructor = Class;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // And make this class extendible
- Class.extend = extendClass;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // And make this class extendible
+ Class.extend = extendClass;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Class;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Class;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Class;
-});
-
-// Included from: js/tinymce/classes/util/EventDispatcher.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Class;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * EventDispatcher.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -25836,505 +29929,510 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * eventDispatcher.on('click', function() {console.log('data');});
</span><span class="cx" style="display: block; padding: 0 10px"> * eventDispatcher.fire('click', {data: 123});
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/util/EventDispatcher", [
- "tinymce/util/Tools"
-], function(Tools) {
- var nativeEvents = Tools.makeMap(
- "focus blur focusin focusout click dblclick mousedown mouseup mousemove mouseover beforepaste paste cut copy selectionchange " +
- "mouseout mouseenter mouseleave wheel keydown keypress keyup input contextmenu dragstart dragend dragover " +
- "draggesture dragdrop drop drag submit " +
- "compositionstart compositionend compositionupdate touchstart touchmove touchend",
- ' '
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.EventDispatcher',
+ [
+ "tinymce.core.util.Tools"
+ ],
+ function (Tools) {
+ var nativeEvents = Tools.makeMap(
+ "focus blur focusin focusout click dblclick mousedown mouseup mousemove mouseover beforepaste paste cut copy selectionchange " +
+ "mouseout mouseenter mouseleave wheel keydown keypress keyup input contextmenu dragstart dragend dragover " +
+ "draggesture dragdrop drop drag submit " +
+ "compositionstart compositionend compositionupdate touchstart touchmove touchend",
+ ' '
+ );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function Dispatcher(settings) {
- var self = this, scope, bindings = {}, toggleEvent;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function Dispatcher(settings) {
+ var self = this, scope, bindings = {}, toggleEvent;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function returnFalse() {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function returnFalse() {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function returnTrue() {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function returnTrue() {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- settings = settings || {};
- scope = settings.scope || self;
- toggleEvent = settings.toggleEvent || returnFalse;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ settings = settings || {};
+ scope = settings.scope || self;
+ toggleEvent = settings.toggleEvent || returnFalse;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Fires the specified event by name.
- *
- * @method fire
- * @param {String} name Name of the event to fire.
- * @param {Object?} args Event arguments.
- * @return {Object} Event args instance passed in.
- * @example
- * instance.fire('event', {...});
- */
- function fire(name, args) {
- var handlers, i, l, callback;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Fires the specified event by name.
+ *
+ * @method fire
+ * @param {String} name Name of the event to fire.
+ * @param {Object?} args Event arguments.
+ * @return {Object} Event args instance passed in.
+ * @example
+ * instance.fire('event', {...});
+ */
+ function fire(name, args) {
+ var handlers, i, l, callback;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- name = name.toLowerCase();
- args = args || {};
- args.type = name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ name = name.toLowerCase();
+ args = args || {};
+ args.type = name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup target is there isn't one
- if (!args.target) {
- args.target = scope;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup target is there isn't one
+ if (!args.target) {
+ args.target = scope;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add event delegation methods if they are missing
- if (!args.preventDefault) {
- // Add preventDefault method
- args.preventDefault = function() {
- args.isDefaultPrevented = returnTrue;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add event delegation methods if they are missing
+ if (!args.preventDefault) {
+ // Add preventDefault method
+ args.preventDefault = function () {
+ args.isDefaultPrevented = returnTrue;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add stopPropagation
- args.stopPropagation = function() {
- args.isPropagationStopped = returnTrue;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add stopPropagation
+ args.stopPropagation = function () {
+ args.isPropagationStopped = returnTrue;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add stopImmediatePropagation
- args.stopImmediatePropagation = function() {
- args.isImmediatePropagationStopped = returnTrue;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add stopImmediatePropagation
+ args.stopImmediatePropagation = function () {
+ args.isImmediatePropagationStopped = returnTrue;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add event delegation states
- args.isDefaultPrevented = returnFalse;
- args.isPropagationStopped = returnFalse;
- args.isImmediatePropagationStopped = returnFalse;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add event delegation states
+ args.isDefaultPrevented = returnFalse;
+ args.isPropagationStopped = returnFalse;
+ args.isImmediatePropagationStopped = returnFalse;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.beforeFire) {
- settings.beforeFire(args);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.beforeFire) {
+ settings.beforeFire(args);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- handlers = bindings[name];
- if (handlers) {
- for (i = 0, l = handlers.length; i < l; i++) {
- callback = handlers[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ handlers = bindings[name];
+ if (handlers) {
+ for (i = 0, l = handlers.length; i < l; i++) {
+ callback = handlers[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Unbind handlers marked with "once"
- if (callback.once) {
- off(name, callback.func);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Unbind handlers marked with "once"
+ if (callback.once) {
+ off(name, callback.func);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Stop immediate propagation if needed
- if (args.isImmediatePropagationStopped()) {
- args.stopPropagation();
- return args;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Stop immediate propagation if needed
+ if (args.isImmediatePropagationStopped()) {
+ args.stopPropagation();
+ return args;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If callback returns false then prevent default and stop all propagation
- if (callback.func.call(scope, args) === false) {
- args.preventDefault();
- return args;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If callback returns false then prevent default and stop all propagation
+ if (callback.func.call(scope, args) === false) {
+ args.preventDefault();
+ return args;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return args;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return args;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Binds an event listener to a specific event by name.
- *
- * @method on
- * @param {String} name Event name or space separated list of events to bind.
- * @param {callback} callback Callback to be executed when the event occurs.
- * @param {Boolean} first Optional flag if the event should be prepended. Use this with care.
- * @return {Object} Current class instance.
- * @example
- * instance.on('event', function(e) {
- * // Callback logic
- * });
- */
- function on(name, callback, prepend, extra) {
- var handlers, names, i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Binds an event listener to a specific event by name.
+ *
+ * @method on
+ * @param {String} name Event name or space separated list of events to bind.
+ * @param {callback} callback Callback to be executed when the event occurs.
+ * @param {Boolean} first Optional flag if the event should be prepended. Use this with care.
+ * @return {Object} Current class instance.
+ * @example
+ * instance.on('event', function(e) {
+ * // Callback logic
+ * });
+ */
+ function on(name, callback, prepend, extra) {
+ var handlers, names, i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (callback === false) {
- callback = returnFalse;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (callback === false) {
+ callback = returnFalse;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (callback) {
- callback = {
- func: callback
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (callback) {
+ callback = {
+ func: callback
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (extra) {
- Tools.extend(callback, extra);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (extra) {
+ Tools.extend(callback, extra);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- names = name.toLowerCase().split(' ');
- i = names.length;
- while (i--) {
- name = names[i];
- handlers = bindings[name];
- if (!handlers) {
- handlers = bindings[name] = [];
- toggleEvent(name, true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ names = name.toLowerCase().split(' ');
+ i = names.length;
+ while (i--) {
+ name = names[i];
+ handlers = bindings[name];
+ if (!handlers) {
+ handlers = bindings[name] = [];
+ toggleEvent(name, true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (prepend) {
- handlers.unshift(callback);
- } else {
- handlers.push(callback);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (prepend) {
+ handlers.unshift(callback);
+ } else {
+ handlers.push(callback);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Unbinds an event listener to a specific event by name.
- *
- * @method off
- * @param {String?} name Name of the event to unbind.
- * @param {callback?} callback Callback to unbind.
- * @return {Object} Current class instance.
- * @example
- * // Unbind specific callback
- * instance.off('event', handler);
- *
- * // Unbind all listeners by name
- * instance.off('event');
- *
- * // Unbind all events
- * instance.off();
- */
- function off(name, callback) {
- var i, handlers, bindingName, names, hi;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Unbinds an event listener to a specific event by name.
+ *
+ * @method off
+ * @param {String?} name Name of the event to unbind.
+ * @param {callback?} callback Callback to unbind.
+ * @return {Object} Current class instance.
+ * @example
+ * // Unbind specific callback
+ * instance.off('event', handler);
+ *
+ * // Unbind all listeners by name
+ * instance.off('event');
+ *
+ * // Unbind all events
+ * instance.off();
+ */
+ function off(name, callback) {
+ var i, handlers, bindingName, names, hi;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name) {
- names = name.toLowerCase().split(' ');
- i = names.length;
- while (i--) {
- name = names[i];
- handlers = bindings[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name) {
+ names = name.toLowerCase().split(' ');
+ i = names.length;
+ while (i--) {
+ name = names[i];
+ handlers = bindings[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Unbind all handlers
- if (!name) {
- for (bindingName in bindings) {
- toggleEvent(bindingName, false);
- delete bindings[bindingName];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Unbind all handlers
+ if (!name) {
+ for (bindingName in bindings) {
+ toggleEvent(bindingName, false);
+ delete bindings[bindingName];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (handlers) {
- // Unbind all by name
- if (!callback) {
- handlers.length = 0;
- } else {
- // Unbind specific ones
- hi = handlers.length;
- while (hi--) {
- if (handlers[hi].func === callback) {
- handlers = handlers.slice(0, hi).concat(handlers.slice(hi + 1));
- bindings[name] = handlers;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (handlers) {
+ // Unbind all by name
+ if (!callback) {
+ handlers.length = 0;
+ } else {
+ // Unbind specific ones
+ hi = handlers.length;
+ while (hi--) {
+ if (handlers[hi].func === callback) {
+ handlers = handlers.slice(0, hi).concat(handlers.slice(hi + 1));
+ bindings[name] = handlers;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!handlers.length) {
- toggleEvent(name, false);
- delete bindings[name];
- }
- }
- }
- } else {
- for (name in bindings) {
- toggleEvent(name, false);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!handlers.length) {
+ toggleEvent(name, false);
+ delete bindings[name];
+ }
+ }
+ }
+ } else {
+ for (name in bindings) {
+ toggleEvent(name, false);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bindings = {};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bindings = {};
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Binds an event listener to a specific event by name
- * and automatically unbind the event once the callback fires.
- *
- * @method once
- * @param {String} name Event name or space separated list of events to bind.
- * @param {callback} callback Callback to be executed when the event occurs.
- * @param {Boolean} first Optional flag if the event should be prepended. Use this with care.
- * @return {Object} Current class instance.
- * @example
- * instance.once('event', function(e) {
- * // Callback logic
- * });
- */
- function once(name, callback, prepend) {
- return on(name, callback, prepend, {once: true});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Binds an event listener to a specific event by name
+ * and automatically unbind the event once the callback fires.
+ *
+ * @method once
+ * @param {String} name Event name or space separated list of events to bind.
+ * @param {callback} callback Callback to be executed when the event occurs.
+ * @param {Boolean} first Optional flag if the event should be prepended. Use this with care.
+ * @return {Object} Current class instance.
+ * @example
+ * instance.once('event', function(e) {
+ * // Callback logic
+ * });
+ */
+ function once(name, callback, prepend) {
+ return on(name, callback, prepend, { once: true });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the dispatcher has a event of the specified name.
- *
- * @method has
- * @param {String} name Name of the event to check for.
- * @return {Boolean} true/false if the event exists or not.
- */
- function has(name) {
- name = name.toLowerCase();
- return !(!bindings[name] || bindings[name].length === 0);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the dispatcher has a event of the specified name.
+ *
+ * @method has
+ * @param {String} name Name of the event to check for.
+ * @return {Boolean} true/false if the event exists or not.
+ */
+ function has(name) {
+ name = name.toLowerCase();
+ return !(!bindings[name] || bindings[name].length === 0);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Expose
- self.fire = fire;
- self.on = on;
- self.off = off;
- self.once = once;
- self.has = has;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Expose
+ self.fire = fire;
+ self.on = on;
+ self.off = off;
+ self.once = once;
+ self.has = has;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the specified event name is a native browser event or not.
- *
- * @method isNative
- * @param {String} name Name to check if it's native.
- * @return {Boolean} true/false if the event is native or not.
- * @static
- */
- Dispatcher.isNative = function(name) {
- return !!nativeEvents[name.toLowerCase()];
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the specified event name is a native browser event or not.
+ *
+ * @method isNative
+ * @param {String} name Name to check if it's native.
+ * @return {Boolean} true/false if the event is native or not.
+ * @static
+ */
+ Dispatcher.isNative = function (name) {
+ return !!nativeEvents[name.toLowerCase()];
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Dispatcher;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Dispatcher;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/data/Binding.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Binding.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Observable.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * This class gets dynamically extended to provide a binding between two models. This makes it possible to
- * sync the state of two properties in two models by a layer of abstraction.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * This mixin will add event binding logic to classes.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @private
- * @class tinymce.data.Binding
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @mixin tinymce.util.Observable
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/data/Binding", [], function() {
- /**
- * Constructs a new bidning.
- *
- * @constructor
- * @method Binding
- * @param {Object} settings Settings to the binding.
- */
- function Binding(settings) {
- this.create = settings.create;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.Observable',
+ [
+ "tinymce.core.util.EventDispatcher"
+ ],
+ function (EventDispatcher) {
+ function getEventDispatcher(obj) {
+ if (!obj._eventDispatcher) {
+ obj._eventDispatcher = new EventDispatcher({
+ scope: obj,
+ toggleEvent: function (name, state) {
+ if (EventDispatcher.isNative(name) && obj.toggleNativeEvent) {
+ obj.toggleNativeEvent(name, state);
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates a binding for a property on a model.
- *
- * @method create
- * @param {tinymce.data.ObservableObject} model Model to create binding to.
- * @param {String} name Name of property to bind.
- * @return {tinymce.data.Binding} Binding instance.
- */
- Binding.create = function(model, name) {
- return new Binding({
- create: function(otherModel, otherName) {
- var bindings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return obj._eventDispatcher;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function fromSelfToOther(e) {
- otherModel.set(otherName, e.value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ /**
+ * Fires the specified event by name. Consult the
+ * <a href="/docs/advanced/events">event reference</a> for more details on each event.
+ *
+ * @method fire
+ * @param {String} name Name of the event to fire.
+ * @param {Object?} args Event arguments.
+ * @param {Boolean?} bubble True/false if the event is to be bubbled.
+ * @return {Object} Event args instance passed in.
+ * @example
+ * instance.fire('event', {...});
+ */
+ fire: function (name, args, bubble) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function fromOtherToSelf(e) {
- model.set(name, e.value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Prevent all events except the remove event after the instance has been removed
+ if (self.removed && name !== "remove") {
+ return args;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- otherModel.on('change:' + otherName, fromOtherToSelf);
- model.on('change:' + name, fromSelfToOther);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args = getEventDispatcher(self).fire(name, args, bubble);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Keep track of the bindings
- bindings = otherModel._bindings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Bubble event up to parents
+ if (bubble !== false && self.parent) {
+ var parent = self.parent();
+ while (parent && !args.isPropagationStopped()) {
+ parent.fire(name, args, false);
+ parent = parent.parent();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!bindings) {
- bindings = otherModel._bindings = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return args;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- otherModel.on('destroy', function() {
- var i = bindings.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Binds an event listener to a specific event by name. Consult the
+ * <a href="/docs/advanced/events">event reference</a> for more details on each event.
+ *
+ * @method on
+ * @param {String} name Event name or space separated list of events to bind.
+ * @param {callback} callback Callback to be executed when the event occurs.
+ * @param {Boolean} first Optional flag if the event should be prepended. Use this with care.
+ * @return {Object} Current class instance.
+ * @example
+ * instance.on('event', function(e) {
+ * // Callback logic
+ * });
+ */
+ on: function (name, callback, prepend) {
+ return getEventDispatcher(this).on(name, callback, prepend);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- bindings[i]();
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Unbinds an event listener to a specific event by name. Consult the
+ * <a href="/docs/advanced/events">event reference</a> for more details on each event.
+ *
+ * @method off
+ * @param {String?} name Name of the event to unbind.
+ * @param {callback?} callback Callback to unbind.
+ * @return {Object} Current class instance.
+ * @example
+ * // Unbind specific callback
+ * instance.off('event', handler);
+ *
+ * // Unbind all listeners by name
+ * instance.off('event');
+ *
+ * // Unbind all events
+ * instance.off();
+ */
+ off: function (name, callback) {
+ return getEventDispatcher(this).off(name, callback);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bindings.push(function() {
- model.off('change:' + name, fromSelfToOther);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Bind the event callback and once it fires the callback is removed. Consult the
+ * <a href="/docs/advanced/events">event reference</a> for more details on each event.
+ *
+ * @method once
+ * @param {String} name Name of the event to bind.
+ * @param {callback} callback Callback to bind only once.
+ * @return {Object} Current class instance.
+ */
+ once: function (name, callback) {
+ return getEventDispatcher(this).once(name, callback);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return model.get(name);
- }
- });
- };
-
- return Binding;
-});
-
-// Included from: js/tinymce/classes/util/Observable.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the object has a event of the specified name.
+ *
+ * @method hasEventListeners
+ * @param {String} name Name of the event to check for.
+ * @return {Boolean} true/false if the event exists or not.
+ */
+ hasEventListeners: function (name) {
+ return getEventDispatcher(this).has(name);
+ }
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Observable.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Binding.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * This mixin will add event binding logic to classes.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * This class gets dynamically extended to provide a binding between two models. This makes it possible to
+ * sync the state of two properties in two models by a layer of abstraction.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @mixin tinymce.util.Observable
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @private
+ * @class tinymce.data.Binding
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/util/Observable", [
- "tinymce/util/EventDispatcher"
-], function(EventDispatcher) {
- function getEventDispatcher(obj) {
- if (!obj._eventDispatcher) {
- obj._eventDispatcher = new EventDispatcher({
- scope: obj,
- toggleEvent: function(name, state) {
- if (EventDispatcher.isNative(name) && obj.toggleNativeEvent) {
- obj.toggleNativeEvent(name, state);
- }
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.data.Binding',
+ [
+ ],
+ function () {
+ /**
+ * Constructs a new bidning.
+ *
+ * @constructor
+ * @method Binding
+ * @param {Object} settings Settings to the binding.
+ */
+ function Binding(settings) {
+ this.create = settings.create;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return obj._eventDispatcher;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates a binding for a property on a model.
+ *
+ * @method create
+ * @param {tinymce.data.ObservableObject} model Model to create binding to.
+ * @param {String} name Name of property to bind.
+ * @return {tinymce.data.Binding} Binding instance.
+ */
+ Binding.create = function (model, name) {
+ return new Binding({
+ create: function (otherModel, otherName) {
+ var bindings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- /**
- * Fires the specified event by name. Consult the
- * <a href="/docs/advanced/events">event reference</a> for more details on each event.
- *
- * @method fire
- * @param {String} name Name of the event to fire.
- * @param {Object?} args Event arguments.
- * @param {Boolean?} bubble True/false if the event is to be bubbled.
- * @return {Object} Event args instance passed in.
- * @example
- * instance.fire('event', {...});
- */
- fire: function(name, args, bubble) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function fromSelfToOther(e) {
+ otherModel.set(otherName, e.value);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Prevent all events except the remove event after the instance has been removed
- if (self.removed && name !== "remove") {
- return args;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function fromOtherToSelf(e) {
+ model.set(name, e.value);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args = getEventDispatcher(self).fire(name, args, bubble);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ otherModel.on('change:' + otherName, fromOtherToSelf);
+ model.on('change:' + name, fromSelfToOther);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Bubble event up to parents
- if (bubble !== false && self.parent) {
- var parent = self.parent();
- while (parent && !args.isPropagationStopped()) {
- parent.fire(name, args, false);
- parent = parent.parent();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Keep track of the bindings
+ bindings = otherModel._bindings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return args;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!bindings) {
+ bindings = otherModel._bindings = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Binds an event listener to a specific event by name. Consult the
- * <a href="/docs/advanced/events">event reference</a> for more details on each event.
- *
- * @method on
- * @param {String} name Event name or space separated list of events to bind.
- * @param {callback} callback Callback to be executed when the event occurs.
- * @param {Boolean} first Optional flag if the event should be prepended. Use this with care.
- * @return {Object} Current class instance.
- * @example
- * instance.on('event', function(e) {
- * // Callback logic
- * });
- */
- on: function(name, callback, prepend) {
- return getEventDispatcher(this).on(name, callback, prepend);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ otherModel.on('destroy', function () {
+ var i = bindings.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Unbinds an event listener to a specific event by name. Consult the
- * <a href="/docs/advanced/events">event reference</a> for more details on each event.
- *
- * @method off
- * @param {String?} name Name of the event to unbind.
- * @param {callback?} callback Callback to unbind.
- * @return {Object} Current class instance.
- * @example
- * // Unbind specific callback
- * instance.off('event', handler);
- *
- * // Unbind all listeners by name
- * instance.off('event');
- *
- * // Unbind all events
- * instance.off();
- */
- off: function(name, callback) {
- return getEventDispatcher(this).off(name, callback);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ bindings[i]();
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Bind the event callback and once it fires the callback is removed. Consult the
- * <a href="/docs/advanced/events">event reference</a> for more details on each event.
- *
- * @method once
- * @param {String} name Name of the event to bind.
- * @param {callback} callback Callback to bind only once.
- * @return {Object} Current class instance.
- */
- once: function(name, callback) {
- return getEventDispatcher(this).once(name, callback);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bindings.push(function () {
+ model.off('change:' + name, fromSelfToOther);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the object has a event of the specified name.
- *
- * @method hasEventListeners
- * @param {String} name Name of the event to check for.
- * @return {Boolean} true/false if the event exists or not.
- */
- hasEventListeners: function(name) {
- return getEventDispatcher(this).has(name);
- }
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return model.get(name);
+ }
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/data/ObservableObject.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Binding;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * ObservableObject.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -26346,192 +30444,192 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.data.ObservableObject
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/data/ObservableObject", [
- "tinymce/data/Binding",
- "tinymce/util/Observable",
- "tinymce/util/Class",
- "tinymce/util/Tools"
-], function(Binding, Observable, Class, Tools) {
- function isNode(node) {
- return node.nodeType > 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.data.ObservableObject',
+ [
+ 'tinymce.core.data.Binding',
+ 'tinymce.core.util.Class',
+ 'tinymce.core.util.Observable',
+ 'tinymce.core.util.Tools'
+ ], function (Binding, Class, Observable, Tools) {
+ function isNode(node) {
+ return node.nodeType > 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Todo: Maybe this should be shallow compare since it might be huge object references
- function isEqual(a, b) {
- var k, checked;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Todo: Maybe this should be shallow compare since it might be huge object references
+ function isEqual(a, b) {
+ var k, checked;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Strict equals
- if (a === b) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Strict equals
+ if (a === b) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Compare null
- if (a === null || b === null) {
- return a === b;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Compare null
+ if (a === null || b === null) {
+ return a === b;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Compare number, boolean, string, undefined
- if (typeof a !== "object" || typeof b !== "object") {
- return a === b;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Compare number, boolean, string, undefined
+ if (typeof a !== "object" || typeof b !== "object") {
+ return a === b;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Compare arrays
- if (Tools.isArray(b)) {
- if (a.length !== b.length) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Compare arrays
+ if (Tools.isArray(b)) {
+ if (a.length !== b.length) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- k = a.length;
- while (k--) {
- if (!isEqual(a[k], b[k])) {
- return false;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ k = a.length;
+ while (k--) {
+ if (!isEqual(a[k], b[k])) {
+ return false;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Shallow compare nodes
- if (isNode(a) || isNode(b)) {
- return a === b;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Shallow compare nodes
+ if (isNode(a) || isNode(b)) {
+ return a === b;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Compare objects
- checked = {};
- for (k in b) {
- if (!isEqual(a[k], b[k])) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Compare objects
+ checked = {};
+ for (k in b) {
+ if (!isEqual(a[k], b[k])) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- checked[k] = true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ checked[k] = true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (k in a) {
- if (!checked[k] && !isEqual(a[k], b[k])) {
- return false;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (k in a) {
+ if (!checked[k] && !isEqual(a[k], b[k])) {
+ return false;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Class.extend({
- Mixins: [Observable],
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Class.extend({
+ Mixins: [Observable],
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a new observable object instance.
- *
- * @constructor
- * @param {Object} data Initial data for the object.
- */
- init: function(data) {
- var name, value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a new observable object instance.
+ *
+ * @constructor
+ * @param {Object} data Initial data for the object.
+ */
+ init: function (data) {
+ var name, value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- data = data || {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ data = data || {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (name in data) {
- value = data[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (name in data) {
+ value = data[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value instanceof Binding) {
- data[name] = value.create(this, name);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value instanceof Binding) {
+ data[name] = value.create(this, name);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.data = data;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.data = data;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets a property on the value this will call
- * observers if the value is a change from the current value.
- *
- * @method set
- * @param {String/object} name Name of the property to set or a object of items to set.
- * @param {Object} value Value to set for the property.
- * @return {tinymce.data.ObservableObject} Observable object instance.
- */
- set: function(name, value) {
- var key, args, oldValue = this.data[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets a property on the value this will call
+ * observers if the value is a change from the current value.
+ *
+ * @method set
+ * @param {String/object} name Name of the property to set or a object of items to set.
+ * @param {Object} value Value to set for the property.
+ * @return {tinymce.data.ObservableObject} Observable object instance.
+ */
+ set: function (name, value) {
+ var key, args, oldValue = this.data[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value instanceof Binding) {
- value = value.create(this, name);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value instanceof Binding) {
+ value = value.create(this, name);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof name === "object") {
- for (key in name) {
- this.set(key, name[key]);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof name === "object") {
+ for (key in name) {
+ this.set(key, name[key]);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isEqual(oldValue, value)) {
- this.data[name] = value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isEqual(oldValue, value)) {
+ this.data[name] = value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args = {
- target: this,
- name: name,
- value: value,
- oldValue: oldValue
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args = {
+ target: this,
+ name: name,
+ value: value,
+ oldValue: oldValue
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.fire('change:' + name, args);
- this.fire('change', args);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.fire('change:' + name, args);
+ this.fire('change', args);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Gets a property by name.
- *
- * @method get
- * @param {String} name Name of the property to get.
- * @return {Object} Object value of propery.
- */
- get: function(name) {
- return this.data[name];
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Gets a property by name.
+ *
+ * @method get
+ * @param {String} name Name of the property to get.
+ * @return {Object} Object value of propery.
+ */
+ get: function (name) {
+ return this.data[name];
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the specified property exists.
- *
- * @method has
- * @param {String} name Name of the property to check for.
- * @return {Boolean} true/false if the item exists.
- */
- has: function(name) {
- return name in this.data;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the specified property exists.
+ *
+ * @method has
+ * @param {String} name Name of the property to check for.
+ * @return {Boolean} true/false if the item exists.
+ */
+ has: function (name) {
+ return name in this.data;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a dynamic property binding for the specified property name. This makes
- * it possible to sync the state of two properties in two ObservableObject instances.
- *
- * @method bind
- * @param {String} name Name of the property to sync with the property it's inserted to.
- * @return {tinymce.data.Binding} Data binding instance.
- */
- bind: function(name) {
- return Binding.create(this, name);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a dynamic property binding for the specified property name. This makes
+ * it possible to sync the state of two properties in two ObservableObject instances.
+ *
+ * @method bind
+ * @param {String} name Name of the property to sync with the property it's inserted to.
+ * @return {tinymce.data.Binding} Data binding instance.
+ */
+ bind: function (name) {
+ return Binding.create(this, name);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Destroys the observable object and fires the "destroy"
- * event and clean up any internal resources.
- *
- * @method destroy
- */
- destroy: function() {
- this.fire('destroy');
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/Selector.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Destroys the observable object and fires the "destroy"
+ * event and clean up any internal resources.
+ *
+ * @method destroy
+ */
+ destroy: function () {
+ this.fire('destroy');
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Selector.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -26566,344 +30664,346 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.Selector
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Selector", [
- "tinymce/util/Class"
-], function(Class) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Selector',
+ [
+ "tinymce.core.util.Class"
+ ],
+ function (Class) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Produces an array with a unique set of objects. It will not compare the values
- * but the references of the objects.
- *
- * @private
- * @method unqiue
- * @param {Array} array Array to make into an array with unique items.
- * @return {Array} Array with unique items.
- */
- function unique(array) {
- var uniqueItems = [], i = array.length, item;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Produces an array with a unique set of objects. It will not compare the values
+ * but the references of the objects.
+ *
+ * @private
+ * @method unqiue
+ * @param {Array} array Array to make into an array with unique items.
+ * @return {Array} Array with unique items.
+ */
+ function unique(array) {
+ var uniqueItems = [], i = array.length, item;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- item = array[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ item = array[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!item.__checked) {
- uniqueItems.push(item);
- item.__checked = 1;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!item.__checked) {
+ uniqueItems.push(item);
+ item.__checked = 1;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- i = uniqueItems.length;
- while (i--) {
- delete uniqueItems[i].__checked;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ i = uniqueItems.length;
+ while (i--) {
+ delete uniqueItems[i].__checked;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return uniqueItems;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return uniqueItems;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var expression = /^([\w\\*]+)?(?:#([\w\-\\]+))?(?:\.([\w\\\.]+))?(?:\[\@?([\w\\]+)([\^\$\*!~]?=)([\w\\]+)\])?(?:\:(.+))?/i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var expression = /^([\w\\*]+)?(?:#([\w\-\\]+))?(?:\.([\w\\\.]+))?(?:\[\@?([\w\\]+)([\^\$\*!~]?=)([\w\\]+)\])?(?:\:(.+))?/i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /*jshint maxlen:255 */
- /*eslint max-len:0 */
- var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
- whiteSpace = /^\s*|\s*$/g,
- Collection;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /*jshint maxlen:255 */
+ /*eslint max-len:0 */
+ var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
+ whiteSpace = /^\s*|\s*$/g,
+ Collection;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var Selector = Class.extend({
- /**
- * Constructs a new Selector instance.
- *
- * @constructor
- * @method init
- * @param {String} selector CSS like selector expression.
- */
- init: function(selector) {
- var match = this.match;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var Selector = Class.extend({
+ /**
+ * Constructs a new Selector instance.
+ *
+ * @constructor
+ * @method init
+ * @param {String} selector CSS like selector expression.
+ */
+ init: function (selector) {
+ var match = this.match;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function compileNameFilter(name) {
- if (name) {
- name = name.toLowerCase();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function compileNameFilter(name) {
+ if (name) {
+ name = name.toLowerCase();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function(item) {
- return name === '*' || item.type === name;
- };
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function (item) {
+ return name === '*' || item.type === name;
+ };
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function compileIdFilter(id) {
- if (id) {
- return function(item) {
- return item._name === id;
- };
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function compileIdFilter(id) {
+ if (id) {
+ return function (item) {
+ return item._name === id;
+ };
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function compileClassesFilter(classes) {
- if (classes) {
- classes = classes.split('.');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function compileClassesFilter(classes) {
+ if (classes) {
+ classes = classes.split('.');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function(item) {
- var i = classes.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function (item) {
+ var i = classes.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- if (!item.classes.contains(classes[i])) {
- return false;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ if (!item.classes.contains(classes[i])) {
+ return false;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- };
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ };
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function compileAttrFilter(name, cmp, check) {
- if (name) {
- return function(item) {
- var value = item[name] ? item[name]() : '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function compileAttrFilter(name, cmp, check) {
+ if (name) {
+ return function (item) {
+ var value = item[name] ? item[name]() : '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return !cmp ? !!check :
- cmp === "=" ? value === check :
- cmp === "*=" ? value.indexOf(check) >= 0 :
- cmp === "~=" ? (" " + value + " ").indexOf(" " + check + " ") >= 0 :
- cmp === "!=" ? value != check :
- cmp === "^=" ? value.indexOf(check) === 0 :
- cmp === "$=" ? value.substr(value.length - check.length) === check :
- false;
- };
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return !cmp ? !!check :
+ cmp === "=" ? value === check :
+ cmp === "*=" ? value.indexOf(check) >= 0 :
+ cmp === "~=" ? (" " + value + " ").indexOf(" " + check + " ") >= 0 :
+ cmp === "!=" ? value != check :
+ cmp === "^=" ? value.indexOf(check) === 0 :
+ cmp === "$=" ? value.substr(value.length - check.length) === check :
+ false;
+ };
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function compilePsuedoFilter(name) {
- var notSelectors;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function compilePsuedoFilter(name) {
+ var notSelectors;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name) {
- name = /(?:not\((.+)\))|(.+)/i.exec(name);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name) {
+ name = /(?:not\((.+)\))|(.+)/i.exec(name);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!name[1]) {
- name = name[2];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!name[1]) {
+ name = name[2];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function(item, index, length) {
- return name === 'first' ? index === 0 :
- name === 'last' ? index === length - 1 :
- name === 'even' ? index % 2 === 0 :
- name === 'odd' ? index % 2 === 1 :
- item[name] ? item[name]() :
- false;
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function (item, index, length) {
+ return name === 'first' ? index === 0 :
+ name === 'last' ? index === length - 1 :
+ name === 'even' ? index % 2 === 0 :
+ name === 'odd' ? index % 2 === 1 :
+ item[name] ? item[name]() :
+ false;
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Compile not expression
- notSelectors = parseChunks(name[1], []);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Compile not expression
+ notSelectors = parseChunks(name[1], []);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function(item) {
- return !match(item, notSelectors);
- };
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function (item) {
+ return !match(item, notSelectors);
+ };
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function compile(selector, filters, direct) {
- var parts;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function compile(selector, filters, direct) {
+ var parts;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function add(filter) {
- if (filter) {
- filters.push(filter);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function add(filter) {
+ if (filter) {
+ filters.push(filter);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Parse expression into parts
- parts = expression.exec(selector.replace(whiteSpace, ''));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Parse expression into parts
+ parts = expression.exec(selector.replace(whiteSpace, ''));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- add(compileNameFilter(parts[1]));
- add(compileIdFilter(parts[2]));
- add(compileClassesFilter(parts[3]));
- add(compileAttrFilter(parts[4], parts[5], parts[6]));
- add(compilePsuedoFilter(parts[7]));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ add(compileNameFilter(parts[1]));
+ add(compileIdFilter(parts[2]));
+ add(compileClassesFilter(parts[3]));
+ add(compileAttrFilter(parts[4], parts[5], parts[6]));
+ add(compilePsuedoFilter(parts[7]));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Mark the filter with pseudo for performance
- filters.pseudo = !!parts[7];
- filters.direct = direct;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Mark the filter with pseudo for performance
+ filters.pseudo = !!parts[7];
+ filters.direct = direct;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return filters;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return filters;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Parser logic based on Sizzle by John Resig
- function parseChunks(selector, selectors) {
- var parts = [], extra, matches, i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Parser logic based on Sizzle by John Resig
+ function parseChunks(selector, selectors) {
+ var parts = [], extra, matches, i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- do {
- chunker.exec("");
- matches = chunker.exec(selector);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ do {
+ chunker.exec("");
+ matches = chunker.exec(selector);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (matches) {
- selector = matches[3];
- parts.push(matches[1]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (matches) {
+ selector = matches[3];
+ parts.push(matches[1]);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (matches[2]) {
- extra = matches[3];
- break;
- }
- }
- } while (matches);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (matches[2]) {
+ extra = matches[3];
+ break;
+ }
+ }
+ } while (matches);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (extra) {
- parseChunks(extra, selectors);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (extra) {
+ parseChunks(extra, selectors);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- selector = [];
- for (i = 0; i < parts.length; i++) {
- if (parts[i] != '>') {
- selector.push(compile(parts[i], [], parts[i - 1] === '>'));
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ selector = [];
+ for (i = 0; i < parts.length; i++) {
+ if (parts[i] != '>') {
+ selector.push(compile(parts[i], [], parts[i - 1] === '>'));
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- selectors.push(selector);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ selectors.push(selector);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return selectors;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return selectors;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this._selectors = parseChunks(selector, []);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this._selectors = parseChunks(selector, []);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the selector matches the specified control.
- *
- * @method match
- * @param {tinymce.ui.Control} control Control to match against the selector.
- * @param {Array} selectors Optional array of selectors, mostly used internally.
- * @return {Boolean} true/false state if the control matches or not.
- */
- match: function(control, selectors) {
- var i, l, si, sl, selector, fi, fl, filters, index, length, siblings, count, item;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the selector matches the specified control.
+ *
+ * @method match
+ * @param {tinymce.ui.Control} control Control to match against the selector.
+ * @param {Array} selectors Optional array of selectors, mostly used internally.
+ * @return {Boolean} true/false state if the control matches or not.
+ */
+ match: function (control, selectors) {
+ var i, l, si, sl, selector, fi, fl, filters, index, length, siblings, count, item;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- selectors = selectors || this._selectors;
- for (i = 0, l = selectors.length; i < l; i++) {
- selector = selectors[i];
- sl = selector.length;
- item = control;
- count = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ selectors = selectors || this._selectors;
+ for (i = 0, l = selectors.length; i < l; i++) {
+ selector = selectors[i];
+ sl = selector.length;
+ item = control;
+ count = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (si = sl - 1; si >= 0; si--) {
- filters = selector[si];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (si = sl - 1; si >= 0; si--) {
+ filters = selector[si];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (item) {
- // Find the index and length since a pseudo filter like :first needs it
- if (filters.pseudo) {
- siblings = item.parent().items();
- index = length = siblings.length;
- while (index--) {
- if (siblings[index] === item) {
- break;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (item) {
+ // Find the index and length since a pseudo filter like :first needs it
+ if (filters.pseudo) {
+ siblings = item.parent().items();
+ index = length = siblings.length;
+ while (index--) {
+ if (siblings[index] === item) {
+ break;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (fi = 0, fl = filters.length; fi < fl; fi++) {
- if (!filters[fi](item, index, length)) {
- fi = fl + 1;
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (fi = 0, fl = filters.length; fi < fl; fi++) {
+ if (!filters[fi](item, index, length)) {
+ fi = fl + 1;
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (fi === fl) {
- count++;
- break;
- } else {
- // If it didn't match the right most expression then
- // break since it's no point looking at the parents
- if (si === sl - 1) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (fi === fl) {
+ count++;
+ break;
+ } else {
+ // If it didn't match the right most expression then
+ // break since it's no point looking at the parents
+ if (si === sl - 1) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- item = item.parent();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ item = item.parent();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If we found all selectors then return true otherwise continue looking
- if (count === sl) {
- return true;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If we found all selectors then return true otherwise continue looking
+ if (count === sl) {
+ return true;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a tinymce.ui.Collection with matches of the specified selector inside the specified container.
- *
- * @method find
- * @param {tinymce.ui.Control} container Container to look for items in.
- * @return {tinymce.ui.Collection} Collection with matched elements.
- */
- find: function(container) {
- var matches = [], i, l, selectors = this._selectors;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a tinymce.ui.Collection with matches of the specified selector inside the specified container.
+ *
+ * @method find
+ * @param {tinymce.ui.Control} container Container to look for items in.
+ * @return {tinymce.ui.Collection} Collection with matched elements.
+ */
+ find: function (container) {
+ var matches = [], i, l, selectors = this._selectors;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function collect(items, selector, index) {
- var i, l, fi, fl, item, filters = selector[index];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function collect(items, selector, index) {
+ var i, l, fi, fl, item, filters = selector[index];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0, l = items.length; i < l; i++) {
- item = items[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0, l = items.length; i < l; i++) {
+ item = items[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Run each filter against the item
- for (fi = 0, fl = filters.length; fi < fl; fi++) {
- if (!filters[fi](item, i, l)) {
- fi = fl + 1;
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Run each filter against the item
+ for (fi = 0, fl = filters.length; fi < fl; fi++) {
+ if (!filters[fi](item, i, l)) {
+ fi = fl + 1;
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // All filters matched the item
- if (fi === fl) {
- // Matched item is on the last expression like: panel toolbar [button]
- if (index == selector.length - 1) {
- matches.push(item);
- } else {
- // Collect next expression type
- if (item.items) {
- collect(item.items(), selector, index + 1);
- }
- }
- } else if (filters.direct) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // All filters matched the item
+ if (fi === fl) {
+ // Matched item is on the last expression like: panel toolbar [button]
+ if (index == selector.length - 1) {
+ matches.push(item);
+ } else {
+ // Collect next expression type
+ if (item.items) {
+ collect(item.items(), selector, index + 1);
+ }
+ }
+ } else if (filters.direct) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Collect child items
- if (item.items) {
- collect(item.items(), selector, index);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Collect child items
+ if (item.items) {
+ collect(item.items(), selector, index);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (container.items) {
- for (i = 0, l = selectors.length; i < l; i++) {
- collect(container.items(), selectors[i], 0);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (container.items) {
+ for (i = 0, l = selectors.length; i < l; i++) {
+ collect(container.items(), selectors[i], 0);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Unique the matches if needed
- if (l > 1) {
- matches = unique(matches);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Unique the matches if needed
+ if (l > 1) {
+ matches = unique(matches);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Fix for circular reference
- if (!Collection) {
- // TODO: Fix me!
- Collection = Selector.Collection;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Fix for circular reference
+ if (!Collection) {
+ // TODO: Fix me!
+ Collection = Selector.Collection;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return new Collection(matches);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return new Collection(matches);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Selector;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Selector;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/Collection.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Collection.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -26918,433 +31018,434 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.Collection
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Collection", [
- "tinymce/util/Tools",
- "tinymce/ui/Selector",
- "tinymce/util/Class"
-], function(Tools, Selector, Class) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Collection',
+ [
+ "tinymce.core.util.Tools",
+ "tinymce.core.ui.Selector",
+ "tinymce.core.util.Class"
+ ],
+ function (Tools, Selector, Class) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var Collection, proto, push = Array.prototype.push, slice = Array.prototype.slice;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var Collection, proto, push = Array.prototype.push, slice = Array.prototype.slice;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- proto = {
- /**
- * Current number of contained control instances.
- *
- * @field length
- * @type Number
- */
- length: 0,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ proto = {
+ /**
+ * Current number of contained control instances.
+ *
+ * @field length
+ * @type Number
+ */
+ length: 0,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructor for the collection.
- *
- * @constructor
- * @method init
- * @param {Array} items Optional array with items to add.
- */
- init: function(items) {
- if (items) {
- this.add(items);
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructor for the collection.
+ *
+ * @constructor
+ * @method init
+ * @param {Array} items Optional array with items to add.
+ */
+ init: function (items) {
+ if (items) {
+ this.add(items);
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds new items to the control collection.
- *
- * @method add
- * @param {Array} items Array if items to add to collection.
- * @return {tinymce.ui.Collection} Current collection instance.
- */
- add: function(items) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds new items to the control collection.
+ *
+ * @method add
+ * @param {Array} items Array if items to add to collection.
+ * @return {tinymce.ui.Collection} Current collection instance.
+ */
+ add: function (items) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Force single item into array
- if (!Tools.isArray(items)) {
- if (items instanceof Collection) {
- self.add(items.toArray());
- } else {
- push.call(self, items);
- }
- } else {
- push.apply(self, items);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Force single item into array
+ if (!Tools.isArray(items)) {
+ if (items instanceof Collection) {
+ self.add(items.toArray());
+ } else {
+ push.call(self, items);
+ }
+ } else {
+ push.apply(self, items);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets the contents of the collection. This will remove any existing items
- * and replace them with the ones specified in the input array.
- *
- * @method set
- * @param {Array} items Array with items to set into the Collection.
- * @return {tinymce.ui.Collection} Collection instance.
- */
- set: function(items) {
- var self = this, len = self.length, i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets the contents of the collection. This will remove any existing items
+ * and replace them with the ones specified in the input array.
+ *
+ * @method set
+ * @param {Array} items Array with items to set into the Collection.
+ * @return {tinymce.ui.Collection} Collection instance.
+ */
+ set: function (items) {
+ var self = this, len = self.length, i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.length = 0;
- self.add(items);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.length = 0;
+ self.add(items);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove old entries
- for (i = self.length; i < len; i++) {
- delete self[i];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove old entries
+ for (i = self.length; i < len; i++) {
+ delete self[i];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Filters the collection item based on the specified selector expression or selector function.
- *
- * @method filter
- * @param {String} selector Selector expression to filter items by.
- * @return {tinymce.ui.Collection} Collection containing the filtered items.
- */
- filter: function(selector) {
- var self = this, i, l, matches = [], item, match;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Filters the collection item based on the specified selector expression or selector function.
+ *
+ * @method filter
+ * @param {String} selector Selector expression to filter items by.
+ * @return {tinymce.ui.Collection} Collection containing the filtered items.
+ */
+ filter: function (selector) {
+ var self = this, i, l, matches = [], item, match;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Compile string into selector expression
- if (typeof selector === "string") {
- selector = new Selector(selector);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Compile string into selector expression
+ if (typeof selector === "string") {
+ selector = new Selector(selector);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- match = function(item) {
- return selector.match(item);
- };
- } else {
- // Use selector as matching function
- match = selector;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ match = function (item) {
+ return selector.match(item);
+ };
+ } else {
+ // Use selector as matching function
+ match = selector;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0, l = self.length; i < l; i++) {
- item = self[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0, l = self.length; i < l; i++) {
+ item = self[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (match(item)) {
- matches.push(item);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (match(item)) {
+ matches.push(item);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return new Collection(matches);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return new Collection(matches);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Slices the items within the collection.
- *
- * @method slice
- * @param {Number} index Index to slice at.
- * @param {Number} len Optional length to slice.
- * @return {tinymce.ui.Collection} Current collection.
- */
- slice: function() {
- return new Collection(slice.apply(this, arguments));
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Slices the items within the collection.
+ *
+ * @method slice
+ * @param {Number} index Index to slice at.
+ * @param {Number} len Optional length to slice.
+ * @return {tinymce.ui.Collection} Current collection.
+ */
+ slice: function () {
+ return new Collection(slice.apply(this, arguments));
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Makes the current collection equal to the specified index.
- *
- * @method eq
- * @param {Number} index Index of the item to set the collection to.
- * @return {tinymce.ui.Collection} Current collection.
- */
- eq: function(index) {
- return index === -1 ? this.slice(index) : this.slice(index, +index + 1);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Makes the current collection equal to the specified index.
+ *
+ * @method eq
+ * @param {Number} index Index of the item to set the collection to.
+ * @return {tinymce.ui.Collection} Current collection.
+ */
+ eq: function (index) {
+ return index === -1 ? this.slice(index) : this.slice(index, +index + 1);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Executes the specified callback on each item in collection.
- *
- * @method each
- * @param {function} callback Callback to execute for each item in collection.
- * @return {tinymce.ui.Collection} Current collection instance.
- */
- each: function(callback) {
- Tools.each(this, callback);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Executes the specified callback on each item in collection.
+ *
+ * @method each
+ * @param {function} callback Callback to execute for each item in collection.
+ * @return {tinymce.ui.Collection} Current collection instance.
+ */
+ each: function (callback) {
+ Tools.each(this, callback);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns an JavaScript array object of the contents inside the collection.
- *
- * @method toArray
- * @return {Array} Array with all items from collection.
- */
- toArray: function() {
- return Tools.toArray(this);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns an JavaScript array object of the contents inside the collection.
+ *
+ * @method toArray
+ * @return {Array} Array with all items from collection.
+ */
+ toArray: function () {
+ return Tools.toArray(this);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Finds the index of the specified control or return -1 if it isn't in the collection.
- *
- * @method indexOf
- * @param {Control} ctrl Control instance to look for.
- * @return {Number} Index of the specified control or -1.
- */
- indexOf: function(ctrl) {
- var self = this, i = self.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Finds the index of the specified control or return -1 if it isn't in the collection.
+ *
+ * @method indexOf
+ * @param {Control} ctrl Control instance to look for.
+ * @return {Number} Index of the specified control or -1.
+ */
+ indexOf: function (ctrl) {
+ var self = this, i = self.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- if (self[i] === ctrl) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ if (self[i] === ctrl) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return i;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return i;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a new collection of the contents in reverse order.
- *
- * @method reverse
- * @return {tinymce.ui.Collection} Collection instance with reversed items.
- */
- reverse: function() {
- return new Collection(Tools.toArray(this).reverse());
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a new collection of the contents in reverse order.
+ *
+ * @method reverse
+ * @return {tinymce.ui.Collection} Collection instance with reversed items.
+ */
+ reverse: function () {
+ return new Collection(Tools.toArray(this).reverse());
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the class exists or not.
- *
- * @method hasClass
- * @param {String} cls Class to check for.
- * @return {Boolean} true/false state if the class exists or not.
- */
- hasClass: function(cls) {
- return this[0] ? this[0].classes.contains(cls) : false;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the class exists or not.
+ *
+ * @method hasClass
+ * @param {String} cls Class to check for.
+ * @return {Boolean} true/false state if the class exists or not.
+ */
+ hasClass: function (cls) {
+ return this[0] ? this[0].classes.contains(cls) : false;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets/gets the specific property on the items in the collection. The same as executing control.<property>(<value>);
- *
- * @method prop
- * @param {String} name Property name to get/set.
- * @param {Object} value Optional object value to set.
- * @return {tinymce.ui.Collection} Current collection instance or value of the first item on a get operation.
- */
- prop: function(name, value) {
- var self = this, undef, item;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets/gets the specific property on the items in the collection. The same as executing control.<property>(<value>);
+ *
+ * @method prop
+ * @param {String} name Property name to get/set.
+ * @param {Object} value Optional object value to set.
+ * @return {tinymce.ui.Collection} Current collection instance or value of the first item on a get operation.
+ */
+ prop: function (name, value) {
+ var self = this, undef, item;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value !== undef) {
- self.each(function(item) {
- if (item[name]) {
- item[name](value);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value !== undef) {
+ self.each(function (item) {
+ if (item[name]) {
+ item[name](value);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- item = self[0];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ item = self[0];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (item && item[name]) {
- return item[name]();
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (item && item[name]) {
+ return item[name]();
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Executes the specific function name with optional arguments an all items in collection if it exists.
- *
- * @example collection.exec("myMethod", arg1, arg2, arg3);
- * @method exec
- * @param {String} name Name of the function to execute.
- * @param {Object} ... Multiple arguments to pass to each function.
- * @return {tinymce.ui.Collection} Current collection.
- */
- exec: function(name) {
- var self = this, args = Tools.toArray(arguments).slice(1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Executes the specific function name with optional arguments an all items in collection if it exists.
+ *
+ * @example collection.exec("myMethod", arg1, arg2, arg3);
+ * @method exec
+ * @param {String} name Name of the function to execute.
+ * @param {Object} ... Multiple arguments to pass to each function.
+ * @return {tinymce.ui.Collection} Current collection.
+ */
+ exec: function (name) {
+ var self = this, args = Tools.toArray(arguments).slice(1);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.each(function(item) {
- if (item[name]) {
- item[name].apply(item, args);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.each(function (item) {
+ if (item[name]) {
+ item[name].apply(item, args);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Remove all items from collection and DOM.
- *
- * @method remove
- * @return {tinymce.ui.Collection} Current collection.
- */
- remove: function() {
- var i = this.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Remove all items from collection and DOM.
+ *
+ * @method remove
+ * @return {tinymce.ui.Collection} Current collection.
+ */
+ remove: function () {
+ var i = this.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- this[i].remove();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ this[i].remove();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds a class to all items in the collection.
- *
- * @method addClass
- * @param {String} cls Class to add to each item.
- * @return {tinymce.ui.Collection} Current collection instance.
- */
- addClass: function(cls) {
- return this.each(function(item) {
- item.classes.add(cls);
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds a class to all items in the collection.
+ *
+ * @method addClass
+ * @param {String} cls Class to add to each item.
+ * @return {tinymce.ui.Collection} Current collection instance.
+ */
+ addClass: function (cls) {
+ return this.each(function (item) {
+ item.classes.add(cls);
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes the specified class from all items in collection.
- *
- * @method removeClass
- * @param {String} cls Class to remove from each item.
- * @return {tinymce.ui.Collection} Current collection instance.
- */
- removeClass: function(cls) {
- return this.each(function(item) {
- item.classes.remove(cls);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes the specified class from all items in collection.
+ *
+ * @method removeClass
+ * @param {String} cls Class to remove from each item.
+ * @return {tinymce.ui.Collection} Current collection instance.
+ */
+ removeClass: function (cls) {
+ return this.each(function (item) {
+ item.classes.remove(cls);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Fires the specified event by name and arguments on the control. This will execute all
- * bound event handlers.
- *
- * @method fire
- * @param {String} name Name of the event to fire.
- * @param {Object} args Optional arguments to pass to the event.
- * @return {tinymce.ui.Collection} Current collection instance.
- */
- // fire: function(event, args) {}, -- Generated by code below
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Fires the specified event by name and arguments on the control. This will execute all
+ * bound event handlers.
+ *
+ * @method fire
+ * @param {String} name Name of the event to fire.
+ * @param {Object} args Optional arguments to pass to the event.
+ * @return {tinymce.ui.Collection} Current collection instance.
+ */
+ // fire: function(event, args) {}, -- Generated by code below
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Binds a callback to the specified event. This event can both be
- * native browser events like "click" or custom ones like PostRender.
- *
- * The callback function will have two parameters the first one being the control that received the event
- * the second one will be the event object either the browsers native event object or a custom JS object.
- *
- * @method on
- * @param {String} name Name of the event to bind. For example "click".
- * @param {String/function} callback Callback function to execute ones the event occurs.
- * @return {tinymce.ui.Collection} Current collection instance.
- */
- // on: function(name, callback) {}, -- Generated by code below
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Binds a callback to the specified event. This event can both be
+ * native browser events like "click" or custom ones like PostRender.
+ *
+ * The callback function will have two parameters the first one being the control that received the event
+ * the second one will be the event object either the browsers native event object or a custom JS object.
+ *
+ * @method on
+ * @param {String} name Name of the event to bind. For example "click".
+ * @param {String/function} callback Callback function to execute ones the event occurs.
+ * @return {tinymce.ui.Collection} Current collection instance.
+ */
+ // on: function(name, callback) {}, -- Generated by code below
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Unbinds the specified event and optionally a specific callback. If you omit the name
- * parameter all event handlers will be removed. If you omit the callback all event handles
- * by the specified name will be removed.
- *
- * @method off
- * @param {String} name Optional name for the event to unbind.
- * @param {function} callback Optional callback function to unbind.
- * @return {tinymce.ui.Collection} Current collection instance.
- */
- // off: function(name, callback) {}, -- Generated by code below
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Unbinds the specified event and optionally a specific callback. If you omit the name
+ * parameter all event handlers will be removed. If you omit the callback all event handles
+ * by the specified name will be removed.
+ *
+ * @method off
+ * @param {String} name Optional name for the event to unbind.
+ * @param {function} callback Optional callback function to unbind.
+ * @return {tinymce.ui.Collection} Current collection instance.
+ */
+ // off: function(name, callback) {}, -- Generated by code below
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Shows the items in the current collection.
- *
- * @method show
- * @return {tinymce.ui.Collection} Current collection instance.
- */
- // show: function() {}, -- Generated by code below
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Shows the items in the current collection.
+ *
+ * @method show
+ * @return {tinymce.ui.Collection} Current collection instance.
+ */
+ // show: function() {}, -- Generated by code below
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Hides the items in the current collection.
- *
- * @method hide
- * @return {tinymce.ui.Collection} Current collection instance.
- */
- // hide: function() {}, -- Generated by code below
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Hides the items in the current collection.
+ *
+ * @method hide
+ * @return {tinymce.ui.Collection} Current collection instance.
+ */
+ // hide: function() {}, -- Generated by code below
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets/gets the text contents of the items in the current collection.
- *
- * @method text
- * @return {tinymce.ui.Collection} Current collection instance or text value of the first item on a get operation.
- */
- // text: function(value) {}, -- Generated by code below
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets/gets the text contents of the items in the current collection.
+ *
+ * @method text
+ * @return {tinymce.ui.Collection} Current collection instance or text value of the first item on a get operation.
+ */
+ // text: function(value) {}, -- Generated by code below
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets/gets the name contents of the items in the current collection.
- *
- * @method name
- * @return {tinymce.ui.Collection} Current collection instance or name value of the first item on a get operation.
- */
- // name: function(value) {}, -- Generated by code below
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets/gets the name contents of the items in the current collection.
+ *
+ * @method name
+ * @return {tinymce.ui.Collection} Current collection instance or name value of the first item on a get operation.
+ */
+ // name: function(value) {}, -- Generated by code below
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets/gets the disabled state on the items in the current collection.
- *
- * @method disabled
- * @return {tinymce.ui.Collection} Current collection instance or disabled state of the first item on a get operation.
- */
- // disabled: function(state) {}, -- Generated by code below
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets/gets the disabled state on the items in the current collection.
+ *
+ * @method disabled
+ * @return {tinymce.ui.Collection} Current collection instance or disabled state of the first item on a get operation.
+ */
+ // disabled: function(state) {}, -- Generated by code below
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets/gets the active state on the items in the current collection.
- *
- * @method active
- * @return {tinymce.ui.Collection} Current collection instance or active state of the first item on a get operation.
- */
- // active: function(state) {}, -- Generated by code below
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets/gets the active state on the items in the current collection.
+ *
+ * @method active
+ * @return {tinymce.ui.Collection} Current collection instance or active state of the first item on a get operation.
+ */
+ // active: function(state) {}, -- Generated by code below
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets/gets the selected state on the items in the current collection.
- *
- * @method selected
- * @return {tinymce.ui.Collection} Current collection instance or selected state of the first item on a get operation.
- */
- // selected: function(state) {}, -- Generated by code below
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets/gets the selected state on the items in the current collection.
+ *
+ * @method selected
+ * @return {tinymce.ui.Collection} Current collection instance or selected state of the first item on a get operation.
+ */
+ // selected: function(state) {}, -- Generated by code below
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets/gets the selected state on the items in the current collection.
- *
- * @method visible
- * @return {tinymce.ui.Collection} Current collection instance or visible state of the first item on a get operation.
- */
- // visible: function(state) {}, -- Generated by code below
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets/gets the selected state on the items in the current collection.
+ *
+ * @method visible
+ * @return {tinymce.ui.Collection} Current collection instance or visible state of the first item on a get operation.
+ */
+ // visible: function(state) {}, -- Generated by code below
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Extend tinymce.ui.Collection prototype with some generated control specific methods
- Tools.each('fire on off show hide append prepend before after reflow'.split(' '), function(name) {
- proto[name] = function() {
- var args = Tools.toArray(arguments);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Extend tinymce.ui.Collection prototype with some generated control specific methods
+ Tools.each('fire on off show hide append prepend before after reflow'.split(' '), function (name) {
+ proto[name] = function () {
+ var args = Tools.toArray(arguments);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.each(function(ctrl) {
- if (name in ctrl) {
- ctrl[name].apply(ctrl, args);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.each(function (ctrl) {
+ if (name in ctrl) {
+ ctrl[name].apply(ctrl, args);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- };
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ };
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Extend tinymce.ui.Collection prototype with some property methods
- Tools.each('text name disabled active selected checked visible parent value data'.split(' '), function(name) {
- proto[name] = function(value) {
- return this.prop(name, value);
- };
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Extend tinymce.ui.Collection prototype with some property methods
+ Tools.each('text name disabled active selected checked visible parent value data'.split(' '), function (name) {
+ proto[name] = function (value) {
+ return this.prop(name, value);
+ };
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Create class based on the new prototype
- Collection = Class.extend(proto);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Create class based on the new prototype
+ Collection = Class.extend(proto);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Stick Collection into Selector to prevent circual references
- Selector.Collection = Collection;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Stick Collection into Selector to prevent circual references
+ Selector.Collection = Collection;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Collection;
-});
-
-// Included from: js/tinymce/classes/ui/DomUtils.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Collection;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * DomUtils.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -27356,130 +31457,131 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.DomUtils
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/DomUtils", [
- "tinymce/Env",
- "tinymce/util/Tools",
- "tinymce/dom/DOMUtils"
-], function(Env, Tools, DOMUtils) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.DomUtils',
+ [
+ "tinymce.core.Env",
+ "tinymce.core.util.Tools",
+ "tinymce.core.dom.DOMUtils"
+ ],
+ function (Env, Tools, DOMUtils) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var count = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var count = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var funcs = {
- id: function() {
- return 'mceu_' + (count++);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var funcs = {
+ id: function () {
+ return 'mceu_' + (count++);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- create: function(name, attrs, children) {
- var elm = document.createElement(name);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ create: function (name, attrs, children) {
+ var elm = document.createElement(name);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DOMUtils.DOM.setAttribs(elm, attrs);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOMUtils.DOM.setAttribs(elm, attrs);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof children === 'string') {
- elm.innerHTML = children;
- } else {
- Tools.each(children, function(child) {
- if (child.nodeType) {
- elm.appendChild(child);
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof children === 'string') {
+ elm.innerHTML = children;
+ } else {
+ Tools.each(children, function (child) {
+ if (child.nodeType) {
+ elm.appendChild(child);
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return elm;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return elm;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- createFragment: function(html) {
- return DOMUtils.DOM.createFragment(html);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ createFragment: function (html) {
+ return DOMUtils.DOM.createFragment(html);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- getWindowSize: function() {
- return DOMUtils.DOM.getViewPort();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ getWindowSize: function () {
+ return DOMUtils.DOM.getViewPort();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- getSize: function(elm) {
- var width, height;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ getSize: function (elm) {
+ var width, height;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elm.getBoundingClientRect) {
- var rect = elm.getBoundingClientRect();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (elm.getBoundingClientRect) {
+ var rect = elm.getBoundingClientRect();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- width = Math.max(rect.width || (rect.right - rect.left), elm.offsetWidth);
- height = Math.max(rect.height || (rect.bottom - rect.bottom), elm.offsetHeight);
- } else {
- width = elm.offsetWidth;
- height = elm.offsetHeight;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ width = Math.max(rect.width || (rect.right - rect.left), elm.offsetWidth);
+ height = Math.max(rect.height || (rect.bottom - rect.bottom), elm.offsetHeight);
+ } else {
+ width = elm.offsetWidth;
+ height = elm.offsetHeight;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {width: width, height: height};
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return { width: width, height: height };
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- getPos: function(elm, root) {
- return DOMUtils.DOM.getPos(elm, root || funcs.getContainer());
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ getPos: function (elm, root) {
+ return DOMUtils.DOM.getPos(elm, root || funcs.getContainer());
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- getContainer: function () {
- return Env.container ? Env.container : document.body;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ getContainer: function () {
+ return Env.container ? Env.container : document.body;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- getViewPort: function(win) {
- return DOMUtils.DOM.getViewPort(win);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ getViewPort: function (win) {
+ return DOMUtils.DOM.getViewPort(win);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- get: function(id) {
- return document.getElementById(id);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ get: function (id) {
+ return document.getElementById(id);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- addClass: function(elm, cls) {
- return DOMUtils.DOM.addClass(elm, cls);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ addClass: function (elm, cls) {
+ return DOMUtils.DOM.addClass(elm, cls);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- removeClass: function(elm, cls) {
- return DOMUtils.DOM.removeClass(elm, cls);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ removeClass: function (elm, cls) {
+ return DOMUtils.DOM.removeClass(elm, cls);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- hasClass: function(elm, cls) {
- return DOMUtils.DOM.hasClass(elm, cls);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ hasClass: function (elm, cls) {
+ return DOMUtils.DOM.hasClass(elm, cls);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- toggleClass: function(elm, cls, state) {
- return DOMUtils.DOM.toggleClass(elm, cls, state);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ toggleClass: function (elm, cls, state) {
+ return DOMUtils.DOM.toggleClass(elm, cls, state);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- css: function(elm, name, value) {
- return DOMUtils.DOM.setStyle(elm, name, value);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ css: function (elm, name, value) {
+ return DOMUtils.DOM.setStyle(elm, name, value);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- getRuntimeStyle: function(elm, name) {
- return DOMUtils.DOM.getStyle(elm, name, true);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ getRuntimeStyle: function (elm, name) {
+ return DOMUtils.DOM.getStyle(elm, name, true);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- on: function(target, name, callback, scope) {
- return DOMUtils.DOM.bind(target, name, callback, scope);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ on: function (target, name, callback, scope) {
+ return DOMUtils.DOM.bind(target, name, callback, scope);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- off: function(target, name, callback) {
- return DOMUtils.DOM.unbind(target, name, callback);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ off: function (target, name, callback) {
+ return DOMUtils.DOM.unbind(target, name, callback);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- fire: function(target, name, args) {
- return DOMUtils.DOM.fire(target, name, args);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ fire: function (target, name, args) {
+ return DOMUtils.DOM.fire(target, name, args);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- innerHtml: function(elm, html) {
- // Workaround for <div> in <p> bug on IE 8 #6178
- DOMUtils.DOM.setHTML(elm, html);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ innerHtml: function (elm, html) {
+ // Workaround for <div> in <p> bug on IE 8 #6178
+ DOMUtils.DOM.setHTML(elm, html);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return funcs;
-});
-
-// Included from: js/tinymce/classes/ui/BoxUtils.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return funcs;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * BoxUtils.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -27491,96 +31593,98 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.BoxUtils
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/BoxUtils", [
-], function() {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.BoxUtils',
+ [
+ ],
+ function () {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- /**
- * Parses the specified box value. A box value contains 1-4 properties in clockwise order.
- *
- * @method parseBox
- * @param {String/Number} value Box value "0 1 2 3" or "0" etc.
- * @return {Object} Object with top/right/bottom/left properties.
- * @private
- */
- parseBox: function(value) {
- var len, radix = 10;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ /**
+ * Parses the specified box value. A box value contains 1-4 properties in clockwise order.
+ *
+ * @method parseBox
+ * @param {String/Number} value Box value "0 1 2 3" or "0" etc.
+ * @return {Object} Object with top/right/bottom/left properties.
+ * @private
+ */
+ parseBox: function (value) {
+ var len, radix = 10;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!value) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!value) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof value === "number") {
- value = value || 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof value === "number") {
+ value = value || 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- top: value,
- left: value,
- bottom: value,
- right: value
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ top: value,
+ left: value,
+ bottom: value,
+ right: value
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- value = value.split(' ');
- len = value.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ value = value.split(' ');
+ len = value.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (len === 1) {
- value[1] = value[2] = value[3] = value[0];
- } else if (len === 2) {
- value[2] = value[0];
- value[3] = value[1];
- } else if (len === 3) {
- value[3] = value[1];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (len === 1) {
+ value[1] = value[2] = value[3] = value[0];
+ } else if (len === 2) {
+ value[2] = value[0];
+ value[3] = value[1];
+ } else if (len === 3) {
+ value[3] = value[1];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- top: parseInt(value[0], radix) || 0,
- right: parseInt(value[1], radix) || 0,
- bottom: parseInt(value[2], radix) || 0,
- left: parseInt(value[3], radix) || 0
- };
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ top: parseInt(value[0], radix) || 0,
+ right: parseInt(value[1], radix) || 0,
+ bottom: parseInt(value[2], radix) || 0,
+ left: parseInt(value[3], radix) || 0
+ };
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- measureBox: function(elm, prefix) {
- function getStyle(name) {
- var defaultView = document.defaultView;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ measureBox: function (elm, prefix) {
+ function getStyle(name) {
+ var defaultView = document.defaultView;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (defaultView) {
- // Remove camelcase
- name = name.replace(/[A-Z]/g, function(a) {
- return '-' + a;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (defaultView) {
+ // Remove camelcase
+ name = name.replace(/[A-Z]/g, function (a) {
+ return '-' + a;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return defaultView.getComputedStyle(elm, null).getPropertyValue(name);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return defaultView.getComputedStyle(elm, null).getPropertyValue(name);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return elm.currentStyle[name];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return elm.currentStyle[name];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getSide(name) {
- var val = parseFloat(getStyle(name), 10);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getSide(name) {
+ var val = parseFloat(getStyle(name), 10);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return isNaN(val) ? 0 : val;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return isNaN(val) ? 0 : val;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- top: getSide(prefix + "TopWidth"),
- right: getSide(prefix + "RightWidth"),
- bottom: getSide(prefix + "BottomWidth"),
- left: getSide(prefix + "LeftWidth")
- };
- }
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ top: getSide(prefix + "TopWidth"),
+ right: getSide(prefix + "RightWidth"),
+ bottom: getSide(prefix + "BottomWidth"),
+ left: getSide(prefix + "LeftWidth")
+ };
+ }
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/ClassList.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * ClassList.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -27592,147 +31696,148 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.ClassList
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/ClassList", [
- "tinymce/util/Tools"
-], function(Tools) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.ClassList',
+ [
+ "tinymce.core.util.Tools"
+ ],
+ function (Tools) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function noop() {
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function noop() {
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a new class list the specified onchange
- * callback will be executed when the class list gets modifed.
- *
- * @constructor ClassList
- * @param {function} onchange Onchange callback to be executed.
- */
- function ClassList(onchange) {
- this.cls = [];
- this.cls._map = {};
- this.onchange = onchange || noop;
- this.prefix = '';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a new class list the specified onchange
+ * callback will be executed when the class list gets modifed.
+ *
+ * @constructor ClassList
+ * @param {function} onchange Onchange callback to be executed.
+ */
+ function ClassList(onchange) {
+ this.cls = [];
+ this.cls._map = {};
+ this.onchange = onchange || noop;
+ this.prefix = '';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.extend(ClassList.prototype, {
- /**
- * Adds a new class to the class list.
- *
- * @method add
- * @param {String} cls Class to be added.
- * @return {tinymce.ui.ClassList} Current class list instance.
- */
- add: function(cls) {
- if (cls && !this.contains(cls)) {
- this.cls._map[cls] = true;
- this.cls.push(cls);
- this._change();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.extend(ClassList.prototype, {
+ /**
+ * Adds a new class to the class list.
+ *
+ * @method add
+ * @param {String} cls Class to be added.
+ * @return {tinymce.ui.ClassList} Current class list instance.
+ */
+ add: function (cls) {
+ if (cls && !this.contains(cls)) {
+ this.cls._map[cls] = true;
+ this.cls.push(cls);
+ this._change();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes the specified class from the class list.
- *
- * @method remove
- * @param {String} cls Class to be removed.
- * @return {tinymce.ui.ClassList} Current class list instance.
- */
- remove: function(cls) {
- if (this.contains(cls)) {
- for (var i = 0; i < this.cls.length; i++) {
- if (this.cls[i] === cls) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes the specified class from the class list.
+ *
+ * @method remove
+ * @param {String} cls Class to be removed.
+ * @return {tinymce.ui.ClassList} Current class list instance.
+ */
+ remove: function (cls) {
+ if (this.contains(cls)) {
+ for (var i = 0; i < this.cls.length; i++) {
+ if (this.cls[i] === cls) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.cls.splice(i, 1);
- delete this.cls._map[cls];
- this._change();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.cls.splice(i, 1);
+ delete this.cls._map[cls];
+ this._change();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Toggles a class in the class list.
- *
- * @method toggle
- * @param {String} cls Class to be added/removed.
- * @param {Boolean} state Optional state if it should be added/removed.
- * @return {tinymce.ui.ClassList} Current class list instance.
- */
- toggle: function(cls, state) {
- var curState = this.contains(cls);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Toggles a class in the class list.
+ *
+ * @method toggle
+ * @param {String} cls Class to be added/removed.
+ * @param {Boolean} state Optional state if it should be added/removed.
+ * @return {tinymce.ui.ClassList} Current class list instance.
+ */
+ toggle: function (cls, state) {
+ var curState = this.contains(cls);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (curState !== state) {
- if (curState) {
- this.remove(cls);
- } else {
- this.add(cls);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (curState !== state) {
+ if (curState) {
+ this.remove(cls);
+ } else {
+ this.add(cls);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this._change();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this._change();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true if the class list has the specified class.
- *
- * @method contains
- * @param {String} cls Class to look for.
- * @return {Boolean} true/false if the class exists or not.
- */
- contains: function(cls) {
- return !!this.cls._map[cls];
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true if the class list has the specified class.
+ *
+ * @method contains
+ * @param {String} cls Class to look for.
+ * @return {Boolean} true/false if the class exists or not.
+ */
+ contains: function (cls) {
+ return !!this.cls._map[cls];
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a space separated list of classes.
- *
- * @method toString
- * @return {String} Space separated list of classes.
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a space separated list of classes.
+ *
+ * @method toString
+ * @return {String} Space separated list of classes.
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- _change: function() {
- delete this.clsValue;
- this.onchange.call(this);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ _change: function () {
+ delete this.clsValue;
+ this.onchange.call(this);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // IE 8 compatibility
- ClassList.prototype.toString = function() {
- var value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // IE 8 compatibility
+ ClassList.prototype.toString = function () {
+ var value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.clsValue) {
- return this.clsValue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.clsValue) {
+ return this.clsValue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- value = '';
- for (var i = 0; i < this.cls.length; i++) {
- if (i > 0) {
- value += ' ';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ value = '';
+ for (var i = 0; i < this.cls.length; i++) {
+ if (i > 0) {
+ value += ' ';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- value += this.prefix + this.cls[i];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ value += this.prefix + this.cls[i];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return value;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return value;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return ClassList;
-});
-
-// Included from: js/tinymce/classes/ui/ReflowQueue.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return ClassList;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * ReflowQueue.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -27746,75 +31851,77 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.ReflowQueue
</span><span class="cx" style="display: block; padding: 0 10px"> * @static
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/ReflowQueue", [
- "tinymce/util/Delay"
-], function(Delay) {
- var dirtyCtrls = {}, animationFrameRequested;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.ReflowQueue',
+ [
+ "tinymce.core.util.Delay"
+ ],
+ function (Delay) {
+ var dirtyCtrls = {}, animationFrameRequested;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- /**
- * Adds a control to the next automatic reflow call. This is the control that had a state
- * change for example if the control was hidden/shown.
- *
- * @method add
- * @param {tinymce.ui.Control} ctrl Control to add to queue.
- */
- add: function(ctrl) {
- var parent = ctrl.parent();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ /**
+ * Adds a control to the next automatic reflow call. This is the control that had a state
+ * change for example if the control was hidden/shown.
+ *
+ * @method add
+ * @param {tinymce.ui.Control} ctrl Control to add to queue.
+ */
+ add: function (ctrl) {
+ var parent = ctrl.parent();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (parent) {
- if (!parent._layout || parent._layout.isNative()) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parent) {
+ if (!parent._layout || parent._layout.isNative()) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!dirtyCtrls[parent._id]) {
- dirtyCtrls[parent._id] = parent;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!dirtyCtrls[parent._id]) {
+ dirtyCtrls[parent._id] = parent;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!animationFrameRequested) {
- animationFrameRequested = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!animationFrameRequested) {
+ animationFrameRequested = true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Delay.requestAnimationFrame(function() {
- var id, ctrl;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Delay.requestAnimationFrame(function () {
+ var id, ctrl;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- animationFrameRequested = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ animationFrameRequested = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (id in dirtyCtrls) {
- ctrl = dirtyCtrls[id];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (id in dirtyCtrls) {
+ ctrl = dirtyCtrls[id];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (ctrl.state.get('rendered')) {
- ctrl.reflow();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (ctrl.state.get('rendered')) {
+ ctrl.reflow();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dirtyCtrls = {};
- }, document.body);
- }
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dirtyCtrls = {};
+ }, document.body);
+ }
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes the specified control from the automatic reflow. This will happen when for example the user
- * manually triggers a reflow.
- *
- * @method remove
- * @param {tinymce.ui.Control} ctrl Control to remove from queue.
- */
- remove: function(ctrl) {
- if (dirtyCtrls[ctrl._id]) {
- delete dirtyCtrls[ctrl._id];
- }
- }
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes the specified control from the automatic reflow. This will happen when for example the user
+ * manually triggers a reflow.
+ *
+ * @method remove
+ * @param {tinymce.ui.Control} ctrl Control to remove from queue.
+ */
+ remove: function (ctrl) {
+ if (dirtyCtrls[ctrl._id]) {
+ delete dirtyCtrls[ctrl._id];
+ }
+ }
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/Control.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Control.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -27828,1304 +31935,1304 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.Control
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Control", [
- "tinymce/util/Class",
- "tinymce/util/Tools",
- "tinymce/util/EventDispatcher",
- "tinymce/data/ObservableObject",
- "tinymce/ui/Collection",
- "tinymce/ui/DomUtils",
- "tinymce/dom/DomQuery",
- "tinymce/ui/BoxUtils",
- "tinymce/ui/ClassList",
- "tinymce/ui/ReflowQueue"
-], function(Class, Tools, EventDispatcher, ObservableObject, Collection, DomUtils, $, BoxUtils, ClassList, ReflowQueue) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Control',
+ [
+ "tinymce.core.util.Class",
+ "tinymce.core.util.Tools",
+ "tinymce.core.util.EventDispatcher",
+ "tinymce.core.data.ObservableObject",
+ "tinymce.core.ui.Collection",
+ "tinymce.core.ui.DomUtils",
+ "tinymce.core.dom.DomQuery",
+ "tinymce.core.ui.BoxUtils",
+ "tinymce.core.ui.ClassList",
+ "tinymce.core.ui.ReflowQueue"
+ ],
+ function (Class, Tools, EventDispatcher, ObservableObject, Collection, DomUtils, $, BoxUtils, ClassList, ReflowQueue) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var hasMouseWheelEventSupport = "onmousewheel" in document;
- var hasWheelEventSupport = false;
- var classPrefix = "mce-";
- var Control, idCounter = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var hasMouseWheelEventSupport = "onmousewheel" in document;
+ var hasWheelEventSupport = false;
+ var classPrefix = "mce-";
+ var Control, idCounter = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var proto = {
- Statics: {
- classPrefix: classPrefix
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var proto = {
+ Statics: {
+ classPrefix: classPrefix
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- isRtl: function() {
- return Control.rtl;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ isRtl: function () {
+ return Control.rtl;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Class/id prefix to use for all controls.
- *
- * @final
- * @field {String} classPrefix
- */
- classPrefix: classPrefix,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Class/id prefix to use for all controls.
+ *
+ * @final
+ * @field {String} classPrefix
+ */
+ classPrefix: classPrefix,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a new control instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- * @setting {String} style Style CSS properties to add.
- * @setting {String} border Border box values example: 1 1 1 1
- * @setting {String} padding Padding box values example: 1 1 1 1
- * @setting {String} margin Margin box values example: 1 1 1 1
- * @setting {Number} minWidth Minimal width for the control.
- * @setting {Number} minHeight Minimal height for the control.
- * @setting {String} classes Space separated list of classes to add.
- * @setting {String} role WAI-ARIA role to use for control.
- * @setting {Boolean} hidden Is the control hidden by default.
- * @setting {Boolean} disabled Is the control disabled by default.
- * @setting {String} name Name of the control instance.
- */
- init: function(settings) {
- var self = this, classes, defaultClasses;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a new control instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ * @setting {String} style Style CSS properties to add.
+ * @setting {String} border Border box values example: 1 1 1 1
+ * @setting {String} padding Padding box values example: 1 1 1 1
+ * @setting {String} margin Margin box values example: 1 1 1 1
+ * @setting {Number} minWidth Minimal width for the control.
+ * @setting {Number} minHeight Minimal height for the control.
+ * @setting {String} classes Space separated list of classes to add.
+ * @setting {String} role WAI-ARIA role to use for control.
+ * @setting {Boolean} hidden Is the control hidden by default.
+ * @setting {Boolean} disabled Is the control disabled by default.
+ * @setting {String} name Name of the control instance.
+ */
+ init: function (settings) {
+ var self = this, classes, defaultClasses;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function applyClasses(classes) {
- var i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function applyClasses(classes) {
+ var i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- classes = classes.split(' ');
- for (i = 0; i < classes.length; i++) {
- self.classes.add(classes[i]);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ classes = classes.split(' ');
+ for (i = 0; i < classes.length; i++) {
+ self.classes.add(classes[i]);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.settings = settings = Tools.extend({}, self.Defaults, settings);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.settings = settings = Tools.extend({}, self.Defaults, settings);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Initial states
- self._id = settings.id || ('mceu_' + (idCounter++));
- self._aria = {role: settings.role};
- self._elmCache = {};
- self.$ = $;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Initial states
+ self._id = settings.id || ('mceu_' + (idCounter++));
+ self._aria = { role: settings.role };
+ self._elmCache = {};
+ self.$ = $;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state = new ObservableObject({
- visible: true,
- active: false,
- disabled: false,
- value: ''
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state = new ObservableObject({
+ visible: true,
+ active: false,
+ disabled: false,
+ value: ''
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.data = new ObservableObject(settings.data);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.data = new ObservableObject(settings.data);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.classes = new ClassList(function() {
- if (self.state.get('rendered')) {
- self.getEl().className = this.toString();
- }
- });
- self.classes.prefix = self.classPrefix;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.classes = new ClassList(function () {
+ if (self.state.get('rendered')) {
+ self.getEl().className = this.toString();
+ }
+ });
+ self.classes.prefix = self.classPrefix;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup classes
- classes = settings.classes;
- if (classes) {
- if (self.Defaults) {
- defaultClasses = self.Defaults.classes;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup classes
+ classes = settings.classes;
+ if (classes) {
+ if (self.Defaults) {
+ defaultClasses = self.Defaults.classes;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (defaultClasses && classes != defaultClasses) {
- applyClasses(defaultClasses);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (defaultClasses && classes != defaultClasses) {
+ applyClasses(defaultClasses);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- applyClasses(classes);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ applyClasses(classes);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each('title text name visible disabled active value'.split(' '), function(name) {
- if (name in settings) {
- self[name](settings[name]);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each('title text name visible disabled active value'.split(' '), function (name) {
+ if (name in settings) {
+ self[name](settings[name]);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('click', function() {
- if (self.disabled()) {
- return false;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('click', function () {
+ if (self.disabled()) {
+ return false;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Name/value object with settings for the current control.
- *
- * @field {Object} settings
- */
- self.settings = settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Name/value object with settings for the current control.
+ *
+ * @field {Object} settings
+ */
+ self.settings = settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.borderBox = BoxUtils.parseBox(settings.border);
- self.paddingBox = BoxUtils.parseBox(settings.padding);
- self.marginBox = BoxUtils.parseBox(settings.margin);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.borderBox = BoxUtils.parseBox(settings.border);
+ self.paddingBox = BoxUtils.parseBox(settings.padding);
+ self.marginBox = BoxUtils.parseBox(settings.margin);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.hidden) {
- self.hide();
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.hidden) {
+ self.hide();
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Will generate getter/setter methods for these properties
- Properties: 'parent,name',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Will generate getter/setter methods for these properties
+ Properties: 'parent,name',
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the root element to render controls into.
- *
- * @method getContainerElm
- * @return {Element} HTML DOM element to render into.
- */
- getContainerElm: function() {
- return DomUtils.getContainer();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the root element to render controls into.
+ *
+ * @method getContainerElm
+ * @return {Element} HTML DOM element to render into.
+ */
+ getContainerElm: function () {
+ return DomUtils.getContainer();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a control instance for the current DOM element.
- *
- * @method getParentCtrl
- * @param {Element} elm HTML dom element to get parent control from.
- * @return {tinymce.ui.Control} Control instance or undefined.
- */
- getParentCtrl: function(elm) {
- var ctrl, lookup = this.getRoot().controlIdLookup;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a control instance for the current DOM element.
+ *
+ * @method getParentCtrl
+ * @param {Element} elm HTML dom element to get parent control from.
+ * @return {tinymce.ui.Control} Control instance or undefined.
+ */
+ getParentCtrl: function (elm) {
+ var ctrl, lookup = this.getRoot().controlIdLookup;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (elm && lookup) {
- ctrl = lookup[elm.id];
- if (ctrl) {
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (elm && lookup) {
+ ctrl = lookup[elm.id];
+ if (ctrl) {
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elm = elm.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elm = elm.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return ctrl;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return ctrl;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Initializes the current controls layout rect.
- * This will be executed by the layout managers to determine the
- * default minWidth/minHeight etc.
- *
- * @method initLayoutRect
- * @return {Object} Layout rect instance.
- */
- initLayoutRect: function() {
- var self = this, settings = self.settings, borderBox, layoutRect;
- var elm = self.getEl(), width, height, minWidth, minHeight, autoResize;
- var startMinWidth, startMinHeight, initialSize;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Initializes the current controls layout rect.
+ * This will be executed by the layout managers to determine the
+ * default minWidth/minHeight etc.
+ *
+ * @method initLayoutRect
+ * @return {Object} Layout rect instance.
+ */
+ initLayoutRect: function () {
+ var self = this, settings = self.settings, borderBox, layoutRect;
+ var elm = self.getEl(), width, height, minWidth, minHeight, autoResize;
+ var startMinWidth, startMinHeight, initialSize;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Measure the current element
- borderBox = self.borderBox = self.borderBox || BoxUtils.measureBox(elm, 'border');
- self.paddingBox = self.paddingBox || BoxUtils.measureBox(elm, 'padding');
- self.marginBox = self.marginBox || BoxUtils.measureBox(elm, 'margin');
- initialSize = DomUtils.getSize(elm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Measure the current element
+ borderBox = self.borderBox = self.borderBox || BoxUtils.measureBox(elm, 'border');
+ self.paddingBox = self.paddingBox || BoxUtils.measureBox(elm, 'padding');
+ self.marginBox = self.marginBox || BoxUtils.measureBox(elm, 'margin');
+ initialSize = DomUtils.getSize(elm);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup minWidth/minHeight and width/height
- startMinWidth = settings.minWidth;
- startMinHeight = settings.minHeight;
- minWidth = startMinWidth || initialSize.width;
- minHeight = startMinHeight || initialSize.height;
- width = settings.width;
- height = settings.height;
- autoResize = settings.autoResize;
- autoResize = typeof autoResize != "undefined" ? autoResize : !width && !height;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup minWidth/minHeight and width/height
+ startMinWidth = settings.minWidth;
+ startMinHeight = settings.minHeight;
+ minWidth = startMinWidth || initialSize.width;
+ minHeight = startMinHeight || initialSize.height;
+ width = settings.width;
+ height = settings.height;
+ autoResize = settings.autoResize;
+ autoResize = typeof autoResize != "undefined" ? autoResize : !width && !height;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- width = width || minWidth;
- height = height || minHeight;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ width = width || minWidth;
+ height = height || minHeight;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var deltaW = borderBox.left + borderBox.right;
- var deltaH = borderBox.top + borderBox.bottom;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var deltaW = borderBox.left + borderBox.right;
+ var deltaH = borderBox.top + borderBox.bottom;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var maxW = settings.maxWidth || 0xFFFF;
- var maxH = settings.maxHeight || 0xFFFF;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var maxW = settings.maxWidth || 0xFFFF;
+ var maxH = settings.maxHeight || 0xFFFF;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup initial layout rect
- self._layoutRect = layoutRect = {
- x: settings.x || 0,
- y: settings.y || 0,
- w: width,
- h: height,
- deltaW: deltaW,
- deltaH: deltaH,
- contentW: width - deltaW,
- contentH: height - deltaH,
- innerW: width - deltaW,
- innerH: height - deltaH,
- startMinWidth: startMinWidth || 0,
- startMinHeight: startMinHeight || 0,
- minW: Math.min(minWidth, maxW),
- minH: Math.min(minHeight, maxH),
- maxW: maxW,
- maxH: maxH,
- autoResize: autoResize,
- scrollW: 0
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup initial layout rect
+ self._layoutRect = layoutRect = {
+ x: settings.x || 0,
+ y: settings.y || 0,
+ w: width,
+ h: height,
+ deltaW: deltaW,
+ deltaH: deltaH,
+ contentW: width - deltaW,
+ contentH: height - deltaH,
+ innerW: width - deltaW,
+ innerH: height - deltaH,
+ startMinWidth: startMinWidth || 0,
+ startMinHeight: startMinHeight || 0,
+ minW: Math.min(minWidth, maxW),
+ minH: Math.min(minHeight, maxH),
+ maxW: maxW,
+ maxH: maxH,
+ autoResize: autoResize,
+ scrollW: 0
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._lastLayoutRect = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._lastLayoutRect = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return layoutRect;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return layoutRect;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Getter/setter for the current layout rect.
- *
- * @method layoutRect
- * @param {Object} [newRect] Optional new layout rect.
- * @return {tinymce.ui.Control/Object} Current control or rect object.
- */
- layoutRect: function(newRect) {
- var self = this, curRect = self._layoutRect, lastLayoutRect, size, deltaWidth, deltaHeight, undef, repaintControls;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Getter/setter for the current layout rect.
+ *
+ * @method layoutRect
+ * @param {Object} [newRect] Optional new layout rect.
+ * @return {tinymce.ui.Control/Object} Current control or rect object.
+ */
+ layoutRect: function (newRect) {
+ var self = this, curRect = self._layoutRect, lastLayoutRect, size, deltaWidth, deltaHeight, undef, repaintControls;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Initialize default layout rect
- if (!curRect) {
- curRect = self.initLayoutRect();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Initialize default layout rect
+ if (!curRect) {
+ curRect = self.initLayoutRect();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set new rect values
- if (newRect) {
- // Calc deltas between inner and outer sizes
- deltaWidth = curRect.deltaW;
- deltaHeight = curRect.deltaH;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set new rect values
+ if (newRect) {
+ // Calc deltas between inner and outer sizes
+ deltaWidth = curRect.deltaW;
+ deltaHeight = curRect.deltaH;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set x position
- if (newRect.x !== undef) {
- curRect.x = newRect.x;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set x position
+ if (newRect.x !== undef) {
+ curRect.x = newRect.x;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set y position
- if (newRect.y !== undef) {
- curRect.y = newRect.y;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set y position
+ if (newRect.y !== undef) {
+ curRect.y = newRect.y;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set minW
- if (newRect.minW !== undef) {
- curRect.minW = newRect.minW;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set minW
+ if (newRect.minW !== undef) {
+ curRect.minW = newRect.minW;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set minH
- if (newRect.minH !== undef) {
- curRect.minH = newRect.minH;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set minH
+ if (newRect.minH !== undef) {
+ curRect.minH = newRect.minH;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set new width and calculate inner width
- size = newRect.w;
- if (size !== undef) {
- size = size < curRect.minW ? curRect.minW : size;
- size = size > curRect.maxW ? curRect.maxW : size;
- curRect.w = size;
- curRect.innerW = size - deltaWidth;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set new width and calculate inner width
+ size = newRect.w;
+ if (size !== undef) {
+ size = size < curRect.minW ? curRect.minW : size;
+ size = size > curRect.maxW ? curRect.maxW : size;
+ curRect.w = size;
+ curRect.innerW = size - deltaWidth;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set new height and calculate inner height
- size = newRect.h;
- if (size !== undef) {
- size = size < curRect.minH ? curRect.minH : size;
- size = size > curRect.maxH ? curRect.maxH : size;
- curRect.h = size;
- curRect.innerH = size - deltaHeight;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set new height and calculate inner height
+ size = newRect.h;
+ if (size !== undef) {
+ size = size < curRect.minH ? curRect.minH : size;
+ size = size > curRect.maxH ? curRect.maxH : size;
+ curRect.h = size;
+ curRect.innerH = size - deltaHeight;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set new inner width and calculate width
- size = newRect.innerW;
- if (size !== undef) {
- size = size < curRect.minW - deltaWidth ? curRect.minW - deltaWidth : size;
- size = size > curRect.maxW - deltaWidth ? curRect.maxW - deltaWidth : size;
- curRect.innerW = size;
- curRect.w = size + deltaWidth;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set new inner width and calculate width
+ size = newRect.innerW;
+ if (size !== undef) {
+ size = size < curRect.minW - deltaWidth ? curRect.minW - deltaWidth : size;
+ size = size > curRect.maxW - deltaWidth ? curRect.maxW - deltaWidth : size;
+ curRect.innerW = size;
+ curRect.w = size + deltaWidth;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set new height and calculate inner height
- size = newRect.innerH;
- if (size !== undef) {
- size = size < curRect.minH - deltaHeight ? curRect.minH - deltaHeight : size;
- size = size > curRect.maxH - deltaHeight ? curRect.maxH - deltaHeight : size;
- curRect.innerH = size;
- curRect.h = size + deltaHeight;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set new height and calculate inner height
+ size = newRect.innerH;
+ if (size !== undef) {
+ size = size < curRect.minH - deltaHeight ? curRect.minH - deltaHeight : size;
+ size = size > curRect.maxH - deltaHeight ? curRect.maxH - deltaHeight : size;
+ curRect.innerH = size;
+ curRect.h = size + deltaHeight;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set new contentW
- if (newRect.contentW !== undef) {
- curRect.contentW = newRect.contentW;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set new contentW
+ if (newRect.contentW !== undef) {
+ curRect.contentW = newRect.contentW;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set new contentH
- if (newRect.contentH !== undef) {
- curRect.contentH = newRect.contentH;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set new contentH
+ if (newRect.contentH !== undef) {
+ curRect.contentH = newRect.contentH;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Compare last layout rect with the current one to see if we need to repaint or not
- lastLayoutRect = self._lastLayoutRect;
- if (lastLayoutRect.x !== curRect.x || lastLayoutRect.y !== curRect.y ||
- lastLayoutRect.w !== curRect.w || lastLayoutRect.h !== curRect.h) {
- repaintControls = Control.repaintControls;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Compare last layout rect with the current one to see if we need to repaint or not
+ lastLayoutRect = self._lastLayoutRect;
+ if (lastLayoutRect.x !== curRect.x || lastLayoutRect.y !== curRect.y ||
+ lastLayoutRect.w !== curRect.w || lastLayoutRect.h !== curRect.h) {
+ repaintControls = Control.repaintControls;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (repaintControls) {
- if (repaintControls.map && !repaintControls.map[self._id]) {
- repaintControls.push(self);
- repaintControls.map[self._id] = true;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (repaintControls) {
+ if (repaintControls.map && !repaintControls.map[self._id]) {
+ repaintControls.push(self);
+ repaintControls.map[self._id] = true;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- lastLayoutRect.x = curRect.x;
- lastLayoutRect.y = curRect.y;
- lastLayoutRect.w = curRect.w;
- lastLayoutRect.h = curRect.h;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ lastLayoutRect.x = curRect.x;
+ lastLayoutRect.y = curRect.y;
+ lastLayoutRect.w = curRect.w;
+ lastLayoutRect.h = curRect.h;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return curRect;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return curRect;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Repaints the control after a layout operation.
- *
- * @method repaint
- */
- repaint: function() {
- var self = this, style, bodyStyle, bodyElm, rect, borderBox;
- var borderW, borderH, lastRepaintRect, round, value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Repaints the control after a layout operation.
+ *
+ * @method repaint
+ */
+ repaint: function () {
+ var self = this, style, bodyStyle, bodyElm, rect, borderBox;
+ var borderW, borderH, lastRepaintRect, round, value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Use Math.round on all values on IE < 9
- round = !document.createRange ? Math.round : function(value) {
- return value;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Use Math.round on all values on IE < 9
+ round = !document.createRange ? Math.round : function (value) {
+ return value;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- style = self.getEl().style;
- rect = self._layoutRect;
- lastRepaintRect = self._lastRepaintRect || {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ style = self.getEl().style;
+ rect = self._layoutRect;
+ lastRepaintRect = self._lastRepaintRect || {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- borderBox = self.borderBox;
- borderW = borderBox.left + borderBox.right;
- borderH = borderBox.top + borderBox.bottom;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ borderBox = self.borderBox;
+ borderW = borderBox.left + borderBox.right;
+ borderH = borderBox.top + borderBox.bottom;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rect.x !== lastRepaintRect.x) {
- style.left = round(rect.x) + 'px';
- lastRepaintRect.x = rect.x;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rect.x !== lastRepaintRect.x) {
+ style.left = round(rect.x) + 'px';
+ lastRepaintRect.x = rect.x;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rect.y !== lastRepaintRect.y) {
- style.top = round(rect.y) + 'px';
- lastRepaintRect.y = rect.y;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rect.y !== lastRepaintRect.y) {
+ style.top = round(rect.y) + 'px';
+ lastRepaintRect.y = rect.y;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rect.w !== lastRepaintRect.w) {
- value = round(rect.w - borderW);
- style.width = (value >= 0 ? value : 0) + 'px';
- lastRepaintRect.w = rect.w;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rect.w !== lastRepaintRect.w) {
+ value = round(rect.w - borderW);
+ style.width = (value >= 0 ? value : 0) + 'px';
+ lastRepaintRect.w = rect.w;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rect.h !== lastRepaintRect.h) {
- value = round(rect.h - borderH);
- style.height = (value >= 0 ? value : 0) + 'px';
- lastRepaintRect.h = rect.h;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rect.h !== lastRepaintRect.h) {
+ value = round(rect.h - borderH);
+ style.height = (value >= 0 ? value : 0) + 'px';
+ lastRepaintRect.h = rect.h;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Update body if needed
- if (self._hasBody && rect.innerW !== lastRepaintRect.innerW) {
- value = round(rect.innerW);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Update body if needed
+ if (self._hasBody && rect.innerW !== lastRepaintRect.innerW) {
+ value = round(rect.innerW);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bodyElm = self.getEl('body');
- if (bodyElm) {
- bodyStyle = bodyElm.style;
- bodyStyle.width = (value >= 0 ? value : 0) + 'px';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bodyElm = self.getEl('body');
+ if (bodyElm) {
+ bodyStyle = bodyElm.style;
+ bodyStyle.width = (value >= 0 ? value : 0) + 'px';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- lastRepaintRect.innerW = rect.innerW;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ lastRepaintRect.innerW = rect.innerW;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self._hasBody && rect.innerH !== lastRepaintRect.innerH) {
- value = round(rect.innerH);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self._hasBody && rect.innerH !== lastRepaintRect.innerH) {
+ value = round(rect.innerH);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bodyElm = bodyElm || self.getEl('body');
- if (bodyElm) {
- bodyStyle = bodyStyle || bodyElm.style;
- bodyStyle.height = (value >= 0 ? value : 0) + 'px';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bodyElm = bodyElm || self.getEl('body');
+ if (bodyElm) {
+ bodyStyle = bodyStyle || bodyElm.style;
+ bodyStyle.height = (value >= 0 ? value : 0) + 'px';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- lastRepaintRect.innerH = rect.innerH;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ lastRepaintRect.innerH = rect.innerH;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._lastRepaintRect = lastRepaintRect;
- self.fire('repaint', {}, false);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._lastRepaintRect = lastRepaintRect;
+ self.fire('repaint', {}, false);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Updates the controls layout rect by re-measuing it.
- */
- updateLayoutRect: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Updates the controls layout rect by re-measuing it.
+ */
+ updateLayoutRect: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.parent()._lastRect = null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.parent()._lastRect = null;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DomUtils.css(self.getEl(), {width: '', height: ''});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DomUtils.css(self.getEl(), { width: '', height: '' });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._layoutRect = self._lastRepaintRect = self._lastLayoutRect = null;
- self.initLayoutRect();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._layoutRect = self._lastRepaintRect = self._lastLayoutRect = null;
+ self.initLayoutRect();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Binds a callback to the specified event. This event can both be
- * native browser events like "click" or custom ones like PostRender.
- *
- * The callback function will be passed a DOM event like object that enables yout do stop propagation.
- *
- * @method on
- * @param {String} name Name of the event to bind. For example "click".
- * @param {String/function} callback Callback function to execute ones the event occurs.
- * @return {tinymce.ui.Control} Current control object.
- */
- on: function(name, callback) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Binds a callback to the specified event. This event can both be
+ * native browser events like "click" or custom ones like PostRender.
+ *
+ * The callback function will be passed a DOM event like object that enables yout do stop propagation.
+ *
+ * @method on
+ * @param {String} name Name of the event to bind. For example "click".
+ * @param {String/function} callback Callback function to execute ones the event occurs.
+ * @return {tinymce.ui.Control} Current control object.
+ */
+ on: function (name, callback) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function resolveCallbackName(name) {
- var callback, scope;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function resolveCallbackName(name) {
+ var callback, scope;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof name != 'string') {
- return name;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof name != 'string') {
+ return name;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function(e) {
- if (!callback) {
- self.parentsAndSelf().each(function(ctrl) {
- var callbacks = ctrl.settings.callbacks;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function (e) {
+ if (!callback) {
+ self.parentsAndSelf().each(function (ctrl) {
+ var callbacks = ctrl.settings.callbacks;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (callbacks && (callback = callbacks[name])) {
- scope = ctrl;
- return false;
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (callbacks && (callback = callbacks[name])) {
+ scope = ctrl;
+ return false;
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!callback) {
- e.action = name;
- this.fire('execute', e);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!callback) {
+ e.action = name;
+ this.fire('execute', e);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return callback.call(scope, e);
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return callback.call(scope, e);
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- getEventDispatcher(self).on(name, resolveCallbackName(callback));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ getEventDispatcher(self).on(name, resolveCallbackName(callback));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Unbinds the specified event and optionally a specific callback. If you omit the name
- * parameter all event handlers will be removed. If you omit the callback all event handles
- * by the specified name will be removed.
- *
- * @method off
- * @param {String} [name] Name for the event to unbind.
- * @param {function} [callback] Callback function to unbind.
- * @return {tinymce.ui.Control} Current control object.
- */
- off: function(name, callback) {
- getEventDispatcher(this).off(name, callback);
- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Unbinds the specified event and optionally a specific callback. If you omit the name
+ * parameter all event handlers will be removed. If you omit the callback all event handles
+ * by the specified name will be removed.
+ *
+ * @method off
+ * @param {String} [name] Name for the event to unbind.
+ * @param {function} [callback] Callback function to unbind.
+ * @return {tinymce.ui.Control} Current control object.
+ */
+ off: function (name, callback) {
+ getEventDispatcher(this).off(name, callback);
+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Fires the specified event by name and arguments on the control. This will execute all
- * bound event handlers.
- *
- * @method fire
- * @param {String} name Name of the event to fire.
- * @param {Object} [args] Arguments to pass to the event.
- * @param {Boolean} [bubble] Value to control bubbling. Defaults to true.
- * @return {Object} Current arguments object.
- */
- fire: function(name, args, bubble) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Fires the specified event by name and arguments on the control. This will execute all
+ * bound event handlers.
+ *
+ * @method fire
+ * @param {String} name Name of the event to fire.
+ * @param {Object} [args] Arguments to pass to the event.
+ * @param {Boolean} [bubble] Value to control bubbling. Defaults to true.
+ * @return {Object} Current arguments object.
+ */
+ fire: function (name, args, bubble) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args = args || {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args = args || {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!args.control) {
- args.control = self;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!args.control) {
+ args.control = self;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args = getEventDispatcher(self).fire(name, args);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args = getEventDispatcher(self).fire(name, args);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Bubble event up to parents
- if (bubble !== false && self.parent) {
- var parent = self.parent();
- while (parent && !args.isPropagationStopped()) {
- parent.fire(name, args, false);
- parent = parent.parent();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Bubble event up to parents
+ if (bubble !== false && self.parent) {
+ var parent = self.parent();
+ while (parent && !args.isPropagationStopped()) {
+ parent.fire(name, args, false);
+ parent = parent.parent();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return args;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return args;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the specified event has any listeners.
- *
- * @method hasEventListeners
- * @param {String} name Name of the event to check for.
- * @return {Boolean} True/false state if the event has listeners.
- */
- hasEventListeners: function(name) {
- return getEventDispatcher(this).has(name);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the specified event has any listeners.
+ *
+ * @method hasEventListeners
+ * @param {String} name Name of the event to check for.
+ * @return {Boolean} True/false state if the event has listeners.
+ */
+ hasEventListeners: function (name) {
+ return getEventDispatcher(this).has(name);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a control collection with all parent controls.
- *
- * @method parents
- * @param {String} selector Optional selector expression to find parents.
- * @return {tinymce.ui.Collection} Collection with all parent controls.
- */
- parents: function(selector) {
- var self = this, ctrl, parents = new Collection();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a control collection with all parent controls.
+ *
+ * @method parents
+ * @param {String} selector Optional selector expression to find parents.
+ * @return {tinymce.ui.Collection} Collection with all parent controls.
+ */
+ parents: function (selector) {
+ var self = this, ctrl, parents = new Collection();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add each parent to collection
- for (ctrl = self.parent(); ctrl; ctrl = ctrl.parent()) {
- parents.add(ctrl);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add each parent to collection
+ for (ctrl = self.parent(); ctrl; ctrl = ctrl.parent()) {
+ parents.add(ctrl);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Filter away everything that doesn't match the selector
- if (selector) {
- parents = parents.filter(selector);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Filter away everything that doesn't match the selector
+ if (selector) {
+ parents = parents.filter(selector);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return parents;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return parents;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the current control and it's parents.
- *
- * @method parentsAndSelf
- * @param {String} selector Optional selector expression to find parents.
- * @return {tinymce.ui.Collection} Collection with all parent controls.
- */
- parentsAndSelf: function(selector) {
- return new Collection(this).add(this.parents(selector));
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the current control and it's parents.
+ *
+ * @method parentsAndSelf
+ * @param {String} selector Optional selector expression to find parents.
+ * @return {tinymce.ui.Collection} Collection with all parent controls.
+ */
+ parentsAndSelf: function (selector) {
+ return new Collection(this).add(this.parents(selector));
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the control next to the current control.
- *
- * @method next
- * @return {tinymce.ui.Control} Next control instance.
- */
- next: function() {
- var parentControls = this.parent().items();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the control next to the current control.
+ *
+ * @method next
+ * @return {tinymce.ui.Control} Next control instance.
+ */
+ next: function () {
+ var parentControls = this.parent().items();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return parentControls[parentControls.indexOf(this) + 1];
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return parentControls[parentControls.indexOf(this) + 1];
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the control previous to the current control.
- *
- * @method prev
- * @return {tinymce.ui.Control} Previous control instance.
- */
- prev: function() {
- var parentControls = this.parent().items();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the control previous to the current control.
+ *
+ * @method prev
+ * @return {tinymce.ui.Control} Previous control instance.
+ */
+ prev: function () {
+ var parentControls = this.parent().items();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return parentControls[parentControls.indexOf(this) - 1];
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return parentControls[parentControls.indexOf(this) - 1];
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets the inner HTML of the control element.
- *
- * @method innerHtml
- * @param {String} html Html string to set as inner html.
- * @return {tinymce.ui.Control} Current control object.
- */
- innerHtml: function(html) {
- this.$el.html(html);
- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets the inner HTML of the control element.
+ *
+ * @method innerHtml
+ * @param {String} html Html string to set as inner html.
+ * @return {tinymce.ui.Control} Current control object.
+ */
+ innerHtml: function (html) {
+ this.$el.html(html);
+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the control DOM element or sub element.
- *
- * @method getEl
- * @param {String} [suffix] Suffix to get element by.
- * @return {Element} HTML DOM element for the current control or it's children.
- */
- getEl: function(suffix) {
- var id = suffix ? this._id + '-' + suffix : this._id;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the control DOM element or sub element.
+ *
+ * @method getEl
+ * @param {String} [suffix] Suffix to get element by.
+ * @return {Element} HTML DOM element for the current control or it's children.
+ */
+ getEl: function (suffix) {
+ var id = suffix ? this._id + '-' + suffix : this._id;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!this._elmCache[id]) {
- this._elmCache[id] = $('#' + id)[0];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!this._elmCache[id]) {
+ this._elmCache[id] = $('#' + id)[0];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this._elmCache[id];
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this._elmCache[id];
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets the visible state to true.
- *
- * @method show
- * @return {tinymce.ui.Control} Current control instance.
- */
- show: function() {
- return this.visible(true);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets the visible state to true.
+ *
+ * @method show
+ * @return {tinymce.ui.Control} Current control instance.
+ */
+ show: function () {
+ return this.visible(true);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets the visible state to false.
- *
- * @method hide
- * @return {tinymce.ui.Control} Current control instance.
- */
- hide: function() {
- return this.visible(false);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets the visible state to false.
+ *
+ * @method hide
+ * @return {tinymce.ui.Control} Current control instance.
+ */
+ hide: function () {
+ return this.visible(false);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Focuses the current control.
- *
- * @method focus
- * @return {tinymce.ui.Control} Current control instance.
- */
- focus: function() {
- try {
- this.getEl().focus();
- } catch (ex) {
- // Ignore IE error
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Focuses the current control.
+ *
+ * @method focus
+ * @return {tinymce.ui.Control} Current control instance.
+ */
+ focus: function () {
+ try {
+ this.getEl().focus();
+ } catch (ex) {
+ // Ignore IE error
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Blurs the current control.
- *
- * @method blur
- * @return {tinymce.ui.Control} Current control instance.
- */
- blur: function() {
- this.getEl().blur();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Blurs the current control.
+ *
+ * @method blur
+ * @return {tinymce.ui.Control} Current control instance.
+ */
+ blur: function () {
+ this.getEl().blur();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets the specified aria property.
- *
- * @method aria
- * @param {String} name Name of the aria property to set.
- * @param {String} value Value of the aria property.
- * @return {tinymce.ui.Control} Current control instance.
- */
- aria: function(name, value) {
- var self = this, elm = self.getEl(self.ariaTarget);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets the specified aria property.
+ *
+ * @method aria
+ * @param {String} name Name of the aria property to set.
+ * @param {String} value Value of the aria property.
+ * @return {tinymce.ui.Control} Current control instance.
+ */
+ aria: function (name, value) {
+ var self = this, elm = self.getEl(self.ariaTarget);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof value === "undefined") {
- return self._aria[name];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof value === "undefined") {
+ return self._aria[name];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._aria[name] = value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._aria[name] = value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.state.get('rendered')) {
- elm.setAttribute(name == 'role' ? name : 'aria-' + name, value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.state.get('rendered')) {
+ elm.setAttribute(name == 'role' ? name : 'aria-' + name, value);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Encodes the specified string with HTML entities. It will also
- * translate the string to different languages.
- *
- * @method encode
- * @param {String/Object/Array} text Text to entity encode.
- * @param {Boolean} [translate=true] False if the contents shouldn't be translated.
- * @return {String} Encoded and possible traslated string.
- */
- encode: function(text, translate) {
- if (translate !== false) {
- text = this.translate(text);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Encodes the specified string with HTML entities. It will also
+ * translate the string to different languages.
+ *
+ * @method encode
+ * @param {String/Object/Array} text Text to entity encode.
+ * @param {Boolean} [translate=true] False if the contents shouldn't be translated.
+ * @return {String} Encoded and possible traslated string.
+ */
+ encode: function (text, translate) {
+ if (translate !== false) {
+ text = this.translate(text);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (text || '').replace(/[&<>"]/g, function(match) {
- return '&#' + match.charCodeAt(0) + ';';
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (text || '').replace(/[&<>"]/g, function (match) {
+ return '&#' + match.charCodeAt(0) + ';';
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the translated string.
- *
- * @method translate
- * @param {String} text Text to translate.
- * @return {String} Translated string or the same as the input.
- */
- translate: function(text) {
- return Control.translate ? Control.translate(text) : text;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the translated string.
+ *
+ * @method translate
+ * @param {String} text Text to translate.
+ * @return {String} Translated string or the same as the input.
+ */
+ translate: function (text) {
+ return Control.translate ? Control.translate(text) : text;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds items before the current control.
- *
- * @method before
- * @param {Array/tinymce.ui.Collection} items Array of items to prepend before this control.
- * @return {tinymce.ui.Control} Current control instance.
- */
- before: function(items) {
- var self = this, parent = self.parent();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds items before the current control.
+ *
+ * @method before
+ * @param {Array/tinymce.ui.Collection} items Array of items to prepend before this control.
+ * @return {tinymce.ui.Control} Current control instance.
+ */
+ before: function (items) {
+ var self = this, parent = self.parent();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (parent) {
- parent.insert(items, parent.items().indexOf(self), true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parent) {
+ parent.insert(items, parent.items().indexOf(self), true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds items after the current control.
- *
- * @method after
- * @param {Array/tinymce.ui.Collection} items Array of items to append after this control.
- * @return {tinymce.ui.Control} Current control instance.
- */
- after: function(items) {
- var self = this, parent = self.parent();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds items after the current control.
+ *
+ * @method after
+ * @param {Array/tinymce.ui.Collection} items Array of items to append after this control.
+ * @return {tinymce.ui.Control} Current control instance.
+ */
+ after: function (items) {
+ var self = this, parent = self.parent();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (parent) {
- parent.insert(items, parent.items().indexOf(self));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parent) {
+ parent.insert(items, parent.items().indexOf(self));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes the current control from DOM and from UI collections.
- *
- * @method remove
- * @return {tinymce.ui.Control} Current control instance.
- */
- remove: function() {
- var self = this, elm = self.getEl(), parent = self.parent(), newItems, i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes the current control from DOM and from UI collections.
+ *
+ * @method remove
+ * @return {tinymce.ui.Control} Current control instance.
+ */
+ remove: function () {
+ var self = this, elm = self.getEl(), parent = self.parent(), newItems, i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.items) {
- var controls = self.items().toArray();
- i = controls.length;
- while (i--) {
- controls[i].remove();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.items) {
+ var controls = self.items().toArray();
+ i = controls.length;
+ while (i--) {
+ controls[i].remove();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (parent && parent.items) {
- newItems = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parent && parent.items) {
+ newItems = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parent.items().each(function(item) {
- if (item !== self) {
- newItems.push(item);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parent.items().each(function (item) {
+ if (item !== self) {
+ newItems.push(item);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parent.items().set(newItems);
- parent._lastRect = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parent.items().set(newItems);
+ parent._lastRect = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self._eventsRoot && self._eventsRoot == self) {
- $(elm).off();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self._eventsRoot && self._eventsRoot == self) {
+ $(elm).off();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var lookup = self.getRoot().controlIdLookup;
- if (lookup) {
- delete lookup[self._id];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var lookup = self.getRoot().controlIdLookup;
+ if (lookup) {
+ delete lookup[self._id];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elm && elm.parentNode) {
- elm.parentNode.removeChild(elm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (elm && elm.parentNode) {
+ elm.parentNode.removeChild(elm);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.set('rendered', false);
- self.state.destroy();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.set('rendered', false);
+ self.state.destroy();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.fire('remove');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.fire('remove');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the control before the specified element.
- *
- * @method renderBefore
- * @param {Element} elm Element to render before.
- * @return {tinymce.ui.Control} Current control instance.
- */
- renderBefore: function(elm) {
- $(elm).before(this.renderHtml());
- this.postRender();
- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the control before the specified element.
+ *
+ * @method renderBefore
+ * @param {Element} elm Element to render before.
+ * @return {tinymce.ui.Control} Current control instance.
+ */
+ renderBefore: function (elm) {
+ $(elm).before(this.renderHtml());
+ this.postRender();
+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the control to the specified element.
- *
- * @method renderBefore
- * @param {Element} elm Element to render to.
- * @return {tinymce.ui.Control} Current control instance.
- */
- renderTo: function(elm) {
- $(elm || this.getContainerElm()).append(this.renderHtml());
- this.postRender();
- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the control to the specified element.
+ *
+ * @method renderBefore
+ * @param {Element} elm Element to render to.
+ * @return {tinymce.ui.Control} Current control instance.
+ */
+ renderTo: function (elm) {
+ $(elm || this.getContainerElm()).append(this.renderHtml());
+ this.postRender();
+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- preRender: function() {
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ preRender: function () {
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- render: function() {
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ render: function () {
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- renderHtml: function() {
- return '<div id="' + this._id + '" class="' + this.classes + '"></div>';
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ renderHtml: function () {
+ return '<div id="' + this._id + '" class="' + this.classes + '"></div>';
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Post render method. Called after the control has been rendered to the target.
- *
- * @method postRender
- * @return {tinymce.ui.Control} Current control instance.
- */
- postRender: function() {
- var self = this, settings = self.settings, elm, box, parent, name, parentEventsRoot;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Post render method. Called after the control has been rendered to the target.
+ *
+ * @method postRender
+ * @return {tinymce.ui.Control} Current control instance.
+ */
+ postRender: function () {
+ var self = this, settings = self.settings, elm, box, parent, name, parentEventsRoot;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.$el = $(self.getEl());
- self.state.set('rendered', true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.$el = $(self.getEl());
+ self.state.set('rendered', true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Bind on<event> settings
- for (name in settings) {
- if (name.indexOf("on") === 0) {
- self.on(name.substr(2), settings[name]);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Bind on<event> settings
+ for (name in settings) {
+ if (name.indexOf("on") === 0) {
+ self.on(name.substr(2), settings[name]);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self._eventsRoot) {
- for (parent = self.parent(); !parentEventsRoot && parent; parent = parent.parent()) {
- parentEventsRoot = parent._eventsRoot;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self._eventsRoot) {
+ for (parent = self.parent(); !parentEventsRoot && parent; parent = parent.parent()) {
+ parentEventsRoot = parent._eventsRoot;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (parentEventsRoot) {
- for (name in parentEventsRoot._nativeEvents) {
- self._nativeEvents[name] = true;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parentEventsRoot) {
+ for (name in parentEventsRoot._nativeEvents) {
+ self._nativeEvents[name] = true;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bindPendingEvents(self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bindPendingEvents(self);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.style) {
- elm = self.getEl();
- if (elm) {
- elm.setAttribute('style', settings.style);
- elm.style.cssText = settings.style;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.style) {
+ elm = self.getEl();
+ if (elm) {
+ elm.setAttribute('style', settings.style);
+ elm.style.cssText = settings.style;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.settings.border) {
- box = self.borderBox;
- self.$el.css({
- 'border-top-width': box.top,
- 'border-right-width': box.right,
- 'border-bottom-width': box.bottom,
- 'border-left-width': box.left
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.settings.border) {
+ box = self.borderBox;
+ self.$el.css({
+ 'border-top-width': box.top,
+ 'border-right-width': box.right,
+ 'border-bottom-width': box.bottom,
+ 'border-left-width': box.left
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add instance to lookup
- var root = self.getRoot();
- if (!root.controlIdLookup) {
- root.controlIdLookup = {};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add instance to lookup
+ var root = self.getRoot();
+ if (!root.controlIdLookup) {
+ root.controlIdLookup = {};
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- root.controlIdLookup[self._id] = self;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ root.controlIdLookup[self._id] = self;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var key in self._aria) {
- self.aria(key, self._aria[key]);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (var key in self._aria) {
+ self.aria(key, self._aria[key]);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.state.get('visible') === false) {
- self.getEl().style.display = 'none';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.state.get('visible') === false) {
+ self.getEl().style.display = 'none';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.bindStates();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.bindStates();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:visible', function(e) {
- var state = e.value, parentCtrl;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:visible', function (e) {
+ var state = e.value, parentCtrl;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.state.get('rendered')) {
- self.getEl().style.display = state === false ? 'none' : '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.state.get('rendered')) {
+ self.getEl().style.display = state === false ? 'none' : '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Need to force a reflow here on IE 8
- self.getEl().getBoundingClientRect();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Need to force a reflow here on IE 8
+ self.getEl().getBoundingClientRect();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Parent container needs to reflow
- parentCtrl = self.parent();
- if (parentCtrl) {
- parentCtrl._lastRect = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Parent container needs to reflow
+ parentCtrl = self.parent();
+ if (parentCtrl) {
+ parentCtrl._lastRect = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.fire(state ? 'show' : 'hide');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.fire(state ? 'show' : 'hide');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ReflowQueue.add(self);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ReflowQueue.add(self);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.fire('postrender', {}, false);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.fire('postrender', {}, false);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bindStates: function() {
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bindStates: function () {
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Scrolls the current control into view.
- *
- * @method scrollIntoView
- * @param {String} align Alignment in view top|center|bottom.
- * @return {tinymce.ui.Control} Current control instance.
- */
- scrollIntoView: function(align) {
- function getOffset(elm, rootElm) {
- var x, y, parent = elm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Scrolls the current control into view.
+ *
+ * @method scrollIntoView
+ * @param {String} align Alignment in view top|center|bottom.
+ * @return {tinymce.ui.Control} Current control instance.
+ */
+ scrollIntoView: function (align) {
+ function getOffset(elm, rootElm) {
+ var x, y, parent = elm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- x = y = 0;
- while (parent && parent != rootElm && parent.nodeType) {
- x += parent.offsetLeft || 0;
- y += parent.offsetTop || 0;
- parent = parent.offsetParent;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ x = y = 0;
+ while (parent && parent != rootElm && parent.nodeType) {
+ x += parent.offsetLeft || 0;
+ y += parent.offsetTop || 0;
+ parent = parent.offsetParent;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {x: x, y: y};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return { x: x, y: y };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var elm = this.getEl(), parentElm = elm.parentNode;
- var x, y, width, height, parentWidth, parentHeight;
- var pos = getOffset(elm, parentElm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var elm = this.getEl(), parentElm = elm.parentNode;
+ var x, y, width, height, parentWidth, parentHeight;
+ var pos = getOffset(elm, parentElm);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- x = pos.x;
- y = pos.y;
- width = elm.offsetWidth;
- height = elm.offsetHeight;
- parentWidth = parentElm.clientWidth;
- parentHeight = parentElm.clientHeight;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ x = pos.x;
+ y = pos.y;
+ width = elm.offsetWidth;
+ height = elm.offsetHeight;
+ parentWidth = parentElm.clientWidth;
+ parentHeight = parentElm.clientHeight;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (align == "end") {
- x -= parentWidth - width;
- y -= parentHeight - height;
- } else if (align == "center") {
- x -= (parentWidth / 2) - (width / 2);
- y -= (parentHeight / 2) - (height / 2);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (align == "end") {
+ x -= parentWidth - width;
+ y -= parentHeight - height;
+ } else if (align == "center") {
+ x -= (parentWidth / 2) - (width / 2);
+ y -= (parentHeight / 2) - (height / 2);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parentElm.scrollLeft = x;
- parentElm.scrollTop = y;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parentElm.scrollLeft = x;
+ parentElm.scrollTop = y;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- getRoot: function() {
- var ctrl = this, rootControl, parents = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ getRoot: function () {
+ var ctrl = this, rootControl, parents = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (ctrl) {
- if (ctrl.rootControl) {
- rootControl = ctrl.rootControl;
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (ctrl) {
+ if (ctrl.rootControl) {
+ rootControl = ctrl.rootControl;
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parents.push(ctrl);
- rootControl = ctrl;
- ctrl = ctrl.parent();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parents.push(ctrl);
+ rootControl = ctrl;
+ ctrl = ctrl.parent();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!rootControl) {
- rootControl = this;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!rootControl) {
+ rootControl = this;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var i = parents.length;
- while (i--) {
- parents[i].rootControl = rootControl;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var i = parents.length;
+ while (i--) {
+ parents[i].rootControl = rootControl;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return rootControl;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return rootControl;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Reflows the current control and it's parents.
- * This should be used after you for example append children to the current control so
- * that the layout managers know that they need to reposition everything.
- *
- * @example
- * container.append({type: 'button', text: 'My button'}).reflow();
- *
- * @method reflow
- * @return {tinymce.ui.Control} Current control instance.
- */
- reflow: function() {
- ReflowQueue.remove(this);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Reflows the current control and it's parents.
+ * This should be used after you for example append children to the current control so
+ * that the layout managers know that they need to reposition everything.
+ *
+ * @example
+ * container.append({type: 'button', text: 'My button'}).reflow();
+ *
+ * @method reflow
+ * @return {tinymce.ui.Control} Current control instance.
+ */
+ reflow: function () {
+ ReflowQueue.remove(this);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var parent = this.parent();
- if (parent._layout && !parent._layout.isNative()) {
- parent.reflow();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var parent = this.parent();
+ if (parent && parent._layout && !parent._layout.isNative()) {
+ parent.reflow();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets/gets the parent container for the control.
- *
- * @method parent
- * @param {tinymce.ui.Container} parent Optional parent to set.
- * @return {tinymce.ui.Control} Parent control or the current control on a set action.
- */
- // parent: function(parent) {} -- Generated
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets/gets the parent container for the control.
+ *
+ * @method parent
+ * @param {tinymce.ui.Container} parent Optional parent to set.
+ * @return {tinymce.ui.Control} Parent control or the current control on a set action.
+ */
+ // parent: function(parent) {} -- Generated
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets/gets the text for the control.
- *
- * @method text
- * @param {String} value Value to set to control.
- * @return {String/tinymce.ui.Control} Current control on a set operation or current value on a get.
- */
- // text: function(value) {} -- Generated
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets/gets the text for the control.
+ *
+ * @method text
+ * @param {String} value Value to set to control.
+ * @return {String/tinymce.ui.Control} Current control on a set operation or current value on a get.
+ */
+ // text: function(value) {} -- Generated
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets/gets the disabled state on the control.
- *
- * @method disabled
- * @param {Boolean} state Value to set to control.
- * @return {Boolean/tinymce.ui.Control} Current control on a set operation or current state on a get.
- */
- // disabled: function(state) {} -- Generated
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets/gets the disabled state on the control.
+ *
+ * @method disabled
+ * @param {Boolean} state Value to set to control.
+ * @return {Boolean/tinymce.ui.Control} Current control on a set operation or current state on a get.
+ */
+ // disabled: function(state) {} -- Generated
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets/gets the active for the control.
- *
- * @method active
- * @param {Boolean} state Value to set to control.
- * @return {Boolean/tinymce.ui.Control} Current control on a set operation or current state on a get.
- */
- // active: function(state) {} -- Generated
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets/gets the active for the control.
+ *
+ * @method active
+ * @param {Boolean} state Value to set to control.
+ * @return {Boolean/tinymce.ui.Control} Current control on a set operation or current state on a get.
+ */
+ // active: function(state) {} -- Generated
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets/gets the name for the control.
- *
- * @method name
- * @param {String} value Value to set to control.
- * @return {String/tinymce.ui.Control} Current control on a set operation or current value on a get.
- */
- // name: function(value) {} -- Generated
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets/gets the name for the control.
+ *
+ * @method name
+ * @param {String} value Value to set to control.
+ * @return {String/tinymce.ui.Control} Current control on a set operation or current value on a get.
+ */
+ // name: function(value) {} -- Generated
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets/gets the title for the control.
- *
- * @method title
- * @param {String} value Value to set to control.
- * @return {String/tinymce.ui.Control} Current control on a set operation or current value on a get.
- */
- // title: function(value) {} -- Generated
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets/gets the title for the control.
+ *
+ * @method title
+ * @param {String} value Value to set to control.
+ * @return {String/tinymce.ui.Control} Current control on a set operation or current value on a get.
+ */
+ // title: function(value) {} -- Generated
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets/gets the visible for the control.
- *
- * @method visible
- * @param {Boolean} state Value to set to control.
- * @return {Boolean/tinymce.ui.Control} Current control on a set operation or current state on a get.
- */
- // visible: function(value) {} -- Generated
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets/gets the visible for the control.
+ *
+ * @method visible
+ * @param {Boolean} state Value to set to control.
+ * @return {Boolean/tinymce.ui.Control} Current control on a set operation or current state on a get.
+ */
+ // visible: function(value) {} -- Generated
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Setup state properties.
- */
- Tools.each('text title visible disabled active value'.split(' '), function(name) {
- proto[name] = function(value) {
- if (arguments.length === 0) {
- return this.state.get(name);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Setup state properties.
+ */
+ Tools.each('text title visible disabled active value'.split(' '), function (name) {
+ proto[name] = function (value) {
+ if (arguments.length === 0) {
+ return this.state.get(name);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof value != "undefined") {
- this.state.set(name, value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof value != "undefined") {
+ this.state.set(name, value);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- };
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ };
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Control = Class.extend(proto);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Control = Class.extend(proto);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getEventDispatcher(obj) {
- if (!obj._eventDispatcher) {
- obj._eventDispatcher = new EventDispatcher({
- scope: obj,
- toggleEvent: function(name, state) {
- if (state && EventDispatcher.isNative(name)) {
- if (!obj._nativeEvents) {
- obj._nativeEvents = {};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getEventDispatcher(obj) {
+ if (!obj._eventDispatcher) {
+ obj._eventDispatcher = new EventDispatcher({
+ scope: obj,
+ toggleEvent: function (name, state) {
+ if (state && EventDispatcher.isNative(name)) {
+ if (!obj._nativeEvents) {
+ obj._nativeEvents = {};
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- obj._nativeEvents[name] = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ obj._nativeEvents[name] = true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (obj.state.get('rendered')) {
- bindPendingEvents(obj);
- }
- }
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (obj.state.get('rendered')) {
+ bindPendingEvents(obj);
+ }
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return obj._eventDispatcher;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return obj._eventDispatcher;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function bindPendingEvents(eventCtrl) {
- var i, l, parents, eventRootCtrl, nativeEvents, name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function bindPendingEvents(eventCtrl) {
+ var i, l, parents, eventRootCtrl, nativeEvents, name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function delegate(e) {
- var control = eventCtrl.getParentCtrl(e.target);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function delegate(e) {
+ var control = eventCtrl.getParentCtrl(e.target);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (control) {
- control.fire(e.type, e);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (control) {
+ control.fire(e.type, e);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function mouseLeaveHandler() {
- var ctrl = eventRootCtrl._lastHoverCtrl;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function mouseLeaveHandler() {
+ var ctrl = eventRootCtrl._lastHoverCtrl;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (ctrl) {
- ctrl.fire("mouseleave", {target: ctrl.getEl()});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (ctrl) {
+ ctrl.fire("mouseleave", { target: ctrl.getEl() });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ctrl.parents().each(function(ctrl) {
- ctrl.fire("mouseleave", {target: ctrl.getEl()});
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ctrl.parents().each(function (ctrl) {
+ ctrl.fire("mouseleave", { target: ctrl.getEl() });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- eventRootCtrl._lastHoverCtrl = null;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ eventRootCtrl._lastHoverCtrl = null;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function mouseEnterHandler(e) {
- var ctrl = eventCtrl.getParentCtrl(e.target), lastCtrl = eventRootCtrl._lastHoverCtrl, idx = 0, i, parents, lastParents;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function mouseEnterHandler(e) {
+ var ctrl = eventCtrl.getParentCtrl(e.target), lastCtrl = eventRootCtrl._lastHoverCtrl, idx = 0, i, parents, lastParents;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Over on a new control
- if (ctrl !== lastCtrl) {
- eventRootCtrl._lastHoverCtrl = ctrl;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Over on a new control
+ if (ctrl !== lastCtrl) {
+ eventRootCtrl._lastHoverCtrl = ctrl;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parents = ctrl.parents().toArray().reverse();
- parents.push(ctrl);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parents = ctrl.parents().toArray().reverse();
+ parents.push(ctrl);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (lastCtrl) {
- lastParents = lastCtrl.parents().toArray().reverse();
- lastParents.push(lastCtrl);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (lastCtrl) {
+ lastParents = lastCtrl.parents().toArray().reverse();
+ lastParents.push(lastCtrl);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (idx = 0; idx < lastParents.length; idx++) {
- if (parents[idx] !== lastParents[idx]) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (idx = 0; idx < lastParents.length; idx++) {
+ if (parents[idx] !== lastParents[idx]) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = lastParents.length - 1; i >= idx; i--) {
- lastCtrl = lastParents[i];
- lastCtrl.fire("mouseleave", {
- target: lastCtrl.getEl()
- });
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = lastParents.length - 1; i >= idx; i--) {
+ lastCtrl = lastParents[i];
+ lastCtrl.fire("mouseleave", {
+ target: lastCtrl.getEl()
+ });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = idx; i < parents.length; i++) {
- ctrl = parents[i];
- ctrl.fire("mouseenter", {
- target: ctrl.getEl()
- });
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = idx; i < parents.length; i++) {
+ ctrl = parents[i];
+ ctrl.fire("mouseenter", {
+ target: ctrl.getEl()
+ });
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function fixWheelEvent(e) {
- e.preventDefault();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function fixWheelEvent(e) {
+ e.preventDefault();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.type == "mousewheel") {
- e.deltaY = -1 / 40 * e.wheelDelta;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.type == "mousewheel") {
+ e.deltaY = -1 / 40 * e.wheelDelta;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.wheelDeltaX) {
- e.deltaX = -1 / 40 * e.wheelDeltaX;
- }
- } else {
- e.deltaX = 0;
- e.deltaY = e.detail;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.wheelDeltaX) {
+ e.deltaX = -1 / 40 * e.wheelDeltaX;
+ }
+ } else {
+ e.deltaX = 0;
+ e.deltaY = e.detail;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- e = eventCtrl.fire("wheel", e);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ e = eventCtrl.fire("wheel", e);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- nativeEvents = eventCtrl._nativeEvents;
- if (nativeEvents) {
- // Find event root element if it exists
- parents = eventCtrl.parents().toArray();
- parents.unshift(eventCtrl);
- for (i = 0, l = parents.length; !eventRootCtrl && i < l; i++) {
- eventRootCtrl = parents[i]._eventsRoot;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ nativeEvents = eventCtrl._nativeEvents;
+ if (nativeEvents) {
+ // Find event root element if it exists
+ parents = eventCtrl.parents().toArray();
+ parents.unshift(eventCtrl);
+ for (i = 0, l = parents.length; !eventRootCtrl && i < l; i++) {
+ eventRootCtrl = parents[i]._eventsRoot;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Event root wasn't found the use the root control
- if (!eventRootCtrl) {
- eventRootCtrl = parents[parents.length - 1] || eventCtrl;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Event root wasn't found the use the root control
+ if (!eventRootCtrl) {
+ eventRootCtrl = parents[parents.length - 1] || eventCtrl;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set the eventsRoot property on children that didn't have it
- eventCtrl._eventsRoot = eventRootCtrl;
- for (l = i, i = 0; i < l; i++) {
- parents[i]._eventsRoot = eventRootCtrl;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set the eventsRoot property on children that didn't have it
+ eventCtrl._eventsRoot = eventRootCtrl;
+ for (l = i, i = 0; i < l; i++) {
+ parents[i]._eventsRoot = eventRootCtrl;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var eventRootDelegates = eventRootCtrl._delegates;
- if (!eventRootDelegates) {
- eventRootDelegates = eventRootCtrl._delegates = {};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var eventRootDelegates = eventRootCtrl._delegates;
+ if (!eventRootDelegates) {
+ eventRootDelegates = eventRootCtrl._delegates = {};
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Bind native event delegates
- for (name in nativeEvents) {
- if (!nativeEvents) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Bind native event delegates
+ for (name in nativeEvents) {
+ if (!nativeEvents) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name === "wheel" && !hasWheelEventSupport) {
- if (hasMouseWheelEventSupport) {
- $(eventCtrl.getEl()).on("mousewheel", fixWheelEvent);
- } else {
- $(eventCtrl.getEl()).on("DOMMouseScroll", fixWheelEvent);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name === "wheel" && !hasWheelEventSupport) {
+ if (hasMouseWheelEventSupport) {
+ $(eventCtrl.getEl()).on("mousewheel", fixWheelEvent);
+ } else {
+ $(eventCtrl.getEl()).on("DOMMouseScroll", fixWheelEvent);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Special treatment for mousenter/mouseleave since these doesn't bubble
- if (name === "mouseenter" || name === "mouseleave") {
- // Fake mousenter/mouseleave
- if (!eventRootCtrl._hasMouseEnter) {
- $(eventRootCtrl.getEl()).on("mouseleave", mouseLeaveHandler).on("mouseover", mouseEnterHandler);
- eventRootCtrl._hasMouseEnter = 1;
- }
- } else if (!eventRootDelegates[name]) {
- $(eventRootCtrl.getEl()).on(name, delegate);
- eventRootDelegates[name] = true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Special treatment for mousenter/mouseleave since these doesn't bubble
+ if (name === "mouseenter" || name === "mouseleave") {
+ // Fake mousenter/mouseleave
+ if (!eventRootCtrl._hasMouseEnter) {
+ $(eventRootCtrl.getEl()).on("mouseleave", mouseLeaveHandler).on("mouseover", mouseEnterHandler);
+ eventRootCtrl._hasMouseEnter = 1;
+ }
+ } else if (!eventRootDelegates[name]) {
+ $(eventRootCtrl.getEl()).on(name, delegate);
+ eventRootDelegates[name] = true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove the event once it's bound
- nativeEvents[name] = false;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove the event once it's bound
+ nativeEvents[name] = false;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Control;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Control;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/Factory.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Factory.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/*global tinymce:true */
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * This class is a factory for control instances. This enables you
</span><span class="cx" style="display: block; padding: 0 10px"> * to create instances of controls without having to require the UI controls directly.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -29134,99 +33241,90 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.Factory
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Factory", [], function() {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Factory',
+ [
+ ],
+ function () {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var types = {}, namespaceInit;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var types = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- /**
- * Adds a new control instance type to the factory.
- *
- * @method add
- * @param {String} type Type name for example "button".
- * @param {function} typeClass Class type function.
- */
- add: function(type, typeClass) {
- types[type.toLowerCase()] = typeClass;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ /**
+ * Adds a new control instance type to the factory.
+ *
+ * @method add
+ * @param {String} type Type name for example "button".
+ * @param {function} typeClass Class type function.
+ */
+ add: function (type, typeClass) {
+ types[type.toLowerCase()] = typeClass;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the specified type exists or not.
- *
- * @method has
- * @param {String} type Type to look for.
- * @return {Boolean} true/false if the control by name exists.
- */
- has: function(type) {
- return !!types[type.toLowerCase()];
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the specified type exists or not.
+ *
+ * @method has
+ * @param {String} type Type to look for.
+ * @return {Boolean} true/false if the control by name exists.
+ */
+ has: function (type) {
+ return !!types[type.toLowerCase()];
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates a new control instance based on the settings provided. The instance created will be
- * based on the specified type property it can also create whole structures of components out of
- * the specified JSON object.
- *
- * @example
- * tinymce.ui.Factory.create({
- * type: 'button',
- * text: 'Hello world!'
- * });
- *
- * @method create
- * @param {Object/String} settings Name/Value object with items used to create the type.
- * @return {tinymce.ui.Control} Control instance based on the specified type.
- */
- create: function(type, settings) {
- var ControlType, name, namespace;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates a new control instance based on the settings provided. The instance created will be
+ * based on the specified type property it can also create whole structures of components out of
+ * the specified JSON object.
+ *
+ * @example
+ * tinymce.ui.Factory.create({
+ * type: 'button',
+ * text: 'Hello world!'
+ * });
+ *
+ * @method create
+ * @param {Object/String} settings Name/Value object with items used to create the type.
+ * @return {tinymce.ui.Control} Control instance based on the specified type.
+ */
+ create: function (type, settings) {
+ var ControlType;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Build type lookup
- if (!namespaceInit) {
- namespace = tinymce.ui;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If string is specified then use it as the type
+ if (typeof type == 'string') {
+ settings = settings || {};
+ settings.type = type;
+ } else {
+ settings = type;
+ type = settings.type;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (name in namespace) {
- types[name.toLowerCase()] = namespace[name];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find control type
+ type = type.toLowerCase();
+ ControlType = types[type];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- namespaceInit = true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // #if debug
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If string is specified then use it as the type
- if (typeof type == 'string') {
- settings = settings || {};
- settings.type = type;
- } else {
- settings = type;
- type = settings.type;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!ControlType) {
+ throw new Error("Could not find control by type: " + type);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Find control type
- type = type.toLowerCase();
- ControlType = types[type];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // #endif
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // #if debug
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ControlType = new ControlType(settings);
+ ControlType.type = type; // Set the type on the instance, this will be used by the Selector engine
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!ControlType) {
- throw new Error("Could not find control by type: " + type);
- }
-
- // #endif
-
- ControlType = new ControlType(settings);
- ControlType.type = type; // Set the type on the instance, this will be used by the Selector engine
-
- return ControlType;
- }
- };
-});
-
-// Included from: js/tinymce/classes/ui/KeyboardNavigation.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return ControlType;
+ }
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * KeyboardNavigation.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -29237,409 +33335,418 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.KeyboardNavigation
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/KeyboardNavigation", [
-], function() {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.KeyboardNavigation',
+ [
+ ],
+ function () {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * This class handles all keyboard navigation for WAI-ARIA support. Each root container
- * gets an instance of this class.
- *
- * @constructor
- */
- return function(settings) {
- var root = settings.root, focusedElement, focusedControl;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var hasTabstopData = function (elm) {
+ return elm.getAttribute('data-mce-tabstop') ? true : false;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isElement(node) {
- return node && node.nodeType === 1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * This class handles all keyboard navigation for WAI-ARIA support. Each root container
+ * gets an instance of this class.
+ *
+ * @constructor
+ */
+ return function (settings) {
+ var root = settings.root, focusedElement, focusedControl;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- try {
- focusedElement = document.activeElement;
- } catch (ex) {
- // IE sometimes fails to return a proper element
- focusedElement = document.body;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isElement(node) {
+ return node && node.nodeType === 1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- focusedControl = root.getParentCtrl(focusedElement);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ try {
+ focusedElement = document.activeElement;
+ } catch (ex) {
+ // IE sometimes fails to return a proper element
+ focusedElement = document.body;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the currently focused elements wai aria role of the currently
- * focused element or specified element.
- *
- * @private
- * @param {Element} elm Optional element to get role from.
- * @return {String} Role of specified element.
- */
- function getRole(elm) {
- elm = elm || focusedElement;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ focusedControl = root.getParentCtrl(focusedElement);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isElement(elm)) {
- return elm.getAttribute('role');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the currently focused elements wai aria role of the currently
+ * focused element or specified element.
+ *
+ * @private
+ * @param {Element} elm Optional element to get role from.
+ * @return {String} Role of specified element.
+ */
+ function getRole(elm) {
+ elm = elm || focusedElement;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isElement(elm)) {
+ return elm.getAttribute('role');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the wai role of the parent element of the currently
- * focused element or specified element.
- *
- * @private
- * @param {Element} elm Optional element to get parent role from.
- * @return {String} Role of the first parent that has a role.
- */
- function getParentRole(elm) {
- var role, parent = elm || focusedElement;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while ((parent = parent.parentNode)) {
- if ((role = getRole(parent))) {
- return role;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the wai role of the parent element of the currently
+ * focused element or specified element.
+ *
+ * @private
+ * @param {Element} elm Optional element to get parent role from.
+ * @return {String} Role of the first parent that has a role.
+ */
+ function getParentRole(elm) {
+ var role, parent = elm || focusedElement;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a wai aria property by name for example aria-selected.
- *
- * @private
- * @param {String} name Name of the aria property to get for example "disabled".
- * @return {String} Aria property value.
- */
- function getAriaProp(name) {
- var elm = focusedElement;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while ((parent = parent.parentNode)) {
+ if ((role = getRole(parent))) {
+ return role;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isElement(elm)) {
- return elm.getAttribute('aria-' + name);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a wai aria property by name for example aria-selected.
+ *
+ * @private
+ * @param {String} name Name of the aria property to get for example "disabled".
+ * @return {String} Aria property value.
+ */
+ function getAriaProp(name) {
+ var elm = focusedElement;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Is the element a text input element or not.
- *
- * @private
- * @param {Element} elm Element to check if it's an text input element or not.
- * @return {Boolean} True/false if the element is a text element or not.
- */
- function isTextInputElement(elm) {
- var tagName = elm.tagName.toUpperCase();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isElement(elm)) {
+ return elm.getAttribute('aria-' + name);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Notice: since type can be "email" etc we don't check the type
- // So all input elements gets treated as text input elements
- return tagName == "INPUT" || tagName == "TEXTAREA" || tagName == "SELECT";
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Is the element a text input element or not.
+ *
+ * @private
+ * @param {Element} elm Element to check if it's an text input element or not.
+ * @return {Boolean} True/false if the element is a text element or not.
+ */
+ function isTextInputElement(elm) {
+ var tagName = elm.tagName.toUpperCase();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the specified element can be focused or not.
- *
- * @private
- * @param {Element} elm DOM element to check if it can be focused or not.
- * @return {Boolean} True/false if the element can have focus.
- */
- function canFocus(elm) {
- if (isTextInputElement(elm) && !elm.hidden) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Notice: since type can be "email" etc we don't check the type
+ // So all input elements gets treated as text input elements
+ return tagName == "INPUT" || tagName == "TEXTAREA" || tagName == "SELECT";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (/^(button|menuitem|checkbox|tab|menuitemcheckbox|option|gridcell|slider)$/.test(getRole(elm))) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the specified element can be focused or not.
+ *
+ * @private
+ * @param {Element} elm DOM element to check if it can be focused or not.
+ * @return {Boolean} True/false if the element can have focus.
+ */
+ function canFocus(elm) {
+ if (isTextInputElement(elm) && !elm.hidden) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (hasTabstopData(elm)) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns an array of focusable visible elements within the specified container element.
- *
- * @private
- * @param {Element} elm DOM element to find focusable elements within.
- * @return {Array} Array of focusable elements.
- */
- function getFocusElements(elm) {
- var elements = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (/^(button|menuitem|checkbox|tab|menuitemcheckbox|option|gridcell|slider)$/.test(getRole(elm))) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function collect(elm) {
- if (elm.nodeType != 1 || elm.style.display == 'none' || elm.disabled) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (canFocus(elm)) {
- elements.push(elm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns an array of focusable visible elements within the specified container element.
+ *
+ * @private
+ * @param {Element} elm DOM element to find focusable elements within.
+ * @return {Array} Array of focusable elements.
+ */
+ function getFocusElements(elm) {
+ var elements = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var i = 0; i < elm.childNodes.length; i++) {
- collect(elm.childNodes[i]);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function collect(elm) {
+ if (elm.nodeType != 1 || elm.style.display == 'none' || elm.disabled) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- collect(elm || root.getEl());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (canFocus(elm)) {
+ elements.push(elm);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return elements;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (var i = 0; i < elm.childNodes.length; i++) {
+ collect(elm.childNodes[i]);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the navigation root control for the specified control. The navigation root
- * is the control that the keyboard navigation gets scoped to for example a menubar or toolbar group.
- * It will look for parents of the specified target control or the currently focused control if this option is omitted.
- *
- * @private
- * @param {tinymce.ui.Control} targetControl Optional target control to find root of.
- * @return {tinymce.ui.Control} Navigation root control.
- */
- function getNavigationRoot(targetControl) {
- var navigationRoot, controls;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ collect(elm || root.getEl());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- targetControl = targetControl || focusedControl;
- controls = targetControl.parents().toArray();
- controls.unshift(targetControl);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return elements;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var i = 0; i < controls.length; i++) {
- navigationRoot = controls[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the navigation root control for the specified control. The navigation root
+ * is the control that the keyboard navigation gets scoped to for example a menubar or toolbar group.
+ * It will look for parents of the specified target control or the currently focused control if this option is omitted.
+ *
+ * @private
+ * @param {tinymce.ui.Control} targetControl Optional target control to find root of.
+ * @return {tinymce.ui.Control} Navigation root control.
+ */
+ function getNavigationRoot(targetControl) {
+ var navigationRoot, controls;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (navigationRoot.settings.ariaRoot) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ targetControl = targetControl || focusedControl;
+ controls = targetControl.parents().toArray();
+ controls.unshift(targetControl);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return navigationRoot;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (var i = 0; i < controls.length; i++) {
+ navigationRoot = controls[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Focuses the first item in the specified targetControl element or the last aria index if the
- * navigation root has the ariaRemember option enabled.
- *
- * @private
- * @param {tinymce.ui.Control} targetControl Target control to focus the first item in.
- */
- function focusFirst(targetControl) {
- var navigationRoot = getNavigationRoot(targetControl);
- var focusElements = getFocusElements(navigationRoot.getEl());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (navigationRoot.settings.ariaRoot) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (navigationRoot.settings.ariaRemember && "lastAriaIndex" in navigationRoot) {
- moveFocusToIndex(navigationRoot.lastAriaIndex, focusElements);
- } else {
- moveFocusToIndex(0, focusElements);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return navigationRoot;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Moves the focus to the specified index within the elements list.
- * This will scope the index to the size of the element list if it changed.
- *
- * @private
- * @param {Number} idx Specified index to move to.
- * @param {Array} elements Array with dom elements to move focus within.
- * @return {Number} Input index or a changed index if it was out of range.
- */
- function moveFocusToIndex(idx, elements) {
- if (idx < 0) {
- idx = elements.length - 1;
- } else if (idx >= elements.length) {
- idx = 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Focuses the first item in the specified targetControl element or the last aria index if the
+ * navigation root has the ariaRemember option enabled.
+ *
+ * @private
+ * @param {tinymce.ui.Control} targetControl Target control to focus the first item in.
+ */
+ function focusFirst(targetControl) {
+ var navigationRoot = getNavigationRoot(targetControl);
+ var focusElements = getFocusElements(navigationRoot.getEl());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elements[idx]) {
- elements[idx].focus();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (navigationRoot.settings.ariaRemember && "lastAriaIndex" in navigationRoot) {
+ moveFocusToIndex(navigationRoot.lastAriaIndex, focusElements);
+ } else {
+ moveFocusToIndex(0, focusElements);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return idx;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Moves the focus to the specified index within the elements list.
+ * This will scope the index to the size of the element list if it changed.
+ *
+ * @private
+ * @param {Number} idx Specified index to move to.
+ * @param {Array} elements Array with dom elements to move focus within.
+ * @return {Number} Input index or a changed index if it was out of range.
+ */
+ function moveFocusToIndex(idx, elements) {
+ if (idx < 0) {
+ idx = elements.length - 1;
+ } else if (idx >= elements.length) {
+ idx = 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Moves the focus forwards or backwards.
- *
- * @private
- * @param {Number} dir Direction to move in positive means forward, negative means backwards.
- * @param {Array} elements Optional array of elements to move within defaults to the current navigation roots elements.
- */
- function moveFocus(dir, elements) {
- var idx = -1, navigationRoot = getNavigationRoot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (elements[idx]) {
+ elements[idx].focus();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elements = elements || getFocusElements(navigationRoot.getEl());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return idx;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var i = 0; i < elements.length; i++) {
- if (elements[i] === focusedElement) {
- idx = i;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Moves the focus forwards or backwards.
+ *
+ * @private
+ * @param {Number} dir Direction to move in positive means forward, negative means backwards.
+ * @param {Array} elements Optional array of elements to move within defaults to the current navigation roots elements.
+ */
+ function moveFocus(dir, elements) {
+ var idx = -1, navigationRoot = getNavigationRoot();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- idx += dir;
- navigationRoot.lastAriaIndex = moveFocusToIndex(idx, elements);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elements = elements || getFocusElements(navigationRoot.getEl());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Moves the focus to the left this is called by the left key.
- *
- * @private
- */
- function left() {
- var parentRole = getParentRole();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (var i = 0; i < elements.length; i++) {
+ if (elements[i] === focusedElement) {
+ idx = i;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (parentRole == "tablist") {
- moveFocus(-1, getFocusElements(focusedElement.parentNode));
- } else if (focusedControl.parent().submenu) {
- cancel();
- } else {
- moveFocus(-1);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ idx += dir;
+ navigationRoot.lastAriaIndex = moveFocusToIndex(idx, elements);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Moves the focus to the right this is called by the right key.
- *
- * @private
- */
- function right() {
- var role = getRole(), parentRole = getParentRole();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Moves the focus to the left this is called by the left key.
+ *
+ * @private
+ */
+ function left() {
+ var parentRole = getParentRole();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (parentRole == "tablist") {
- moveFocus(1, getFocusElements(focusedElement.parentNode));
- } else if (role == "menuitem" && parentRole == "menu" && getAriaProp('haspopup')) {
- enter();
- } else {
- moveFocus(1);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parentRole == "tablist") {
+ moveFocus(-1, getFocusElements(focusedElement.parentNode));
+ } else if (focusedControl.parent().submenu) {
+ cancel();
+ } else {
+ moveFocus(-1);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Moves the focus to the up this is called by the up key.
- *
- * @private
- */
- function up() {
- moveFocus(-1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Moves the focus to the right this is called by the right key.
+ *
+ * @private
+ */
+ function right() {
+ var role = getRole(), parentRole = getParentRole();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Moves the focus to the up this is called by the down key.
- *
- * @private
- */
- function down() {
- var role = getRole(), parentRole = getParentRole();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parentRole == "tablist") {
+ moveFocus(1, getFocusElements(focusedElement.parentNode));
+ } else if (role == "menuitem" && parentRole == "menu" && getAriaProp('haspopup')) {
+ enter();
+ } else {
+ moveFocus(1);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (role == "menuitem" && parentRole == "menubar") {
- enter();
- } else if (role == "button" && getAriaProp('haspopup')) {
- enter({key: 'down'});
- } else {
- moveFocus(1);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Moves the focus to the up this is called by the up key.
+ *
+ * @private
+ */
+ function up() {
+ moveFocus(-1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Moves the focus to the next item or previous item depending on shift key.
- *
- * @private
- * @param {DOMEvent} e DOM event object.
- */
- function tab(e) {
- var parentRole = getParentRole();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Moves the focus to the up this is called by the down key.
+ *
+ * @private
+ */
+ function down() {
+ var role = getRole(), parentRole = getParentRole();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (parentRole == "tablist") {
- var elm = getFocusElements(focusedControl.getEl('body'))[0];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (role == "menuitem" && parentRole == "menubar") {
+ enter();
+ } else if (role == "button" && getAriaProp('haspopup')) {
+ enter({ key: 'down' });
+ } else {
+ moveFocus(1);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elm) {
- elm.focus();
- }
- } else {
- moveFocus(e.shiftKey ? -1 : 1);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Moves the focus to the next item or previous item depending on shift key.
+ *
+ * @private
+ * @param {DOMEvent} e DOM event object.
+ */
+ function tab(e) {
+ var parentRole = getParentRole();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Calls the cancel event on the currently focused control. This is normally done using the Esc key.
- *
- * @private
- */
- function cancel() {
- focusedControl.fire('cancel');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parentRole == "tablist") {
+ var elm = getFocusElements(focusedControl.getEl('body'))[0];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Calls the click event on the currently focused control. This is normally done using the Enter/Space keys.
- *
- * @private
- * @param {Object} aria Optional aria data to pass along with the enter event.
- */
- function enter(aria) {
- aria = aria || {};
- focusedControl.fire('click', {target: focusedElement, aria: aria});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (elm) {
+ elm.focus();
+ }
+ } else {
+ moveFocus(e.shiftKey ? -1 : 1);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- root.on('keydown', function(e) {
- function handleNonTabOrEscEvent(e, handler) {
- // Ignore non tab keys for text elements
- if (isTextInputElement(focusedElement)) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Calls the cancel event on the currently focused control. This is normally done using the Esc key.
+ *
+ * @private
+ */
+ function cancel() {
+ focusedControl.fire('cancel');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (getRole(focusedElement) === 'slider') {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Calls the click event on the currently focused control. This is normally done using the Enter/Space keys.
+ *
+ * @private
+ * @param {Object} aria Optional aria data to pass along with the enter event.
+ */
+ function enter(aria) {
+ aria = aria || {};
+ focusedControl.fire('click', { target: focusedElement, aria: aria });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (handler(e) !== false) {
- e.preventDefault();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ root.on('keydown', function (e) {
+ function handleNonTabOrEscEvent(e, handler) {
+ // Ignore non tab keys for text elements
+ if (isTextInputElement(focusedElement) || hasTabstopData(focusedElement)) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.isDefaultPrevented()) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (getRole(focusedElement) === 'slider') {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- switch (e.keyCode) {
- case 37: // DOM_VK_LEFT
- handleNonTabOrEscEvent(e, left);
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (handler(e) !== false) {
+ e.preventDefault();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case 39: // DOM_VK_RIGHT
- handleNonTabOrEscEvent(e, right);
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.isDefaultPrevented()) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case 38: // DOM_VK_UP
- handleNonTabOrEscEvent(e, up);
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ switch (e.keyCode) {
+ case 37: // DOM_VK_LEFT
+ handleNonTabOrEscEvent(e, left);
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case 40: // DOM_VK_DOWN
- handleNonTabOrEscEvent(e, down);
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case 39: // DOM_VK_RIGHT
+ handleNonTabOrEscEvent(e, right);
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case 27: // DOM_VK_ESCAPE
- cancel();
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case 38: // DOM_VK_UP
+ handleNonTabOrEscEvent(e, up);
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case 14: // DOM_VK_ENTER
- case 13: // DOM_VK_RETURN
- case 32: // DOM_VK_SPACE
- handleNonTabOrEscEvent(e, enter);
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case 40: // DOM_VK_DOWN
+ handleNonTabOrEscEvent(e, down);
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case 9: // DOM_VK_TAB
- if (tab(e) !== false) {
- e.preventDefault();
- }
- break;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case 27: // DOM_VK_ESCAPE
+ cancel();
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- root.on('focusin', function(e) {
- focusedElement = e.target;
- focusedControl = e.control;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case 14: // DOM_VK_ENTER
+ case 13: // DOM_VK_RETURN
+ case 32: // DOM_VK_SPACE
+ handleNonTabOrEscEvent(e, enter);
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- focusFirst: focusFirst
- };
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case 9: // DOM_VK_TAB
+ if (tab(e) !== false) {
+ e.preventDefault();
+ }
+ break;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/Container.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ root.on('focusin', function (e) {
+ focusedElement = e.target;
+ focusedControl = e.control;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ focusFirst: focusFirst
+ };
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Container.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -29654,501 +33761,502 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.Container
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Control
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Container", [
- "tinymce/ui/Control",
- "tinymce/ui/Collection",
- "tinymce/ui/Selector",
- "tinymce/ui/Factory",
- "tinymce/ui/KeyboardNavigation",
- "tinymce/util/Tools",
- "tinymce/dom/DomQuery",
- "tinymce/ui/ClassList",
- "tinymce/ui/ReflowQueue"
-], function(Control, Collection, Selector, Factory, KeyboardNavigation, Tools, $, ClassList, ReflowQueue) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Container',
+ [
+ "tinymce.core.ui.Control",
+ "tinymce.core.ui.Collection",
+ "tinymce.core.ui.Selector",
+ "tinymce.core.ui.Factory",
+ "tinymce.core.ui.KeyboardNavigation",
+ "tinymce.core.util.Tools",
+ "tinymce.core.dom.DomQuery",
+ "tinymce.core.ui.ClassList",
+ "tinymce.core.ui.ReflowQueue"
+ ],
+ function (Control, Collection, Selector, Factory, KeyboardNavigation, Tools, $, ClassList, ReflowQueue) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var selectorCache = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var selectorCache = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Control.extend({
- /**
- * Constructs a new control instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- * @setting {Array} items Items to add to container in JSON format or control instances.
- * @setting {String} layout Layout manager by name to use.
- * @setting {Object} defaults Default settings to apply to all items.
- */
- init: function(settings) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Control.extend({
+ /**
+ * Constructs a new control instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ * @setting {Array} items Items to add to container in JSON format or control instances.
+ * @setting {String} layout Layout manager by name to use.
+ * @setting {Object} defaults Default settings to apply to all items.
+ */
+ init: function (settings) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super(settings);
- settings = self.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super(settings);
+ settings = self.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.fixed) {
- self.state.set('fixed', true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.fixed) {
+ self.state.set('fixed', true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._items = new Collection();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._items = new Collection();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.isRtl()) {
- self.classes.add('rtl');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.isRtl()) {
+ self.classes.add('rtl');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.bodyClasses = new ClassList(function() {
- if (self.state.get('rendered')) {
- self.getEl('body').className = this.toString();
- }
- });
- self.bodyClasses.prefix = self.classPrefix;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.bodyClasses = new ClassList(function () {
+ if (self.state.get('rendered')) {
+ self.getEl('body').className = this.toString();
+ }
+ });
+ self.bodyClasses.prefix = self.classPrefix;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.classes.add('container');
- self.bodyClasses.add('container-body');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.classes.add('container');
+ self.bodyClasses.add('container-body');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.containerCls) {
- self.classes.add(settings.containerCls);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.containerCls) {
+ self.classes.add(settings.containerCls);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._layout = Factory.create((settings.layout || '') + 'layout');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._layout = Factory.create((settings.layout || '') + 'layout');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.settings.items) {
- self.add(self.settings.items);
- } else {
- self.add(self.render());
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.settings.items) {
+ self.add(self.settings.items);
+ } else {
+ self.add(self.render());
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // TODO: Fix this!
- self._hasBody = true;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // TODO: Fix this!
+ self._hasBody = true;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a collection of child items that the container currently have.
- *
- * @method items
- * @return {tinymce.ui.Collection} Control collection direct child controls.
- */
- items: function() {
- return this._items;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a collection of child items that the container currently have.
+ *
+ * @method items
+ * @return {tinymce.ui.Collection} Control collection direct child controls.
+ */
+ items: function () {
+ return this._items;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Find child controls by selector.
- *
- * @method find
- * @param {String} selector Selector CSS pattern to find children by.
- * @return {tinymce.ui.Collection} Control collection with child controls.
- */
- find: function(selector) {
- selector = selectorCache[selector] = selectorCache[selector] || new Selector(selector);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Find child controls by selector.
+ *
+ * @method find
+ * @param {String} selector Selector CSS pattern to find children by.
+ * @return {tinymce.ui.Collection} Control collection with child controls.
+ */
+ find: function (selector) {
+ selector = selectorCache[selector] = selectorCache[selector] || new Selector(selector);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return selector.find(this);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return selector.find(this);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds one or many items to the current container. This will create instances of
- * the object representations if needed.
- *
- * @method add
- * @param {Array/Object/tinymce.ui.Control} items Array or item that will be added to the container.
- * @return {tinymce.ui.Collection} Current collection control.
- */
- add: function(items) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds one or many items to the current container. This will create instances of
+ * the object representations if needed.
+ *
+ * @method add
+ * @param {Array/Object/tinymce.ui.Control} items Array or item that will be added to the container.
+ * @return {tinymce.ui.Collection} Current collection control.
+ */
+ add: function (items) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.items().add(self.create(items)).parent(self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.items().add(self.create(items)).parent(self);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Focuses the current container instance. This will look
- * for the first control in the container and focus that.
- *
- * @method focus
- * @param {Boolean} keyboard Optional true/false if the focus was a keyboard focus or not.
- * @return {tinymce.ui.Collection} Current instance.
- */
- focus: function(keyboard) {
- var self = this, focusCtrl, keyboardNav, items;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Focuses the current container instance. This will look
+ * for the first control in the container and focus that.
+ *
+ * @method focus
+ * @param {Boolean} keyboard Optional true/false if the focus was a keyboard focus or not.
+ * @return {tinymce.ui.Collection} Current instance.
+ */
+ focus: function (keyboard) {
+ var self = this, focusCtrl, keyboardNav, items;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (keyboard) {
- keyboardNav = self.keyboardNav || self.parents().eq(-1)[0].keyboardNav;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (keyboard) {
+ keyboardNav = self.keyboardNav || self.parents().eq(-1)[0].keyboardNav;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (keyboardNav) {
- keyboardNav.focusFirst(self);
- return;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (keyboardNav) {
+ keyboardNav.focusFirst(self);
+ return;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- items = self.find('*');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ items = self.find('*');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // TODO: Figure out a better way to auto focus alert dialog buttons
- if (self.statusbar) {
- items.add(self.statusbar.items());
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // TODO: Figure out a better way to auto focus alert dialog buttons
+ if (self.statusbar) {
+ items.add(self.statusbar.items());
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- items.each(function(ctrl) {
- if (ctrl.settings.autofocus) {
- focusCtrl = null;
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ items.each(function (ctrl) {
+ if (ctrl.settings.autofocus) {
+ focusCtrl = null;
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (ctrl.canFocus) {
- focusCtrl = focusCtrl || ctrl;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (ctrl.canFocus) {
+ focusCtrl = focusCtrl || ctrl;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (focusCtrl) {
- focusCtrl.focus();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (focusCtrl) {
+ focusCtrl.focus();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Replaces the specified child control with a new control.
- *
- * @method replace
- * @param {tinymce.ui.Control} oldItem Old item to be replaced.
- * @param {tinymce.ui.Control} newItem New item to be inserted.
- */
- replace: function(oldItem, newItem) {
- var ctrlElm, items = this.items(), i = items.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Replaces the specified child control with a new control.
+ *
+ * @method replace
+ * @param {tinymce.ui.Control} oldItem Old item to be replaced.
+ * @param {tinymce.ui.Control} newItem New item to be inserted.
+ */
+ replace: function (oldItem, newItem) {
+ var ctrlElm, items = this.items(), i = items.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Replace the item in collection
- while (i--) {
- if (items[i] === oldItem) {
- items[i] = newItem;
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Replace the item in collection
+ while (i--) {
+ if (items[i] === oldItem) {
+ items[i] = newItem;
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (i >= 0) {
- // Remove new item from DOM
- ctrlElm = newItem.getEl();
- if (ctrlElm) {
- ctrlElm.parentNode.removeChild(ctrlElm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (i >= 0) {
+ // Remove new item from DOM
+ ctrlElm = newItem.getEl();
+ if (ctrlElm) {
+ ctrlElm.parentNode.removeChild(ctrlElm);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove old item from DOM
- ctrlElm = oldItem.getEl();
- if (ctrlElm) {
- ctrlElm.parentNode.removeChild(ctrlElm);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove old item from DOM
+ ctrlElm = oldItem.getEl();
+ if (ctrlElm) {
+ ctrlElm.parentNode.removeChild(ctrlElm);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Adopt the item
- newItem.parent(this);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Adopt the item
+ newItem.parent(this);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates the specified items. If any of the items is plain JSON style objects
- * it will convert these into real tinymce.ui.Control instances.
- *
- * @method create
- * @param {Array} items Array of items to convert into control instances.
- * @return {Array} Array with control instances.
- */
- create: function(items) {
- var self = this, settings, ctrlItems = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates the specified items. If any of the items is plain JSON style objects
+ * it will convert these into real tinymce.ui.Control instances.
+ *
+ * @method create
+ * @param {Array} items Array of items to convert into control instances.
+ * @return {Array} Array with control instances.
+ */
+ create: function (items) {
+ var self = this, settings, ctrlItems = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Non array structure, then force it into an array
- if (!Tools.isArray(items)) {
- items = [items];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Non array structure, then force it into an array
+ if (!Tools.isArray(items)) {
+ items = [items];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add default type to each child control
- Tools.each(items, function(item) {
- if (item) {
- // Construct item if needed
- if (!(item instanceof Control)) {
- // Name only then convert it to an object
- if (typeof item == "string") {
- item = {type: item};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add default type to each child control
+ Tools.each(items, function (item) {
+ if (item) {
+ // Construct item if needed
+ if (!(item instanceof Control)) {
+ // Name only then convert it to an object
+ if (typeof item == "string") {
+ item = { type: item };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Create control instance based on input settings and default settings
- settings = Tools.extend({}, self.settings.defaults, item);
- item.type = settings.type = settings.type || item.type || self.settings.defaultType ||
- (settings.defaults ? settings.defaults.type : null);
- item = Factory.create(settings);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Create control instance based on input settings and default settings
+ settings = Tools.extend({}, self.settings.defaults, item);
+ item.type = settings.type = settings.type || item.type || self.settings.defaultType ||
+ (settings.defaults ? settings.defaults.type : null);
+ item = Factory.create(settings);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ctrlItems.push(item);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ctrlItems.push(item);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return ctrlItems;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return ctrlItems;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders new control instances.
- *
- * @private
- */
- renderNew: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders new control instances.
+ *
+ * @private
+ */
+ renderNew: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Render any new items
- self.items().each(function(ctrl, index) {
- var containerElm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Render any new items
+ self.items().each(function (ctrl, index) {
+ var containerElm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ctrl.parent(self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ctrl.parent(self);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!ctrl.state.get('rendered')) {
- containerElm = self.getEl('body');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!ctrl.state.get('rendered')) {
+ containerElm = self.getEl('body');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Insert or append the item
- if (containerElm.hasChildNodes() && index <= containerElm.childNodes.length - 1) {
- $(containerElm.childNodes[index]).before(ctrl.renderHtml());
- } else {
- $(containerElm).append(ctrl.renderHtml());
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Insert or append the item
+ if (containerElm.hasChildNodes() && index <= containerElm.childNodes.length - 1) {
+ $(containerElm.childNodes[index]).before(ctrl.renderHtml());
+ } else {
+ $(containerElm).append(ctrl.renderHtml());
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ctrl.postRender();
- ReflowQueue.add(ctrl);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ctrl.postRender();
+ ReflowQueue.add(ctrl);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._layout.applyClasses(self.items().filter(':visible'));
- self._lastRect = null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._layout.applyClasses(self.items().filter(':visible'));
+ self._lastRect = null;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Appends new instances to the current container.
- *
- * @method append
- * @param {Array/tinymce.ui.Collection} items Array if controls to append.
- * @return {tinymce.ui.Container} Current container instance.
- */
- append: function(items) {
- return this.add(items).renderNew();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Appends new instances to the current container.
+ *
+ * @method append
+ * @param {Array/tinymce.ui.Collection} items Array if controls to append.
+ * @return {tinymce.ui.Container} Current container instance.
+ */
+ append: function (items) {
+ return this.add(items).renderNew();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Prepends new instances to the current container.
- *
- * @method prepend
- * @param {Array/tinymce.ui.Collection} items Array if controls to prepend.
- * @return {tinymce.ui.Container} Current container instance.
- */
- prepend: function(items) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Prepends new instances to the current container.
+ *
+ * @method prepend
+ * @param {Array/tinymce.ui.Collection} items Array if controls to prepend.
+ * @return {tinymce.ui.Container} Current container instance.
+ */
+ prepend: function (items) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.items().set(self.create(items).concat(self.items().toArray()));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.items().set(self.create(items).concat(self.items().toArray()));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self.renderNew();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self.renderNew();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Inserts an control at a specific index.
- *
- * @method insert
- * @param {Array/tinymce.ui.Collection} items Array if controls to insert.
- * @param {Number} index Index to insert controls at.
- * @param {Boolean} [before=false] Inserts controls before the index.
- */
- insert: function(items, index, before) {
- var self = this, curItems, beforeItems, afterItems;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Inserts an control at a specific index.
+ *
+ * @method insert
+ * @param {Array/tinymce.ui.Collection} items Array if controls to insert.
+ * @param {Number} index Index to insert controls at.
+ * @param {Boolean} [before=false] Inserts controls before the index.
+ */
+ insert: function (items, index, before) {
+ var self = this, curItems, beforeItems, afterItems;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- items = self.create(items);
- curItems = self.items();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ items = self.create(items);
+ curItems = self.items();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!before && index < curItems.length - 1) {
- index += 1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!before && index < curItems.length - 1) {
+ index += 1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (index >= 0 && index < curItems.length) {
- beforeItems = curItems.slice(0, index).toArray();
- afterItems = curItems.slice(index).toArray();
- curItems.set(beforeItems.concat(items, afterItems));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (index >= 0 && index < curItems.length) {
+ beforeItems = curItems.slice(0, index).toArray();
+ afterItems = curItems.slice(index).toArray();
+ curItems.set(beforeItems.concat(items, afterItems));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self.renderNew();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self.renderNew();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Populates the form fields from the specified JSON data object.
- *
- * Control items in the form that matches the data will have it's value set.
- *
- * @method fromJSON
- * @param {Object} data JSON data object to set control values by.
- * @return {tinymce.ui.Container} Current form instance.
- */
- fromJSON: function(data) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Populates the form fields from the specified JSON data object.
+ *
+ * Control items in the form that matches the data will have it's value set.
+ *
+ * @method fromJSON
+ * @param {Object} data JSON data object to set control values by.
+ * @return {tinymce.ui.Container} Current form instance.
+ */
+ fromJSON: function (data) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var name in data) {
- self.find('#' + name).value(data[name]);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (var name in data) {
+ self.find('#' + name).value(data[name]);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Serializes the form into a JSON object by getting all items
- * that has a name and a value.
- *
- * @method toJSON
- * @return {Object} JSON object with form data.
- */
- toJSON: function() {
- var self = this, data = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Serializes the form into a JSON object by getting all items
+ * that has a name and a value.
+ *
+ * @method toJSON
+ * @return {Object} JSON object with form data.
+ */
+ toJSON: function () {
+ var self = this, data = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.find('*').each(function(ctrl) {
- var name = ctrl.name(), value = ctrl.value();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.find('*').each(function (ctrl) {
+ var name = ctrl.name(), value = ctrl.value();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name && typeof value != "undefined") {
- data[name] = value;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name && typeof value != "undefined") {
+ data[name] = value;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return data;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return data;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this, layout = self._layout, role = this.settings.role;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this, layout = self._layout, role = this.settings.role;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.preRender();
- layout.preRender(self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.preRender();
+ layout.preRender(self);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<div id="' + self._id + '" class="' + self.classes + '"' + (role ? ' role="' + this.settings.role + '"' : '') + '>' +
- '<div id="' + self._id + '-body" class="' + self.bodyClasses + '">' +
- (self.settings.html || '') + layout.renderHtml(self) +
- '</div>' +
- '</div>'
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<div id="' + self._id + '" class="' + self.classes + '"' + (role ? ' role="' + this.settings.role + '"' : '') + '>' +
+ '<div id="' + self._id + '-body" class="' + self.bodyClasses + '">' +
+ (self.settings.html || '') + layout.renderHtml(self) +
+ '</div>' +
+ '</div>'
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Post render method. Called after the control has been rendered to the target.
- *
- * @method postRender
- * @return {tinymce.ui.Container} Current combobox instance.
- */
- postRender: function() {
- var self = this, box;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Post render method. Called after the control has been rendered to the target.
+ *
+ * @method postRender
+ * @return {tinymce.ui.Container} Current combobox instance.
+ */
+ postRender: function () {
+ var self = this, box;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.items().exec('postRender');
- self._super();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.items().exec('postRender');
+ self._super();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._layout.postRender(self);
- self.state.set('rendered', true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._layout.postRender(self);
+ self.state.set('rendered', true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.settings.style) {
- self.$el.css(self.settings.style);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.settings.style) {
+ self.$el.css(self.settings.style);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.settings.border) {
- box = self.borderBox;
- self.$el.css({
- 'border-top-width': box.top,
- 'border-right-width': box.right,
- 'border-bottom-width': box.bottom,
- 'border-left-width': box.left
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.settings.border) {
+ box = self.borderBox;
+ self.$el.css({
+ 'border-top-width': box.top,
+ 'border-right-width': box.right,
+ 'border-bottom-width': box.bottom,
+ 'border-left-width': box.left
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.parent()) {
- self.keyboardNav = new KeyboardNavigation({
- root: self
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.parent()) {
+ self.keyboardNav = new KeyboardNavigation({
+ root: self
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Initializes the current controls layout rect.
- * This will be executed by the layout managers to determine the
- * default minWidth/minHeight etc.
- *
- * @method initLayoutRect
- * @return {Object} Layout rect instance.
- */
- initLayoutRect: function() {
- var self = this, layoutRect = self._super();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Initializes the current controls layout rect.
+ * This will be executed by the layout managers to determine the
+ * default minWidth/minHeight etc.
+ *
+ * @method initLayoutRect
+ * @return {Object} Layout rect instance.
+ */
+ initLayoutRect: function () {
+ var self = this, layoutRect = self._super();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Recalc container size by asking layout manager
- self._layout.recalc(self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Recalc container size by asking layout manager
+ self._layout.recalc(self);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return layoutRect;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return layoutRect;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Recalculates the positions of the controls in the current container.
- * This is invoked by the reflow method and shouldn't be called directly.
- *
- * @method recalc
- */
- recalc: function() {
- var self = this, rect = self._layoutRect, lastRect = self._lastRect;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Recalculates the positions of the controls in the current container.
+ * This is invoked by the reflow method and shouldn't be called directly.
+ *
+ * @method recalc
+ */
+ recalc: function () {
+ var self = this, rect = self._layoutRect, lastRect = self._lastRect;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!lastRect || lastRect.w != rect.w || lastRect.h != rect.h) {
- self._layout.recalc(self);
- rect = self.layoutRect();
- self._lastRect = {x: rect.x, y: rect.y, w: rect.w, h: rect.h};
- return true;
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!lastRect || lastRect.w != rect.w || lastRect.h != rect.h) {
+ self._layout.recalc(self);
+ rect = self.layoutRect();
+ self._lastRect = { x: rect.x, y: rect.y, w: rect.w, h: rect.h };
+ return true;
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Reflows the current container and it's children and possible parents.
- * This should be used after you for example append children to the current control so
- * that the layout managers know that they need to reposition everything.
- *
- * @example
- * container.append({type: 'button', text: 'My button'}).reflow();
- *
- * @method reflow
- * @return {tinymce.ui.Container} Current container instance.
- */
- reflow: function() {
- var i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Reflows the current container and it's children and possible parents.
+ * This should be used after you for example append children to the current control so
+ * that the layout managers know that they need to reposition everything.
+ *
+ * @example
+ * container.append({type: 'button', text: 'My button'}).reflow();
+ *
+ * @method reflow
+ * @return {tinymce.ui.Container} Current container instance.
+ */
+ reflow: function () {
+ var i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ReflowQueue.remove(this);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ReflowQueue.remove(this);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.visible()) {
- Control.repaintControls = [];
- Control.repaintControls.map = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.visible()) {
+ Control.repaintControls = [];
+ Control.repaintControls.map = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.recalc();
- i = Control.repaintControls.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.recalc();
+ i = Control.repaintControls.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- Control.repaintControls[i].repaint();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ Control.repaintControls[i].repaint();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // TODO: Fix me!
- if (this.settings.layout !== "flow" && this.settings.layout !== "stack") {
- this.repaint();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // TODO: Fix me!
+ if (this.settings.layout !== "flow" && this.settings.layout !== "stack") {
+ this.repaint();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Control.repaintControls = [];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Control.repaintControls = [];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/DragHelper.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * DragHelper.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -30171,131 +34279,132 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.DragHelper
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/DragHelper", [
- "tinymce/dom/DomQuery"
-], function($) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.DragHelper',
+ [
+ "tinymce.core.dom.DomQuery"
+ ],
+ function ($) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getDocumentSize(doc) {
- var documentElement, body, scrollWidth, clientWidth;
- var offsetWidth, scrollHeight, clientHeight, offsetHeight, max = Math.max;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getDocumentSize(doc) {
+ var documentElement, body, scrollWidth, clientWidth;
+ var offsetWidth, scrollHeight, clientHeight, offsetHeight, max = Math.max;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- documentElement = doc.documentElement;
- body = doc.body;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ documentElement = doc.documentElement;
+ body = doc.body;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- scrollWidth = max(documentElement.scrollWidth, body.scrollWidth);
- clientWidth = max(documentElement.clientWidth, body.clientWidth);
- offsetWidth = max(documentElement.offsetWidth, body.offsetWidth);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ scrollWidth = max(documentElement.scrollWidth, body.scrollWidth);
+ clientWidth = max(documentElement.clientWidth, body.clientWidth);
+ offsetWidth = max(documentElement.offsetWidth, body.offsetWidth);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- scrollHeight = max(documentElement.scrollHeight, body.scrollHeight);
- clientHeight = max(documentElement.clientHeight, body.clientHeight);
- offsetHeight = max(documentElement.offsetHeight, body.offsetHeight);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ scrollHeight = max(documentElement.scrollHeight, body.scrollHeight);
+ clientHeight = max(documentElement.clientHeight, body.clientHeight);
+ offsetHeight = max(documentElement.offsetHeight, body.offsetHeight);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- width: scrollWidth < offsetWidth ? clientWidth : scrollWidth,
- height: scrollHeight < offsetHeight ? clientHeight : scrollHeight
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ width: scrollWidth < offsetWidth ? clientWidth : scrollWidth,
+ height: scrollHeight < offsetHeight ? clientHeight : scrollHeight
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function updateWithTouchData(e) {
- var keys, i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function updateWithTouchData(e) {
+ var keys, i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.changedTouches) {
- keys = "screenX screenY pageX pageY clientX clientY".split(' ');
- for (i = 0; i < keys.length; i++) {
- e[keys[i]] = e.changedTouches[0][keys[i]];
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.changedTouches) {
+ keys = "screenX screenY pageX pageY clientX clientY".split(' ');
+ for (i = 0; i < keys.length; i++) {
+ e[keys[i]] = e.changedTouches[0][keys[i]];
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function(id, settings) {
- var $eventOverlay, doc = settings.document || document, downButton, start, stop, drag, startX, startY;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function (id, settings) {
+ var $eventOverlay, doc = settings.document || document, downButton, start, stop, drag, startX, startY;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- settings = settings || {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ settings = settings || {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getHandleElm() {
- return doc.getElementById(settings.handle || id);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getHandleElm() {
+ return doc.getElementById(settings.handle || id);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- start = function(e) {
- var docSize = getDocumentSize(doc), handleElm, cursor;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ start = function (e) {
+ var docSize = getDocumentSize(doc), handleElm, cursor;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- updateWithTouchData(e);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ updateWithTouchData(e);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- e.preventDefault();
- downButton = e.button;
- handleElm = getHandleElm();
- startX = e.screenX;
- startY = e.screenY;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ e.preventDefault();
+ downButton = e.button;
+ handleElm = getHandleElm();
+ startX = e.screenX;
+ startY = e.screenY;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Grab cursor from handle so we can place it on overlay
- if (window.getComputedStyle) {
- cursor = window.getComputedStyle(handleElm, null).getPropertyValue("cursor");
- } else {
- cursor = handleElm.runtimeStyle.cursor;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Grab cursor from handle so we can place it on overlay
+ if (window.getComputedStyle) {
+ cursor = window.getComputedStyle(handleElm, null).getPropertyValue("cursor");
+ } else {
+ cursor = handleElm.runtimeStyle.cursor;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $eventOverlay = $('<div></div>').css({
- position: "absolute",
- top: 0, left: 0,
- width: docSize.width,
- height: docSize.height,
- zIndex: 0x7FFFFFFF,
- opacity: 0.0001,
- cursor: cursor
- }).appendTo(doc.body);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $eventOverlay = $('<div></div>').css({
+ position: "absolute",
+ top: 0, left: 0,
+ width: docSize.width,
+ height: docSize.height,
+ zIndex: 0x7FFFFFFF,
+ opacity: 0.0001,
+ cursor: cursor
+ }).appendTo(doc.body);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $(doc).on('mousemove touchmove', drag).on('mouseup touchend', stop);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $(doc).on('mousemove touchmove', drag).on('mouseup touchend', stop);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- settings.start(e);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ settings.start(e);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- drag = function(e) {
- updateWithTouchData(e);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ drag = function (e) {
+ updateWithTouchData(e);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.button !== downButton) {
- return stop(e);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.button !== downButton) {
+ return stop(e);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- e.deltaX = e.screenX - startX;
- e.deltaY = e.screenY - startY;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ e.deltaX = e.screenX - startX;
+ e.deltaY = e.screenY - startY;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- e.preventDefault();
- settings.drag(e);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ e.preventDefault();
+ settings.drag(e);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- stop = function(e) {
- updateWithTouchData(e);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ stop = function (e) {
+ updateWithTouchData(e);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $(doc).off('mousemove touchmove', drag).off('mouseup touchend', stop);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $(doc).off('mousemove touchmove', drag).off('mouseup touchend', stop);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $eventOverlay.remove();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $eventOverlay.remove();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.stop) {
- settings.stop(e);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.stop) {
+ settings.stop(e);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Destroys the drag/drop helper instance.
- *
- * @method destroy
- */
- this.destroy = function() {
- $(getHandleElm()).off();
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Destroys the drag/drop helper instance.
+ *
+ * @method destroy
+ */
+ this.destroy = function () {
+ $(getHandleElm()).off();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $(getHandleElm()).on('mousedown touchstart', start);
- };
-});
-
-// Included from: js/tinymce/classes/ui/Scrollable.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $(getHandleElm()).on('mousedown touchstart', start);
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Scrollable.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -30307,139 +34416,140 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @-x-less Scrollable.less
</span><span class="cx" style="display: block; padding: 0 10px"> * @mixin tinymce.ui.Scrollable
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Scrollable", [
- "tinymce/dom/DomQuery",
- "tinymce/ui/DragHelper"
-], function($, DragHelper) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Scrollable',
+ [
+ "tinymce.core.dom.DomQuery",
+ "tinymce.core.ui.DragHelper"
+ ],
+ function ($, DragHelper) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- init: function() {
- var self = this;
- self.on('repaint', self.renderScroll);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ init: function () {
+ var self = this;
+ self.on('repaint', self.renderScroll);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- renderScroll: function() {
- var self = this, margin = 2;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ renderScroll: function () {
+ var self = this, margin = 2;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function repaintScroll() {
- var hasScrollH, hasScrollV, bodyElm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function repaintScroll() {
+ var hasScrollH, hasScrollV, bodyElm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function repaintAxis(axisName, posName, sizeName, contentSizeName, hasScroll, ax) {
- var containerElm, scrollBarElm, scrollThumbElm;
- var containerSize, scrollSize, ratio, rect;
- var posNameLower, sizeNameLower;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function repaintAxis(axisName, posName, sizeName, contentSizeName, hasScroll, ax) {
+ var containerElm, scrollBarElm, scrollThumbElm;
+ var containerSize, scrollSize, ratio, rect;
+ var posNameLower, sizeNameLower;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- scrollBarElm = self.getEl('scroll' + axisName);
- if (scrollBarElm) {
- posNameLower = posName.toLowerCase();
- sizeNameLower = sizeName.toLowerCase();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ scrollBarElm = self.getEl('scroll' + axisName);
+ if (scrollBarElm) {
+ posNameLower = posName.toLowerCase();
+ sizeNameLower = sizeName.toLowerCase();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $(self.getEl('absend')).css(posNameLower, self.layoutRect()[contentSizeName] - 1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $(self.getEl('absend')).css(posNameLower, self.layoutRect()[contentSizeName] - 1);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!hasScroll) {
- $(scrollBarElm).css('display', 'none');
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!hasScroll) {
+ $(scrollBarElm).css('display', 'none');
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $(scrollBarElm).css('display', 'block');
- containerElm = self.getEl('body');
- scrollThumbElm = self.getEl('scroll' + axisName + "t");
- containerSize = containerElm["client" + sizeName] - (margin * 2);
- containerSize -= hasScrollH && hasScrollV ? scrollBarElm["client" + ax] : 0;
- scrollSize = containerElm["scroll" + sizeName];
- ratio = containerSize / scrollSize;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $(scrollBarElm).css('display', 'block');
+ containerElm = self.getEl('body');
+ scrollThumbElm = self.getEl('scroll' + axisName + "t");
+ containerSize = containerElm["client" + sizeName] - (margin * 2);
+ containerSize -= hasScrollH && hasScrollV ? scrollBarElm["client" + ax] : 0;
+ scrollSize = containerElm["scroll" + sizeName];
+ ratio = containerSize / scrollSize;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rect = {};
- rect[posNameLower] = containerElm["offset" + posName] + margin;
- rect[sizeNameLower] = containerSize;
- $(scrollBarElm).css(rect);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rect = {};
+ rect[posNameLower] = containerElm["offset" + posName] + margin;
+ rect[sizeNameLower] = containerSize;
+ $(scrollBarElm).css(rect);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rect = {};
- rect[posNameLower] = containerElm["scroll" + posName] * ratio;
- rect[sizeNameLower] = containerSize * ratio;
- $(scrollThumbElm).css(rect);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rect = {};
+ rect[posNameLower] = containerElm["scroll" + posName] * ratio;
+ rect[sizeNameLower] = containerSize * ratio;
+ $(scrollThumbElm).css(rect);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bodyElm = self.getEl('body');
- hasScrollH = bodyElm.scrollWidth > bodyElm.clientWidth;
- hasScrollV = bodyElm.scrollHeight > bodyElm.clientHeight;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bodyElm = self.getEl('body');
+ hasScrollH = bodyElm.scrollWidth > bodyElm.clientWidth;
+ hasScrollV = bodyElm.scrollHeight > bodyElm.clientHeight;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- repaintAxis("h", "Left", "Width", "contentW", hasScrollH, "Height");
- repaintAxis("v", "Top", "Height", "contentH", hasScrollV, "Width");
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ repaintAxis("h", "Left", "Width", "contentW", hasScrollH, "Height");
+ repaintAxis("v", "Top", "Height", "contentH", hasScrollV, "Width");
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function addScroll() {
- function addScrollAxis(axisName, posName, sizeName, deltaPosName, ax) {
- var scrollStart, axisId = self._id + '-scroll' + axisName, prefix = self.classPrefix;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function addScroll() {
+ function addScrollAxis(axisName, posName, sizeName, deltaPosName, ax) {
+ var scrollStart, axisId = self._id + '-scroll' + axisName, prefix = self.classPrefix;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $(self.getEl()).append(
- '<div id="' + axisId + '" class="' + prefix + 'scrollbar ' + prefix + 'scrollbar-' + axisName + '">' +
- '<div id="' + axisId + 't" class="' + prefix + 'scrollbar-thumb"></div>' +
- '</div>'
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $(self.getEl()).append(
+ '<div id="' + axisId + '" class="' + prefix + 'scrollbar ' + prefix + 'scrollbar-' + axisName + '">' +
+ '<div id="' + axisId + 't" class="' + prefix + 'scrollbar-thumb"></div>' +
+ '</div>'
+ );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.draghelper = new DragHelper(axisId + 't', {
- start: function() {
- scrollStart = self.getEl('body')["scroll" + posName];
- $('#' + axisId).addClass(prefix + 'active');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.draghelper = new DragHelper(axisId + 't', {
+ start: function () {
+ scrollStart = self.getEl('body')["scroll" + posName];
+ $('#' + axisId).addClass(prefix + 'active');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- drag: function(e) {
- var ratio, hasScrollH, hasScrollV, containerSize, layoutRect = self.layoutRect();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ drag: function (e) {
+ var ratio, hasScrollH, hasScrollV, containerSize, layoutRect = self.layoutRect();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- hasScrollH = layoutRect.contentW > layoutRect.innerW;
- hasScrollV = layoutRect.contentH > layoutRect.innerH;
- containerSize = self.getEl('body')["client" + sizeName] - (margin * 2);
- containerSize -= hasScrollH && hasScrollV ? self.getEl('scroll' + axisName)["client" + ax] : 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ hasScrollH = layoutRect.contentW > layoutRect.innerW;
+ hasScrollV = layoutRect.contentH > layoutRect.innerH;
+ containerSize = self.getEl('body')["client" + sizeName] - (margin * 2);
+ containerSize -= hasScrollH && hasScrollV ? self.getEl('scroll' + axisName)["client" + ax] : 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ratio = containerSize / self.getEl('body')["scroll" + sizeName];
- self.getEl('body')["scroll" + posName] = scrollStart + (e["delta" + deltaPosName] / ratio);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ratio = containerSize / self.getEl('body')["scroll" + sizeName];
+ self.getEl('body')["scroll" + posName] = scrollStart + (e["delta" + deltaPosName] / ratio);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- stop: function() {
- $('#' + axisId).removeClass(prefix + 'active');
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ stop: function () {
+ $('#' + axisId).removeClass(prefix + 'active');
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.classes.add('scroll');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.classes.add('scroll');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- addScrollAxis("v", "Top", "Height", "Y", "Width");
- addScrollAxis("h", "Left", "Width", "X", "Height");
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ addScrollAxis("v", "Top", "Height", "Y", "Width");
+ addScrollAxis("h", "Left", "Width", "X", "Height");
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.settings.autoScroll) {
- if (!self._hasScroll) {
- self._hasScroll = true;
- addScroll();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.settings.autoScroll) {
+ if (!self._hasScroll) {
+ self._hasScroll = true;
+ addScroll();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('wheel', function(e) {
- var bodyEl = self.getEl('body');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('wheel', function (e) {
+ var bodyEl = self.getEl('body');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bodyEl.scrollLeft += (e.deltaX || 0) * 10;
- bodyEl.scrollTop += e.deltaY * 10;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bodyEl.scrollLeft += (e.deltaX || 0) * 10;
+ bodyEl.scrollTop += e.deltaY * 10;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- repaintScroll();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ repaintScroll();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $(self.getEl('body')).on("scroll", repaintScroll);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $(self.getEl('body')).on("scroll", repaintScroll);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- repaintScroll();
- }
- }
- };
-});
-
-// Included from: js/tinymce/classes/ui/Panel.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ repaintScroll();
+ }
+ }
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Panel.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -30453,63 +34563,65 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Container
</span><span class="cx" style="display: block; padding: 0 10px"> * @mixes tinymce.ui.Scrollable
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Panel", [
- "tinymce/ui/Container",
- "tinymce/ui/Scrollable"
-], function(Container, Scrollable) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Panel',
+ [
+ "tinymce.core.ui.Container",
+ "tinymce.core.ui.Scrollable"
+ ],
+ function (Container, Scrollable) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Container.extend({
- Defaults: {
- layout: 'fit',
- containerCls: 'panel'
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Container.extend({
+ Defaults: {
+ layout: 'fit',
+ containerCls: 'panel'
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Mixins: [Scrollable],
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Mixins: [Scrollable],
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this, layout = self._layout, innerHtml = self.settings.html;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this, layout = self._layout, innerHtml = self.settings.html;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.preRender();
- layout.preRender(self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.preRender();
+ layout.preRender(self);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof innerHtml == "undefined") {
- innerHtml = (
- '<div id="' + self._id + '-body" class="' + self.bodyClasses + '">' +
- layout.renderHtml(self) +
- '</div>'
- );
- } else {
- if (typeof innerHtml == 'function') {
- innerHtml = innerHtml.call(self);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof innerHtml == "undefined") {
+ innerHtml = (
+ '<div id="' + self._id + '-body" class="' + self.bodyClasses + '">' +
+ layout.renderHtml(self) +
+ '</div>'
+ );
+ } else {
+ if (typeof innerHtml == 'function') {
+ innerHtml = innerHtml.call(self);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._hasBody = false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._hasBody = false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<div id="' + self._id + '" class="' + self.classes + '" hidefocus="1" tabindex="-1" role="group">' +
- (self._preBodyHtml || '') +
- innerHtml +
- '</div>'
- );
- }
- });
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<div id="' + self._id + '" class="' + self.classes + '" hidefocus="1" tabindex="-1" role="group">' +
+ (self._preBodyHtml || '') +
+ innerHtml +
+ '</div>'
+ );
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/Movable.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Movable.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -30520,199 +34632,200 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @mixin tinymce.ui.Movable
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Movable", [
- "tinymce/ui/DomUtils"
-], function(DomUtils) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Movable',
+ [
+ "tinymce.core.ui.DomUtils"
+ ],
+ function (DomUtils) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function calculateRelativePosition(ctrl, targetElm, rel) {
- var ctrlElm, pos, x, y, selfW, selfH, targetW, targetH, viewport, size;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function calculateRelativePosition(ctrl, targetElm, rel) {
+ var ctrlElm, pos, x, y, selfW, selfH, targetW, targetH, viewport, size;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- viewport = DomUtils.getViewPort();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ viewport = DomUtils.getViewPort();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Get pos of target
- pos = DomUtils.getPos(targetElm);
- x = pos.x;
- y = pos.y;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get pos of target
+ pos = DomUtils.getPos(targetElm);
+ x = pos.x;
+ y = pos.y;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (ctrl.state.get('fixed') && DomUtils.getRuntimeStyle(document.body, 'position') == 'static') {
- x -= viewport.x;
- y -= viewport.y;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (ctrl.state.get('fixed') && DomUtils.getRuntimeStyle(document.body, 'position') == 'static') {
+ x -= viewport.x;
+ y -= viewport.y;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Get size of self
- ctrlElm = ctrl.getEl();
- size = DomUtils.getSize(ctrlElm);
- selfW = size.width;
- selfH = size.height;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get size of self
+ ctrlElm = ctrl.getEl();
+ size = DomUtils.getSize(ctrlElm);
+ selfW = size.width;
+ selfH = size.height;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Get size of target
- size = DomUtils.getSize(targetElm);
- targetW = size.width;
- targetH = size.height;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get size of target
+ size = DomUtils.getSize(targetElm);
+ targetW = size.width;
+ targetH = size.height;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Parse align string
- rel = (rel || '').split('');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Parse align string
+ rel = (rel || '').split('');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Target corners
- if (rel[0] === 'b') {
- y += targetH;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Target corners
+ if (rel[0] === 'b') {
+ y += targetH;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rel[1] === 'r') {
- x += targetW;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rel[1] === 'r') {
+ x += targetW;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rel[0] === 'c') {
- y += Math.round(targetH / 2);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rel[0] === 'c') {
+ y += Math.round(targetH / 2);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rel[1] === 'c') {
- x += Math.round(targetW / 2);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rel[1] === 'c') {
+ x += Math.round(targetW / 2);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Self corners
- if (rel[3] === 'b') {
- y -= selfH;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Self corners
+ if (rel[3] === 'b') {
+ y -= selfH;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rel[4] === 'r') {
- x -= selfW;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rel[4] === 'r') {
+ x -= selfW;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rel[3] === 'c') {
- y -= Math.round(selfH / 2);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rel[3] === 'c') {
+ y -= Math.round(selfH / 2);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rel[4] === 'c') {
- x -= Math.round(selfW / 2);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rel[4] === 'c') {
+ x -= Math.round(selfW / 2);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- x: x,
- y: y,
- w: selfW,
- h: selfH
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ x: x,
+ y: y,
+ w: selfW,
+ h: selfH
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- /**
- * Tests various positions to get the most suitable one.
- *
- * @method testMoveRel
- * @param {DOMElement} elm Element to position against.
- * @param {Array} rels Array with relative positions.
- * @return {String} Best suitable relative position.
- */
- testMoveRel: function(elm, rels) {
- var viewPortRect = DomUtils.getViewPort();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ /**
+ * Tests various positions to get the most suitable one.
+ *
+ * @method testMoveRel
+ * @param {DOMElement} elm Element to position against.
+ * @param {Array} rels Array with relative positions.
+ * @return {String} Best suitable relative position.
+ */
+ testMoveRel: function (elm, rels) {
+ var viewPortRect = DomUtils.getViewPort();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var i = 0; i < rels.length; i++) {
- var pos = calculateRelativePosition(this, elm, rels[i]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (var i = 0; i < rels.length; i++) {
+ var pos = calculateRelativePosition(this, elm, rels[i]);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.state.get('fixed')) {
- if (pos.x > 0 && pos.x + pos.w < viewPortRect.w && pos.y > 0 && pos.y + pos.h < viewPortRect.h) {
- return rels[i];
- }
- } else {
- if (pos.x > viewPortRect.x && pos.x + pos.w < viewPortRect.w + viewPortRect.x &&
- pos.y > viewPortRect.y && pos.y + pos.h < viewPortRect.h + viewPortRect.y) {
- return rels[i];
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.state.get('fixed')) {
+ if (pos.x > 0 && pos.x + pos.w < viewPortRect.w && pos.y > 0 && pos.y + pos.h < viewPortRect.h) {
+ return rels[i];
+ }
+ } else {
+ if (pos.x > viewPortRect.x && pos.x + pos.w < viewPortRect.w + viewPortRect.x &&
+ pos.y > viewPortRect.y && pos.y + pos.h < viewPortRect.h + viewPortRect.y) {
+ return rels[i];
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return rels[0];
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return rels[0];
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Move relative to the specified element.
- *
- * @method moveRel
- * @param {Element} elm Element to move relative to.
- * @param {String} rel Relative mode. For example: br-tl.
- * @return {tinymce.ui.Control} Current control instance.
- */
- moveRel: function(elm, rel) {
- if (typeof rel != 'string') {
- rel = this.testMoveRel(elm, rel);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Move relative to the specified element.
+ *
+ * @method moveRel
+ * @param {Element} elm Element to move relative to.
+ * @param {String} rel Relative mode. For example: br-tl.
+ * @return {tinymce.ui.Control} Current control instance.
+ */
+ moveRel: function (elm, rel) {
+ if (typeof rel != 'string') {
+ rel = this.testMoveRel(elm, rel);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var pos = calculateRelativePosition(this, elm, rel);
- return this.moveTo(pos.x, pos.y);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var pos = calculateRelativePosition(this, elm, rel);
+ return this.moveTo(pos.x, pos.y);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Move by a relative x, y values.
- *
- * @method moveBy
- * @param {Number} dx Relative x position.
- * @param {Number} dy Relative y position.
- * @return {tinymce.ui.Control} Current control instance.
- */
- moveBy: function(dx, dy) {
- var self = this, rect = self.layoutRect();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Move by a relative x, y values.
+ *
+ * @method moveBy
+ * @param {Number} dx Relative x position.
+ * @param {Number} dy Relative y position.
+ * @return {tinymce.ui.Control} Current control instance.
+ */
+ moveBy: function (dx, dy) {
+ var self = this, rect = self.layoutRect();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.moveTo(rect.x + dx, rect.y + dy);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.moveTo(rect.x + dx, rect.y + dy);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Move to absolute position.
- *
- * @method moveTo
- * @param {Number} x Absolute x position.
- * @param {Number} y Absolute y position.
- * @return {tinymce.ui.Control} Current control instance.
- */
- moveTo: function(x, y) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Move to absolute position.
+ *
+ * @method moveTo
+ * @param {Number} x Absolute x position.
+ * @param {Number} y Absolute y position.
+ * @return {tinymce.ui.Control} Current control instance.
+ */
+ moveTo: function (x, y) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // TODO: Move this to some global class
- function constrain(value, max, size) {
- if (value < 0) {
- return 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // TODO: Move this to some global class
+ function constrain(value, max, size) {
+ if (value < 0) {
+ return 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value + size > max) {
- value = max - size;
- return value < 0 ? 0 : value;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value + size > max) {
+ value = max - size;
+ return value < 0 ? 0 : value;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return value;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return value;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.settings.constrainToViewport) {
- var viewPortRect = DomUtils.getViewPort(window);
- var layoutRect = self.layoutRect();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.settings.constrainToViewport) {
+ var viewPortRect = DomUtils.getViewPort(window);
+ var layoutRect = self.layoutRect();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- x = constrain(x, viewPortRect.w + viewPortRect.x, layoutRect.w);
- y = constrain(y, viewPortRect.h + viewPortRect.y, layoutRect.h);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ x = constrain(x, viewPortRect.w + viewPortRect.x, layoutRect.w);
+ y = constrain(y, viewPortRect.h + viewPortRect.y, layoutRect.h);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.state.get('rendered')) {
- self.layoutRect({x: x, y: y}).repaint();
- } else {
- self.settings.x = x;
- self.settings.y = y;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.state.get('rendered')) {
+ self.layoutRect({ x: x, y: y }).repaint();
+ } else {
+ self.settings.x = x;
+ self.settings.y = y;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.fire('move', {x: x, y: y});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.fire('move', { x: x, y: y });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- }
- };
-});
-
-// Included from: js/tinymce/classes/ui/Resizable.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ }
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Resizable.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -30723,67 +34836,68 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @mixin tinymce.ui.Resizable
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Resizable", [
- "tinymce/ui/DomUtils"
-], function(DomUtils) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Resizable',
+ [
+ "tinymce.core.ui.DomUtils"
+ ],
+ function (DomUtils) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- /**
- * Resizes the control to contents.
- *
- * @method resizeToContent
- */
- resizeToContent: function() {
- this._layoutRect.autoResize = true;
- this._lastRect = null;
- this.reflow();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ /**
+ * Resizes the control to contents.
+ *
+ * @method resizeToContent
+ */
+ resizeToContent: function () {
+ this._layoutRect.autoResize = true;
+ this._lastRect = null;
+ this.reflow();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Resizes the control to a specific width/height.
- *
- * @method resizeTo
- * @param {Number} w Control width.
- * @param {Number} h Control height.
- * @return {tinymce.ui.Control} Current control instance.
- */
- resizeTo: function(w, h) {
- // TODO: Fix hack
- if (w <= 1 || h <= 1) {
- var rect = DomUtils.getWindowSize();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Resizes the control to a specific width/height.
+ *
+ * @method resizeTo
+ * @param {Number} w Control width.
+ * @param {Number} h Control height.
+ * @return {tinymce.ui.Control} Current control instance.
+ */
+ resizeTo: function (w, h) {
+ // TODO: Fix hack
+ if (w <= 1 || h <= 1) {
+ var rect = DomUtils.getWindowSize();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- w = w <= 1 ? w * rect.w : w;
- h = h <= 1 ? h * rect.h : h;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ w = w <= 1 ? w * rect.w : w;
+ h = h <= 1 ? h * rect.h : h;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this._layoutRect.autoResize = false;
- return this.layoutRect({minW: w, minH: h, w: w, h: h}).reflow();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this._layoutRect.autoResize = false;
+ return this.layoutRect({ minW: w, minH: h, w: w, h: h }).reflow();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Resizes the control to a specific relative width/height.
- *
- * @method resizeBy
- * @param {Number} dw Relative control width.
- * @param {Number} dh Relative control height.
- * @return {tinymce.ui.Control} Current control instance.
- */
- resizeBy: function(dw, dh) {
- var self = this, rect = self.layoutRect();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Resizes the control to a specific relative width/height.
+ *
+ * @method resizeBy
+ * @param {Number} dw Relative control width.
+ * @param {Number} dh Relative control height.
+ * @return {tinymce.ui.Control} Current control instance.
+ */
+ resizeBy: function (dw, dh) {
+ var self = this, rect = self.layoutRect();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self.resizeTo(rect.w + dw, rect.h + dh);
- }
- };
-});
-
-// Included from: js/tinymce/classes/ui/FloatPanel.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self.resizeTo(rect.w + dw, rect.h + dh);
+ }
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * FloatPanel.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -30798,408 +34912,410 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @mixes tinymce.ui.Movable
</span><span class="cx" style="display: block; padding: 0 10px"> * @mixes tinymce.ui.Resizable
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/FloatPanel", [
- "tinymce/ui/Panel",
- "tinymce/ui/Movable",
- "tinymce/ui/Resizable",
- "tinymce/ui/DomUtils",
- "tinymce/dom/DomQuery",
- "tinymce/util/Delay"
-], function(Panel, Movable, Resizable, DomUtils, $, Delay) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.FloatPanel',
+ [
+ "tinymce.core.ui.Panel",
+ "tinymce.core.ui.Movable",
+ "tinymce.core.ui.Resizable",
+ "tinymce.core.ui.DomUtils",
+ "tinymce.core.dom.DomQuery",
+ "tinymce.core.util.Delay"
+ ],
+ function (Panel, Movable, Resizable, DomUtils, $, Delay) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var documentClickHandler, documentScrollHandler, windowResizeHandler, visiblePanels = [];
- var zOrder = [], hasModal;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var documentClickHandler, documentScrollHandler, windowResizeHandler, visiblePanels = [];
+ var zOrder = [], hasModal;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isChildOf(ctrl, parent) {
- while (ctrl) {
- if (ctrl == parent) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isChildOf(ctrl, parent) {
+ while (ctrl) {
+ if (ctrl == parent) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ctrl = ctrl.parent();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ctrl = ctrl.parent();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function skipOrHidePanels(e) {
- // Hide any float panel when a click/focus out is out side that float panel and the
- // float panels direct parent for example a click on a menu button
- var i = visiblePanels.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function skipOrHidePanels(e) {
+ // Hide any float panel when a click/focus out is out side that float panel and the
+ // float panels direct parent for example a click on a menu button
+ var i = visiblePanels.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- var panel = visiblePanels[i], clickCtrl = panel.getParentCtrl(e.target);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ var panel = visiblePanels[i], clickCtrl = panel.getParentCtrl(e.target);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (panel.settings.autohide) {
- if (clickCtrl) {
- if (isChildOf(clickCtrl, panel) || panel.parent() === clickCtrl) {
- continue;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (panel.settings.autohide) {
+ if (clickCtrl) {
+ if (isChildOf(clickCtrl, panel) || panel.parent() === clickCtrl) {
+ continue;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- e = panel.fire('autohide', {target: e.target});
- if (!e.isDefaultPrevented()) {
- panel.hide();
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ e = panel.fire('autohide', { target: e.target });
+ if (!e.isDefaultPrevented()) {
+ panel.hide();
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function bindDocumentClickHandler() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function bindDocumentClickHandler() {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!documentClickHandler) {
- documentClickHandler = function(e) {
- // Gecko fires click event and in the wrong order on Mac so lets normalize
- if (e.button == 2) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!documentClickHandler) {
+ documentClickHandler = function (e) {
+ // Gecko fires click event and in the wrong order on Mac so lets normalize
+ if (e.button == 2) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- skipOrHidePanels(e);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ skipOrHidePanels(e);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $(document).on('click touchstart', documentClickHandler);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $(document).on('click touchstart', documentClickHandler);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function bindDocumentScrollHandler() {
- if (!documentScrollHandler) {
- documentScrollHandler = function() {
- var i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function bindDocumentScrollHandler() {
+ if (!documentScrollHandler) {
+ documentScrollHandler = function () {
+ var i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- i = visiblePanels.length;
- while (i--) {
- repositionPanel(visiblePanels[i]);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ i = visiblePanels.length;
+ while (i--) {
+ repositionPanel(visiblePanels[i]);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $(window).on('scroll', documentScrollHandler);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $(window).on('scroll', documentScrollHandler);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function bindWindowResizeHandler() {
- if (!windowResizeHandler) {
- var docElm = document.documentElement, clientWidth = docElm.clientWidth, clientHeight = docElm.clientHeight;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function bindWindowResizeHandler() {
+ if (!windowResizeHandler) {
+ var docElm = document.documentElement, clientWidth = docElm.clientWidth, clientHeight = docElm.clientHeight;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- windowResizeHandler = function() {
- // Workaround for #7065 IE 7 fires resize events event though the window wasn't resized
- if (!document.all || clientWidth != docElm.clientWidth || clientHeight != docElm.clientHeight) {
- clientWidth = docElm.clientWidth;
- clientHeight = docElm.clientHeight;
- FloatPanel.hideAll();
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ windowResizeHandler = function () {
+ // Workaround for #7065 IE 7 fires resize events event though the window wasn't resized
+ if (!document.all || clientWidth != docElm.clientWidth || clientHeight != docElm.clientHeight) {
+ clientWidth = docElm.clientWidth;
+ clientHeight = docElm.clientHeight;
+ FloatPanel.hideAll();
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $(window).on('resize', windowResizeHandler);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $(window).on('resize', windowResizeHandler);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Repositions the panel to the top of page if the panel is outside of the visual viewport. It will
- * also reposition all child panels of the current panel.
- */
- function repositionPanel(panel) {
- var scrollY = DomUtils.getViewPort().y;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Repositions the panel to the top of page if the panel is outside of the visual viewport. It will
+ * also reposition all child panels of the current panel.
+ */
+ function repositionPanel(panel) {
+ var scrollY = DomUtils.getViewPort().y;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function toggleFixedChildPanels(fixed, deltaY) {
- var parent;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function toggleFixedChildPanels(fixed, deltaY) {
+ var parent;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var i = 0; i < visiblePanels.length; i++) {
- if (visiblePanels[i] != panel) {
- parent = visiblePanels[i].parent();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (var i = 0; i < visiblePanels.length; i++) {
+ if (visiblePanels[i] != panel) {
+ parent = visiblePanels[i].parent();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (parent && (parent = parent.parent())) {
- if (parent == panel) {
- visiblePanels[i].fixed(fixed).moveBy(0, deltaY).repaint();
- }
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (parent && (parent = parent.parent())) {
+ if (parent == panel) {
+ visiblePanels[i].fixed(fixed).moveBy(0, deltaY).repaint();
+ }
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (panel.settings.autofix) {
- if (!panel.state.get('fixed')) {
- panel._autoFixY = panel.layoutRect().y;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (panel.settings.autofix) {
+ if (!panel.state.get('fixed')) {
+ panel._autoFixY = panel.layoutRect().y;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (panel._autoFixY < scrollY) {
- panel.fixed(true).layoutRect({y: 0}).repaint();
- toggleFixedChildPanels(true, scrollY - panel._autoFixY);
- }
- } else {
- if (panel._autoFixY > scrollY) {
- panel.fixed(false).layoutRect({y: panel._autoFixY}).repaint();
- toggleFixedChildPanels(false, panel._autoFixY - scrollY);
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (panel._autoFixY < scrollY) {
+ panel.fixed(true).layoutRect({ y: 0 }).repaint();
+ toggleFixedChildPanels(true, scrollY - panel._autoFixY);
+ }
+ } else {
+ if (panel._autoFixY > scrollY) {
+ panel.fixed(false).layoutRect({ y: panel._autoFixY }).repaint();
+ toggleFixedChildPanels(false, panel._autoFixY - scrollY);
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function addRemove(add, ctrl) {
- var i, zIndex = FloatPanel.zIndex || 0xFFFF, topModal;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function addRemove(add, ctrl) {
+ var i, zIndex = FloatPanel.zIndex || 0xFFFF, topModal;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (add) {
- zOrder.push(ctrl);
- } else {
- i = zOrder.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (add) {
+ zOrder.push(ctrl);
+ } else {
+ i = zOrder.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- if (zOrder[i] === ctrl) {
- zOrder.splice(i, 1);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ if (zOrder[i] === ctrl) {
+ zOrder.splice(i, 1);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (zOrder.length) {
- for (i = 0; i < zOrder.length; i++) {
- if (zOrder[i].modal) {
- zIndex++;
- topModal = zOrder[i];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (zOrder.length) {
+ for (i = 0; i < zOrder.length; i++) {
+ if (zOrder[i].modal) {
+ zIndex++;
+ topModal = zOrder[i];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- zOrder[i].getEl().style.zIndex = zIndex;
- zOrder[i].zIndex = zIndex;
- zIndex++;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ zOrder[i].getEl().style.zIndex = zIndex;
+ zOrder[i].zIndex = zIndex;
+ zIndex++;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var modalBlockEl = $('#' + ctrl.classPrefix + 'modal-block', ctrl.getContainerElm())[0];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var modalBlockEl = $('#' + ctrl.classPrefix + 'modal-block', ctrl.getContainerElm())[0];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (topModal) {
- $(modalBlockEl).css('z-index', topModal.zIndex - 1);
- } else if (modalBlockEl) {
- modalBlockEl.parentNode.removeChild(modalBlockEl);
- hasModal = false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (topModal) {
+ $(modalBlockEl).css('z-index', topModal.zIndex - 1);
+ } else if (modalBlockEl) {
+ modalBlockEl.parentNode.removeChild(modalBlockEl);
+ hasModal = false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- FloatPanel.currentZIndex = zIndex;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ FloatPanel.currentZIndex = zIndex;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var FloatPanel = Panel.extend({
- Mixins: [Movable, Resizable],
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var FloatPanel = Panel.extend({
+ Mixins: [Movable, Resizable],
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a new control instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- * @setting {Boolean} autohide Automatically hide the panel.
- */
- init: function(settings) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a new control instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ * @setting {Boolean} autohide Automatically hide the panel.
+ */
+ init: function (settings) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super(settings);
- self._eventsRoot = self;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super(settings);
+ self._eventsRoot = self;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.classes.add('floatpanel');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.classes.add('floatpanel');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Hide floatpanes on click out side the root button
- if (settings.autohide) {
- bindDocumentClickHandler();
- bindWindowResizeHandler();
- visiblePanels.push(self);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Hide floatpanes on click out side the root button
+ if (settings.autohide) {
+ bindDocumentClickHandler();
+ bindWindowResizeHandler();
+ visiblePanels.push(self);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.autofix) {
- bindDocumentScrollHandler();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.autofix) {
+ bindDocumentScrollHandler();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('move', function() {
- repositionPanel(this);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('move', function () {
+ repositionPanel(this);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('postrender show', function(e) {
- if (e.control == self) {
- var $modalBlockEl, prefix = self.classPrefix;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('postrender show', function (e) {
+ if (e.control == self) {
+ var $modalBlockEl, prefix = self.classPrefix;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.modal && !hasModal) {
- $modalBlockEl = $('#' + prefix + 'modal-block', self.getContainerElm());
- if (!$modalBlockEl[0]) {
- $modalBlockEl = $(
- '<div id="' + prefix + 'modal-block" class="' + prefix + 'reset ' + prefix + 'fade"></div>'
- ).appendTo(self.getContainerElm());
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.modal && !hasModal) {
+ $modalBlockEl = $('#' + prefix + 'modal-block', self.getContainerElm());
+ if (!$modalBlockEl[0]) {
+ $modalBlockEl = $(
+ '<div id="' + prefix + 'modal-block" class="' + prefix + 'reset ' + prefix + 'fade"></div>'
+ ).appendTo(self.getContainerElm());
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Delay.setTimeout(function() {
- $modalBlockEl.addClass(prefix + 'in');
- $(self.getEl()).addClass(prefix + 'in');
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Delay.setTimeout(function () {
+ $modalBlockEl.addClass(prefix + 'in');
+ $(self.getEl()).addClass(prefix + 'in');
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- hasModal = true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ hasModal = true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- addRemove(true, self);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ addRemove(true, self);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('show', function() {
- self.parents().each(function(ctrl) {
- if (ctrl.state.get('fixed')) {
- self.fixed(true);
- return false;
- }
- });
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('show', function () {
+ self.parents().each(function (ctrl) {
+ if (ctrl.state.get('fixed')) {
+ self.fixed(true);
+ return false;
+ }
+ });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.popover) {
- self._preBodyHtml = '<div class="' + self.classPrefix + 'arrow"></div>';
- self.classes.add('popover').add('bottom').add(self.isRtl() ? 'end' : 'start');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.popover) {
+ self._preBodyHtml = '<div class="' + self.classPrefix + 'arrow"></div>';
+ self.classes.add('popover').add('bottom').add(self.isRtl() ? 'end' : 'start');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.aria('label', settings.ariaLabel);
- self.aria('labelledby', self._id);
- self.aria('describedby', self.describedBy || self._id + '-none');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.aria('label', settings.ariaLabel);
+ self.aria('labelledby', self._id);
+ self.aria('describedby', self.describedBy || self._id + '-none');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- fixed: function(state) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ fixed: function (state) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.state.get('fixed') != state) {
- if (self.state.get('rendered')) {
- var viewport = DomUtils.getViewPort();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.state.get('fixed') != state) {
+ if (self.state.get('rendered')) {
+ var viewport = DomUtils.getViewPort();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (state) {
- self.layoutRect().y -= viewport.y;
- } else {
- self.layoutRect().y += viewport.y;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (state) {
+ self.layoutRect().y -= viewport.y;
+ } else {
+ self.layoutRect().y += viewport.y;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.classes.toggle('fixed', state);
- self.state.set('fixed', state);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.classes.toggle('fixed', state);
+ self.state.set('fixed', state);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Shows the current float panel.
- *
- * @method show
- * @return {tinymce.ui.FloatPanel} Current floatpanel instance.
- */
- show: function() {
- var self = this, i, state = self._super();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Shows the current float panel.
+ *
+ * @method show
+ * @return {tinymce.ui.FloatPanel} Current floatpanel instance.
+ */
+ show: function () {
+ var self = this, i, state = self._super();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- i = visiblePanels.length;
- while (i--) {
- if (visiblePanels[i] === self) {
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ i = visiblePanels.length;
+ while (i--) {
+ if (visiblePanels[i] === self) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (i === -1) {
- visiblePanels.push(self);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (i === -1) {
+ visiblePanels.push(self);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return state;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return state;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Hides the current float panel.
- *
- * @method hide
- * @return {tinymce.ui.FloatPanel} Current floatpanel instance.
- */
- hide: function() {
- removeVisiblePanel(this);
- addRemove(false, this);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Hides the current float panel.
+ *
+ * @method hide
+ * @return {tinymce.ui.FloatPanel} Current floatpanel instance.
+ */
+ hide: function () {
+ removeVisiblePanel(this);
+ addRemove(false, this);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this._super();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this._super();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Hide all visible float panels with he autohide setting enabled. This is for
- * manually hiding floating menus or panels.
- *
- * @method hideAll
- */
- hideAll: function() {
- FloatPanel.hideAll();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Hide all visible float panels with he autohide setting enabled. This is for
+ * manually hiding floating menus or panels.
+ *
+ * @method hideAll
+ */
+ hideAll: function () {
+ FloatPanel.hideAll();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Closes the float panel. This will remove the float panel from page and fire the close event.
- *
- * @method close
- */
- close: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Closes the float panel. This will remove the float panel from page and fire the close event.
+ *
+ * @method close
+ */
+ close: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.fire('close').isDefaultPrevented()) {
- self.remove();
- addRemove(false, self);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.fire('close').isDefaultPrevented()) {
+ self.remove();
+ addRemove(false, self);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes the float panel from page.
- *
- * @method remove
- */
- remove: function() {
- removeVisiblePanel(this);
- this._super();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes the float panel from page.
+ *
+ * @method remove
+ */
+ remove: function () {
+ removeVisiblePanel(this);
+ this._super();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- postRender: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ postRender: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.settings.bodyRole) {
- this.getEl('body').setAttribute('role', self.settings.bodyRole);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.settings.bodyRole) {
+ this.getEl('body').setAttribute('role', self.settings.bodyRole);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Hide all visible float panels with he autohide setting enabled. This is for
- * manually hiding floating menus or panels.
- *
- * @static
- * @method hideAll
- */
- FloatPanel.hideAll = function() {
- var i = visiblePanels.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Hide all visible float panels with he autohide setting enabled. This is for
+ * manually hiding floating menus or panels.
+ *
+ * @static
+ * @method hideAll
+ */
+ FloatPanel.hideAll = function () {
+ var i = visiblePanels.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- var panel = visiblePanels[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ var panel = visiblePanels[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (panel && panel.settings.autohide) {
- panel.hide();
- visiblePanels.splice(i, 1);
- }
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (panel && panel.settings.autohide) {
+ panel.hide();
+ visiblePanels.splice(i, 1);
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function removeVisiblePanel(panel) {
- var i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function removeVisiblePanel(panel) {
+ var i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- i = visiblePanels.length;
- while (i--) {
- if (visiblePanels[i] === panel) {
- visiblePanels.splice(i, 1);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ i = visiblePanels.length;
+ while (i--) {
+ if (visiblePanels[i] === panel) {
+ visiblePanels.splice(i, 1);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- i = zOrder.length;
- while (i--) {
- if (zOrder[i] === panel) {
- zOrder.splice(i, 1);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ i = zOrder.length;
+ while (i--) {
+ if (zOrder[i] === panel) {
+ zOrder.splice(i, 1);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return FloatPanel;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return FloatPanel;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/Window.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Window.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -31212,478 +35328,479 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.Window
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.FloatPanel
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Window", [
- "tinymce/ui/FloatPanel",
- "tinymce/ui/Panel",
- "tinymce/ui/DomUtils",
- "tinymce/dom/DomQuery",
- "tinymce/ui/DragHelper",
- "tinymce/ui/BoxUtils",
- "tinymce/Env",
- "tinymce/util/Delay"
-], function(FloatPanel, Panel, DomUtils, $, DragHelper, BoxUtils, Env, Delay) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Window',
+ [
+ "tinymce.core.ui.FloatPanel",
+ "tinymce.core.ui.Panel",
+ "tinymce.core.ui.DomUtils",
+ "tinymce.core.dom.DomQuery",
+ "tinymce.core.ui.DragHelper",
+ "tinymce.core.ui.BoxUtils",
+ "tinymce.core.Env",
+ "tinymce.core.util.Delay"
+ ],
+ function (FloatPanel, Panel, DomUtils, $, DragHelper, BoxUtils, Env, Delay) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var windows = [], oldMetaValue = '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var windows = [], oldMetaValue = '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function toggleFullScreenState(state) {
- var noScaleMetaValue = 'width=device-width,initial-scale=1.0,user-scalable=0,minimum-scale=1.0,maximum-scale=1.0',
- viewport = $("meta[name=viewport]")[0],
- contentValue;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function toggleFullScreenState(state) {
+ var noScaleMetaValue = 'width=device-width,initial-scale=1.0,user-scalable=0,minimum-scale=1.0,maximum-scale=1.0',
+ viewport = $("meta[name=viewport]")[0],
+ contentValue;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (Env.overrideViewPort === false) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (Env.overrideViewPort === false) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!viewport) {
- viewport = document.createElement('meta');
- viewport.setAttribute('name', 'viewport');
- document.getElementsByTagName('head')[0].appendChild(viewport);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!viewport) {
+ viewport = document.createElement('meta');
+ viewport.setAttribute('name', 'viewport');
+ document.getElementsByTagName('head')[0].appendChild(viewport);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- contentValue = viewport.getAttribute('content');
- if (contentValue && typeof oldMetaValue != 'undefined') {
- oldMetaValue = contentValue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ contentValue = viewport.getAttribute('content');
+ if (contentValue && typeof oldMetaValue != 'undefined') {
+ oldMetaValue = contentValue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- viewport.setAttribute('content', state ? noScaleMetaValue : oldMetaValue);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ viewport.setAttribute('content', state ? noScaleMetaValue : oldMetaValue);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function toggleBodyFullScreenClasses(classPrefix, state) {
- if (checkFullscreenWindows() && state === false) {
- $([document.documentElement, document.body]).removeClass(classPrefix + 'fullscreen');
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function toggleBodyFullScreenClasses(classPrefix, state) {
+ if (checkFullscreenWindows() && state === false) {
+ $([document.documentElement, document.body]).removeClass(classPrefix + 'fullscreen');
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function checkFullscreenWindows() {
- for (var i = 0; i < windows.length; i++) {
- if (windows[i]._fullscreen) {
- return true;
- }
- }
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function checkFullscreenWindows() {
+ for (var i = 0; i < windows.length; i++) {
+ if (windows[i]._fullscreen) {
+ return true;
+ }
+ }
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function handleWindowResize() {
- if (!Env.desktop) {
- var lastSize = {
- w: window.innerWidth,
- h: window.innerHeight
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function handleWindowResize() {
+ if (!Env.desktop) {
+ var lastSize = {
+ w: window.innerWidth,
+ h: window.innerHeight
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Delay.setInterval(function() {
- var w = window.innerWidth,
- h = window.innerHeight;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Delay.setInterval(function () {
+ var w = window.innerWidth,
+ h = window.innerHeight;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (lastSize.w != w || lastSize.h != h) {
- lastSize = {
- w: w,
- h: h
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (lastSize.w != w || lastSize.h != h) {
+ lastSize = {
+ w: w,
+ h: h
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $(window).trigger('resize');
- }
- }, 100);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $(window).trigger('resize');
+ }
+ }, 100);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function reposition() {
- var i, rect = DomUtils.getWindowSize(), layoutRect;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function reposition() {
+ var i, rect = DomUtils.getWindowSize(), layoutRect;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0; i < windows.length; i++) {
- layoutRect = windows[i].layoutRect();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0; i < windows.length; i++) {
+ layoutRect = windows[i].layoutRect();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- windows[i].moveTo(
- windows[i].settings.x || Math.max(0, rect.w / 2 - layoutRect.w / 2),
- windows[i].settings.y || Math.max(0, rect.h / 2 - layoutRect.h / 2)
- );
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ windows[i].moveTo(
+ windows[i].settings.x || Math.max(0, rect.w / 2 - layoutRect.w / 2),
+ windows[i].settings.y || Math.max(0, rect.h / 2 - layoutRect.h / 2)
+ );
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $(window).on('resize', reposition);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $(window).on('resize', reposition);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var Window = FloatPanel.extend({
- modal: true,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var Window = FloatPanel.extend({
+ modal: true,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Defaults: {
- border: 1,
- layout: 'flex',
- containerCls: 'panel',
- role: 'dialog',
- callbacks: {
- submit: function() {
- this.fire('submit', {data: this.toJSON()});
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Defaults: {
+ border: 1,
+ layout: 'flex',
+ containerCls: 'panel',
+ role: 'dialog',
+ callbacks: {
+ submit: function () {
+ this.fire('submit', { data: this.toJSON() });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- close: function() {
- this.close();
- }
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ close: function () {
+ this.close();
+ }
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- */
- init: function(settings) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ */
+ init: function (settings) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super(settings);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super(settings);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.isRtl()) {
- self.classes.add('rtl');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.isRtl()) {
+ self.classes.add('rtl');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.classes.add('window');
- self.bodyClasses.add('window-body');
- self.state.set('fixed', true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.classes.add('window');
+ self.bodyClasses.add('window-body');
+ self.state.set('fixed', true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Create statusbar
- if (settings.buttons) {
- self.statusbar = new Panel({
- layout: 'flex',
- border: '1 0 0 0',
- spacing: 3,
- padding: 10,
- align: 'center',
- pack: self.isRtl() ? 'start' : 'end',
- defaults: {
- type: 'button'
- },
- items: settings.buttons
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Create statusbar
+ if (settings.buttons) {
+ self.statusbar = new Panel({
+ layout: 'flex',
+ border: '1 0 0 0',
+ spacing: 3,
+ padding: 10,
+ align: 'center',
+ pack: self.isRtl() ? 'start' : 'end',
+ defaults: {
+ type: 'button'
+ },
+ items: settings.buttons
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.statusbar.classes.add('foot');
- self.statusbar.parent(self);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.statusbar.classes.add('foot');
+ self.statusbar.parent(self);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('click', function(e) {
- var closeClass = self.classPrefix + 'close';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('click', function (e) {
+ var closeClass = self.classPrefix + 'close';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (DomUtils.hasClass(e.target, closeClass) || DomUtils.hasClass(e.target.parentNode, closeClass)) {
- self.close();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (DomUtils.hasClass(e.target, closeClass) || DomUtils.hasClass(e.target.parentNode, closeClass)) {
+ self.close();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('cancel', function() {
- self.close();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('cancel', function () {
+ self.close();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.aria('describedby', self.describedBy || self._id + '-none');
- self.aria('label', settings.title);
- self._fullscreen = false;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.aria('describedby', self.describedBy || self._id + '-none');
+ self.aria('label', settings.title);
+ self._fullscreen = false;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Recalculates the positions of the controls in the current container.
- * This is invoked by the reflow method and shouldn't be called directly.
- *
- * @method recalc
- */
- recalc: function() {
- var self = this, statusbar = self.statusbar, layoutRect, width, x, needsRecalc;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Recalculates the positions of the controls in the current container.
+ * This is invoked by the reflow method and shouldn't be called directly.
+ *
+ * @method recalc
+ */
+ recalc: function () {
+ var self = this, statusbar = self.statusbar, layoutRect, width, x, needsRecalc;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self._fullscreen) {
- self.layoutRect(DomUtils.getWindowSize());
- self.layoutRect().contentH = self.layoutRect().innerH;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self._fullscreen) {
+ self.layoutRect(DomUtils.getWindowSize());
+ self.layoutRect().contentH = self.layoutRect().innerH;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- layoutRect = self.layoutRect();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ layoutRect = self.layoutRect();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Resize window based on title width
- if (self.settings.title && !self._fullscreen) {
- width = layoutRect.headerW;
- if (width > layoutRect.w) {
- x = layoutRect.x - Math.max(0, width / 2);
- self.layoutRect({w: width, x: x});
- needsRecalc = true;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Resize window based on title width
+ if (self.settings.title && !self._fullscreen) {
+ width = layoutRect.headerW;
+ if (width > layoutRect.w) {
+ x = layoutRect.x - Math.max(0, width / 2);
+ self.layoutRect({ w: width, x: x });
+ needsRecalc = true;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Resize window based on statusbar width
- if (statusbar) {
- statusbar.layoutRect({w: self.layoutRect().innerW}).recalc();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Resize window based on statusbar width
+ if (statusbar) {
+ statusbar.layoutRect({ w: self.layoutRect().innerW }).recalc();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- width = statusbar.layoutRect().minW + layoutRect.deltaW;
- if (width > layoutRect.w) {
- x = layoutRect.x - Math.max(0, width - layoutRect.w);
- self.layoutRect({w: width, x: x});
- needsRecalc = true;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ width = statusbar.layoutRect().minW + layoutRect.deltaW;
+ if (width > layoutRect.w) {
+ x = layoutRect.x - Math.max(0, width - layoutRect.w);
+ self.layoutRect({ w: width, x: x });
+ needsRecalc = true;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Recalc body and disable auto resize
- if (needsRecalc) {
- self.recalc();
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Recalc body and disable auto resize
+ if (needsRecalc) {
+ self.recalc();
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Initializes the current controls layout rect.
- * This will be executed by the layout managers to determine the
- * default minWidth/minHeight etc.
- *
- * @method initLayoutRect
- * @return {Object} Layout rect instance.
- */
- initLayoutRect: function() {
- var self = this, layoutRect = self._super(), deltaH = 0, headEl;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Initializes the current controls layout rect.
+ * This will be executed by the layout managers to determine the
+ * default minWidth/minHeight etc.
+ *
+ * @method initLayoutRect
+ * @return {Object} Layout rect instance.
+ */
+ initLayoutRect: function () {
+ var self = this, layoutRect = self._super(), deltaH = 0, headEl;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Reserve vertical space for title
- if (self.settings.title && !self._fullscreen) {
- headEl = self.getEl('head');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Reserve vertical space for title
+ if (self.settings.title && !self._fullscreen) {
+ headEl = self.getEl('head');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var size = DomUtils.getSize(headEl);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var size = DomUtils.getSize(headEl);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- layoutRect.headerW = size.width;
- layoutRect.headerH = size.height;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ layoutRect.headerW = size.width;
+ layoutRect.headerH = size.height;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- deltaH += layoutRect.headerH;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ deltaH += layoutRect.headerH;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Reserve vertical space for statusbar
- if (self.statusbar) {
- deltaH += self.statusbar.layoutRect().h;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Reserve vertical space for statusbar
+ if (self.statusbar) {
+ deltaH += self.statusbar.layoutRect().h;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- layoutRect.deltaH += deltaH;
- layoutRect.minH += deltaH;
- //layoutRect.innerH -= deltaH;
- layoutRect.h += deltaH;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ layoutRect.deltaH += deltaH;
+ layoutRect.minH += deltaH;
+ //layoutRect.innerH -= deltaH;
+ layoutRect.h += deltaH;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var rect = DomUtils.getWindowSize();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var rect = DomUtils.getWindowSize();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- layoutRect.x = self.settings.x || Math.max(0, rect.w / 2 - layoutRect.w / 2);
- layoutRect.y = self.settings.y || Math.max(0, rect.h / 2 - layoutRect.h / 2);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ layoutRect.x = self.settings.x || Math.max(0, rect.w / 2 - layoutRect.w / 2);
+ layoutRect.y = self.settings.y || Math.max(0, rect.h / 2 - layoutRect.h / 2);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return layoutRect;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return layoutRect;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this, layout = self._layout, id = self._id, prefix = self.classPrefix;
- var settings = self.settings, headerHtml = '', footerHtml = '', html = settings.html;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this, layout = self._layout, id = self._id, prefix = self.classPrefix;
+ var settings = self.settings, headerHtml = '', footerHtml = '', html = settings.html;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.preRender();
- layout.preRender(self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.preRender();
+ layout.preRender(self);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.title) {
- headerHtml = (
- '<div id="' + id + '-head" class="' + prefix + 'window-head">' +
- '<div id="' + id + '-title" class="' + prefix + 'title">' + self.encode(settings.title) + '</div>' +
- '<div id="' + id + '-dragh" class="' + prefix + 'dragh"></div>' +
- '<button type="button" class="' + prefix + 'close" aria-hidden="true">' +
- '<i class="mce-ico mce-i-remove"></i>' +
- '</button>' +
- '</div>'
- );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.title) {
+ headerHtml = (
+ '<div id="' + id + '-head" class="' + prefix + 'window-head">' +
+ '<div id="' + id + '-title" class="' + prefix + 'title">' + self.encode(settings.title) + '</div>' +
+ '<div id="' + id + '-dragh" class="' + prefix + 'dragh"></div>' +
+ '<button type="button" class="' + prefix + 'close" aria-hidden="true">' +
+ '<i class="mce-ico mce-i-remove"></i>' +
+ '</button>' +
+ '</div>'
+ );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.url) {
- html = '<iframe src="' + settings.url + '" tabindex="-1"></iframe>';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.url) {
+ html = '<iframe src="' + settings.url + '" tabindex="-1"></iframe>';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof html == "undefined") {
- html = layout.renderHtml(self);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof html == "undefined") {
+ html = layout.renderHtml(self);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.statusbar) {
- footerHtml = self.statusbar.renderHtml();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.statusbar) {
+ footerHtml = self.statusbar.renderHtml();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<div id="' + id + '" class="' + self.classes + '" hidefocus="1">' +
- '<div class="' + self.classPrefix + 'reset" role="application">' +
- headerHtml +
- '<div id="' + id + '-body" class="' + self.bodyClasses + '">' +
- html +
- '</div>' +
- footerHtml +
- '</div>' +
- '</div>'
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<div id="' + id + '" class="' + self.classes + '" hidefocus="1">' +
+ '<div class="' + self.classPrefix + 'reset" role="application">' +
+ headerHtml +
+ '<div id="' + id + '-body" class="' + self.bodyClasses + '">' +
+ html +
+ '</div>' +
+ footerHtml +
+ '</div>' +
+ '</div>'
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Switches the window fullscreen mode.
- *
- * @method fullscreen
- * @param {Boolean} state True/false state.
- * @return {tinymce.ui.Window} Current window instance.
- */
- fullscreen: function(state) {
- var self = this, documentElement = document.documentElement, slowRendering, prefix = self.classPrefix, layoutRect;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Switches the window fullscreen mode.
+ *
+ * @method fullscreen
+ * @param {Boolean} state True/false state.
+ * @return {tinymce.ui.Window} Current window instance.
+ */
+ fullscreen: function (state) {
+ var self = this, documentElement = document.documentElement, slowRendering, prefix = self.classPrefix, layoutRect;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (state != self._fullscreen) {
- $(window).on('resize', function() {
- var time;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (state != self._fullscreen) {
+ $(window).on('resize', function () {
+ var time;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self._fullscreen) {
- // Time the layout time if it's to slow use a timeout to not hog the CPU
- if (!slowRendering) {
- time = new Date().getTime();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self._fullscreen) {
+ // Time the layout time if it's to slow use a timeout to not hog the CPU
+ if (!slowRendering) {
+ time = new Date().getTime();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var rect = DomUtils.getWindowSize();
- self.moveTo(0, 0).resizeTo(rect.w, rect.h);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var rect = DomUtils.getWindowSize();
+ self.moveTo(0, 0).resizeTo(rect.w, rect.h);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ((new Date().getTime()) - time > 50) {
- slowRendering = true;
- }
- } else {
- if (!self._timer) {
- self._timer = Delay.setTimeout(function() {
- var rect = DomUtils.getWindowSize();
- self.moveTo(0, 0).resizeTo(rect.w, rect.h);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((new Date().getTime()) - time > 50) {
+ slowRendering = true;
+ }
+ } else {
+ if (!self._timer) {
+ self._timer = Delay.setTimeout(function () {
+ var rect = DomUtils.getWindowSize();
+ self.moveTo(0, 0).resizeTo(rect.w, rect.h);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._timer = 0;
- }, 50);
- }
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._timer = 0;
+ }, 50);
+ }
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- layoutRect = self.layoutRect();
- self._fullscreen = state;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ layoutRect = self.layoutRect();
+ self._fullscreen = state;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!state) {
- self.borderBox = BoxUtils.parseBox(self.settings.border);
- self.getEl('head').style.display = '';
- layoutRect.deltaH += layoutRect.headerH;
- $([documentElement, document.body]).removeClass(prefix + 'fullscreen');
- self.classes.remove('fullscreen');
- self.moveTo(self._initial.x, self._initial.y).resizeTo(self._initial.w, self._initial.h);
- } else {
- self._initial = {x: layoutRect.x, y: layoutRect.y, w: layoutRect.w, h: layoutRect.h};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!state) {
+ self.borderBox = BoxUtils.parseBox(self.settings.border);
+ self.getEl('head').style.display = '';
+ layoutRect.deltaH += layoutRect.headerH;
+ $([documentElement, document.body]).removeClass(prefix + 'fullscreen');
+ self.classes.remove('fullscreen');
+ self.moveTo(self._initial.x, self._initial.y).resizeTo(self._initial.w, self._initial.h);
+ } else {
+ self._initial = { x: layoutRect.x, y: layoutRect.y, w: layoutRect.w, h: layoutRect.h };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.borderBox = BoxUtils.parseBox('0');
- self.getEl('head').style.display = 'none';
- layoutRect.deltaH -= layoutRect.headerH + 2;
- $([documentElement, document.body]).addClass(prefix + 'fullscreen');
- self.classes.add('fullscreen');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.borderBox = BoxUtils.parseBox('0');
+ self.getEl('head').style.display = 'none';
+ layoutRect.deltaH -= layoutRect.headerH + 2;
+ $([documentElement, document.body]).addClass(prefix + 'fullscreen');
+ self.classes.add('fullscreen');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var rect = DomUtils.getWindowSize();
- self.moveTo(0, 0).resizeTo(rect.w, rect.h);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var rect = DomUtils.getWindowSize();
+ self.moveTo(0, 0).resizeTo(rect.w, rect.h);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self.reflow();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self.reflow();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Called after the control has been rendered.
- *
- * @method postRender
- */
- postRender: function() {
- var self = this, startPos;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Called after the control has been rendered.
+ *
+ * @method postRender
+ */
+ postRender: function () {
+ var self = this, startPos;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- setTimeout(function() {
- self.classes.add('in');
- self.fire('open');
- }, 0);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ setTimeout(function () {
+ self.classes.add('in');
+ self.fire('open');
+ }, 0);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.statusbar) {
- self.statusbar.postRender();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.statusbar) {
+ self.statusbar.postRender();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.focus();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.focus();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.dragHelper = new DragHelper(self._id + '-dragh', {
- start: function() {
- startPos = {
- x: self.layoutRect().x,
- y: self.layoutRect().y
- };
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.dragHelper = new DragHelper(self._id + '-dragh', {
+ start: function () {
+ startPos = {
+ x: self.layoutRect().x,
+ y: self.layoutRect().y
+ };
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- drag: function(e) {
- self.moveTo(startPos.x + e.deltaX, startPos.y + e.deltaY);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ drag: function (e) {
+ self.moveTo(startPos.x + e.deltaX, startPos.y + e.deltaY);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('submit', function(e) {
- if (!e.isDefaultPrevented()) {
- self.close();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('submit', function (e) {
+ if (!e.isDefaultPrevented()) {
+ self.close();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- windows.push(self);
- toggleFullScreenState(true);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ windows.push(self);
+ toggleFullScreenState(true);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Fires a submit event with the serialized form.
- *
- * @method submit
- * @return {Object} Event arguments object.
- */
- submit: function() {
- return this.fire('submit', {data: this.toJSON()});
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Fires a submit event with the serialized form.
+ *
+ * @method submit
+ * @return {Object} Event arguments object.
+ */
+ submit: function () {
+ return this.fire('submit', { data: this.toJSON() });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes the current control from DOM and from UI collections.
- *
- * @method remove
- * @return {tinymce.ui.Control} Current control instance.
- */
- remove: function() {
- var self = this, i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes the current control from DOM and from UI collections.
+ *
+ * @method remove
+ * @return {tinymce.ui.Control} Current control instance.
+ */
+ remove: function () {
+ var self = this, i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.dragHelper.destroy();
- self._super();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.dragHelper.destroy();
+ self._super();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.statusbar) {
- this.statusbar.remove();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.statusbar) {
+ this.statusbar.remove();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- toggleBodyFullScreenClasses(self.classPrefix, false);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ toggleBodyFullScreenClasses(self.classPrefix, false);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- i = windows.length;
- while (i--) {
- if (windows[i] === self) {
- windows.splice(i, 1);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ i = windows.length;
+ while (i--) {
+ if (windows[i] === self) {
+ windows.splice(i, 1);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- toggleFullScreenState(windows.length > 0);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ toggleFullScreenState(windows.length > 0);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the contentWindow object of the iframe if it exists.
- *
- * @method getContentWindow
- * @return {Window} window object or null.
- */
- getContentWindow: function() {
- var ifr = this.getEl().getElementsByTagName('iframe')[0];
- return ifr ? ifr.contentWindow : null;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the contentWindow object of the iframe if it exists.
+ *
+ * @method getContentWindow
+ * @return {Window} window object or null.
+ */
+ getContentWindow: function () {
+ var ifr = this.getEl().getElementsByTagName('iframe')[0];
+ return ifr ? ifr.contentWindow : null;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- handleWindowResize();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ handleWindowResize();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Window;
-});
-
-// Included from: js/tinymce/classes/ui/MessageBox.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Window;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * MessageBox.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -31695,200 +35812,202 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.MessageBox
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.FloatPanel
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/MessageBox", [
- "tinymce/ui/Window"
-], function(Window) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.MessageBox',
+ [
+ "tinymce.core.ui.Window"
+ ],
+ function (Window) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var MessageBox = Window.extend({
- /**
- * Constructs a instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- */
- init: function(settings) {
- settings = {
- border: 1,
- padding: 20,
- layout: 'flex',
- pack: "center",
- align: "center",
- containerCls: 'panel',
- autoScroll: true,
- buttons: {type: "button", text: "Ok", action: "ok"},
- items: {
- type: "label",
- multiline: true,
- maxWidth: 500,
- maxHeight: 200
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var MessageBox = Window.extend({
+ /**
+ * Constructs a instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ */
+ init: function (settings) {
+ settings = {
+ border: 1,
+ padding: 20,
+ layout: 'flex',
+ pack: "center",
+ align: "center",
+ containerCls: 'panel',
+ autoScroll: true,
+ buttons: { type: "button", text: "Ok", action: "ok" },
+ items: {
+ type: "label",
+ multiline: true,
+ maxWidth: 500,
+ maxHeight: 200
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this._super(settings);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this._super(settings);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Statics: {
- /**
- * Ok buttons constant.
- *
- * @static
- * @final
- * @field {Number} OK
- */
- OK: 1,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Statics: {
+ /**
+ * Ok buttons constant.
+ *
+ * @static
+ * @final
+ * @field {Number} OK
+ */
+ OK: 1,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Ok/cancel buttons constant.
- *
- * @static
- * @final
- * @field {Number} OK_CANCEL
- */
- OK_CANCEL: 2,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Ok/cancel buttons constant.
+ *
+ * @static
+ * @final
+ * @field {Number} OK_CANCEL
+ */
+ OK_CANCEL: 2,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * yes/no buttons constant.
- *
- * @static
- * @final
- * @field {Number} YES_NO
- */
- YES_NO: 3,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * yes/no buttons constant.
+ *
+ * @static
+ * @final
+ * @field {Number} YES_NO
+ */
+ YES_NO: 3,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * yes/no/cancel buttons constant.
- *
- * @static
- * @final
- * @field {Number} YES_NO_CANCEL
- */
- YES_NO_CANCEL: 4,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * yes/no/cancel buttons constant.
+ *
+ * @static
+ * @final
+ * @field {Number} YES_NO_CANCEL
+ */
+ YES_NO_CANCEL: 4,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a new message box and renders it to the body element.
- *
- * @static
- * @method msgBox
- * @param {Object} settings Name/value object with settings.
- */
- msgBox: function(settings) {
- var buttons, callback = settings.callback || function() {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a new message box and renders it to the body element.
+ *
+ * @static
+ * @method msgBox
+ * @param {Object} settings Name/value object with settings.
+ */
+ msgBox: function (settings) {
+ var buttons, callback = settings.callback || function () { };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function createButton(text, status, primary) {
- return {
- type: "button",
- text: text,
- subtype: primary ? 'primary' : '',
- onClick: function(e) {
- e.control.parents()[1].close();
- callback(status);
- }
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function createButton(text, status, primary) {
+ return {
+ type: "button",
+ text: text,
+ subtype: primary ? 'primary' : '',
+ onClick: function (e) {
+ e.control.parents()[1].close();
+ callback(status);
+ }
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- switch (settings.buttons) {
- case MessageBox.OK_CANCEL:
- buttons = [
- createButton('Ok', true, true),
- createButton('Cancel', false)
- ];
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ switch (settings.buttons) {
+ case MessageBox.OK_CANCEL:
+ buttons = [
+ createButton('Ok', true, true),
+ createButton('Cancel', false)
+ ];
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case MessageBox.YES_NO:
- case MessageBox.YES_NO_CANCEL:
- buttons = [
- createButton('Yes', 1, true),
- createButton('No', 0)
- ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case MessageBox.YES_NO:
+ case MessageBox.YES_NO_CANCEL:
+ buttons = [
+ createButton('Yes', 1, true),
+ createButton('No', 0)
+ ];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.buttons == MessageBox.YES_NO_CANCEL) {
- buttons.push(createButton('Cancel', -1));
- }
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.buttons == MessageBox.YES_NO_CANCEL) {
+ buttons.push(createButton('Cancel', -1));
+ }
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- default:
- buttons = [
- createButton('Ok', true, true)
- ];
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ default:
+ buttons = [
+ createButton('Ok', true, true)
+ ];
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return new Window({
- padding: 20,
- x: settings.x,
- y: settings.y,
- minWidth: 300,
- minHeight: 100,
- layout: "flex",
- pack: "center",
- align: "center",
- buttons: buttons,
- title: settings.title,
- role: 'alertdialog',
- items: {
- type: "label",
- multiline: true,
- maxWidth: 500,
- maxHeight: 200,
- text: settings.text
- },
- onPostRender: function() {
- this.aria('describedby', this.items()[0]._id);
- },
- onClose: settings.onClose,
- onCancel: function() {
- callback(false);
- }
- }).renderTo(document.body).reflow();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return new Window({
+ padding: 20,
+ x: settings.x,
+ y: settings.y,
+ minWidth: 300,
+ minHeight: 100,
+ layout: "flex",
+ pack: "center",
+ align: "center",
+ buttons: buttons,
+ title: settings.title,
+ role: 'alertdialog',
+ items: {
+ type: "label",
+ multiline: true,
+ maxWidth: 500,
+ maxHeight: 200,
+ text: settings.text
+ },
+ onPostRender: function () {
+ this.aria('describedby', this.items()[0]._id);
+ },
+ onClose: settings.onClose,
+ onCancel: function () {
+ callback(false);
+ }
+ }).renderTo(document.body).reflow();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates a new alert dialog.
- *
- * @method alert
- * @param {Object} settings Settings for the alert dialog.
- * @param {function} [callback] Callback to execute when the user makes a choice.
- */
- alert: function(settings, callback) {
- if (typeof settings == "string") {
- settings = {text: settings};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates a new alert dialog.
+ *
+ * @method alert
+ * @param {Object} settings Settings for the alert dialog.
+ * @param {function} [callback] Callback to execute when the user makes a choice.
+ */
+ alert: function (settings, callback) {
+ if (typeof settings == "string") {
+ settings = { text: settings };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- settings.callback = callback;
- return MessageBox.msgBox(settings);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ settings.callback = callback;
+ return MessageBox.msgBox(settings);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates a new confirm dialog.
- *
- * @method confirm
- * @param {Object} settings Settings for the confirm dialog.
- * @param {function} [callback] Callback to execute when the user makes a choice.
- */
- confirm: function(settings, callback) {
- if (typeof settings == "string") {
- settings = {text: settings};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates a new confirm dialog.
+ *
+ * @method confirm
+ * @param {Object} settings Settings for the confirm dialog.
+ * @param {function} [callback] Callback to execute when the user makes a choice.
+ */
+ confirm: function (settings, callback) {
+ if (typeof settings == "string") {
+ settings = { text: settings };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- settings.callback = callback;
- settings.buttons = MessageBox.OK_CANCEL;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ settings.callback = callback;
+ settings.buttons = MessageBox.OK_CANCEL;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return MessageBox.msgBox(settings);
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return MessageBox.msgBox(settings);
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return MessageBox;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return MessageBox;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/WindowManager.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * WindowManager.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -31920,256 +36039,262 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * tinymce.activeEditor.windowManager.alert("Cancel");
</span><span class="cx" style="display: block; padding: 0 10px"> * });
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/WindowManager", [
- "tinymce/ui/Window",
- "tinymce/ui/MessageBox"
-], function(Window, MessageBox) {
- return function(editor) {
- var self = this, windows = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.WindowManager',
+ [
+ "tinymce.core.ui.Window",
+ "tinymce.core.ui.MessageBox"
+ ],
+ function (Window, MessageBox) {
+ return function (editor) {
+ var self = this, windows = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getTopMostWindow() {
- if (windows.length) {
- return windows[windows.length - 1];
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getTopMostWindow() {
+ if (windows.length) {
+ return windows[windows.length - 1];
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function fireOpenEvent(win) {
- editor.fire('OpenWindow', {
- win: win
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function fireOpenEvent(win) {
+ editor.fire('OpenWindow', {
+ win: win
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function fireCloseEvent(win) {
- editor.fire('CloseWindow', {
- win: win
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function fireCloseEvent(win) {
+ editor.fire('CloseWindow', {
+ win: win
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.windows = windows;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.windows = windows;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('remove', function() {
- var i = windows.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('remove', function () {
+ var i = windows.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- windows[i].close();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ windows[i].close();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Opens a new window.
- *
- * @method open
- * @param {Object} args Optional name/value settings collection contains things like width/height/url etc.
- * @param {Object} params Options like title, file, width, height etc.
- * @option {String} title Window title.
- * @option {String} file URL of the file to open in the window.
- * @option {Number} width Width in pixels.
- * @option {Number} height Height in pixels.
- * @option {Boolean} autoScroll Specifies whether the popup window can have scrollbars if required (i.e. content
- * larger than the popup size specified).
- */
- self.open = function(args, params) {
- var win;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Opens a new window.
+ *
+ * @method open
+ * @param {Object} args Optional name/value settings collection contains things like width/height/url etc.
+ * @param {Object} params Options like title, file, width, height etc.
+ * @option {String} title Window title.
+ * @option {String} file URL of the file to open in the window.
+ * @option {Number} width Width in pixels.
+ * @option {Number} height Height in pixels.
+ * @option {Boolean} autoScroll Specifies whether the popup window can have scrollbars if required (i.e. content
+ * larger than the popup size specified).
+ */
+ self.open = function (args, params) {
+ var win;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.editorManager.setActive(editor);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.editorManager.setActive(editor);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args.title = args.title || ' ';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args.title = args.title || ' ';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle URL
- args.url = args.url || args.file; // Legacy
- if (args.url) {
- args.width = parseInt(args.width || 320, 10);
- args.height = parseInt(args.height || 240, 10);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handle URL
+ args.url = args.url || args.file; // Legacy
+ if (args.url) {
+ args.width = parseInt(args.width || 320, 10);
+ args.height = parseInt(args.height || 240, 10);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle body
- if (args.body) {
- args.items = {
- defaults: args.defaults,
- type: args.bodyType || 'form',
- items: args.body,
- data: args.data,
- callbacks: args.commands
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handle body
+ if (args.body) {
+ args.items = {
+ defaults: args.defaults,
+ type: args.bodyType || 'form',
+ items: args.body,
+ data: args.data,
+ callbacks: args.commands
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!args.url && !args.buttons) {
- args.buttons = [
- {text: 'Ok', subtype: 'primary', onclick: function() {
- win.find('form')[0].submit();
- }},
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!args.url && !args.buttons) {
+ args.buttons = [
+ {
+ text: 'Ok', subtype: 'primary', onclick: function () {
+ win.find('form')[0].submit();
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- {text: 'Cancel', onclick: function() {
- win.close();
- }}
- ];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ {
+ text: 'Cancel', onclick: function () {
+ win.close();
+ }
+ }
+ ];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- win = new Window(args);
- windows.push(win);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ win = new Window(args);
+ windows.push(win);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- win.on('close', function() {
- var i = windows.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ win.on('close', function () {
+ var i = windows.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- if (windows[i] === win) {
- windows.splice(i, 1);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ if (windows[i] === win) {
+ windows.splice(i, 1);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!windows.length) {
- editor.focus();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!windows.length) {
+ editor.focus();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- fireCloseEvent(win);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ fireCloseEvent(win);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle data
- if (args.data) {
- win.on('postRender', function() {
- this.find('*').each(function(ctrl) {
- var name = ctrl.name();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handle data
+ if (args.data) {
+ win.on('postRender', function () {
+ this.find('*').each(function (ctrl) {
+ var name = ctrl.name();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name in args.data) {
- ctrl.value(args.data[name]);
- }
- });
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name in args.data) {
+ ctrl.value(args.data[name]);
+ }
+ });
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // store args and parameters
- win.features = args || {};
- win.params = params || {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // store args and parameters
+ win.features = args || {};
+ win.params = params || {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Takes a snapshot in the FocusManager of the selection before focus is lost to dialog
- if (windows.length === 1) {
- editor.nodeChanged();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Takes a snapshot in the FocusManager of the selection before focus is lost to dialog
+ if (windows.length === 1) {
+ editor.nodeChanged();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- win = win.renderTo().reflow();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ win = win.renderTo().reflow();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- fireOpenEvent(win);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ fireOpenEvent(win);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return win;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return win;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates a alert dialog. Please don't use the blocking behavior of this
- * native version use the callback method instead then it can be extended.
- *
- * @method alert
- * @param {String} message Text to display in the new alert dialog.
- * @param {function} callback Callback function to be executed after the user has selected ok.
- * @param {Object} scope Optional scope to execute the callback in.
- * @example
- * // Displays an alert box using the active editors window manager instance
- * tinymce.activeEditor.windowManager.alert('Hello world!');
- */
- self.alert = function(message, callback, scope) {
- var win;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates a alert dialog. Please don't use the blocking behavior of this
+ * native version use the callback method instead then it can be extended.
+ *
+ * @method alert
+ * @param {String} message Text to display in the new alert dialog.
+ * @param {function} callback Callback function to be executed after the user has selected ok.
+ * @param {Object} scope Optional scope to execute the callback in.
+ * @example
+ * // Displays an alert box using the active editors window manager instance
+ * tinymce.activeEditor.windowManager.alert('Hello world!');
+ */
+ self.alert = function (message, callback, scope) {
+ var win;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- win = MessageBox.alert(message, function() {
- if (callback) {
- callback.call(scope || this);
- } else {
- editor.focus();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ win = MessageBox.alert(message, function () {
+ if (callback) {
+ callback.call(scope || this);
+ } else {
+ editor.focus();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- win.on('close', function() {
- fireCloseEvent(win);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ win.on('close', function () {
+ fireCloseEvent(win);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- fireOpenEvent(win);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ fireOpenEvent(win);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates a confirm dialog. Please don't use the blocking behavior of this
- * native version use the callback method instead then it can be extended.
- *
- * @method confirm
- * @param {String} message Text to display in the new confirm dialog.
- * @param {function} callback Callback function to be executed after the user has selected ok or cancel.
- * @param {Object} scope Optional scope to execute the callback in.
- * @example
- * // Displays an confirm box and an alert message will be displayed depending on what you choose in the confirm
- * tinymce.activeEditor.windowManager.confirm("Do you want to do something", function(s) {
- * if (s)
- * tinymce.activeEditor.windowManager.alert("Ok");
- * else
- * tinymce.activeEditor.windowManager.alert("Cancel");
- * });
- */
- self.confirm = function(message, callback, scope) {
- var win;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates a confirm dialog. Please don't use the blocking behavior of this
+ * native version use the callback method instead then it can be extended.
+ *
+ * @method confirm
+ * @param {String} message Text to display in the new confirm dialog.
+ * @param {function} callback Callback function to be executed after the user has selected ok or cancel.
+ * @param {Object} scope Optional scope to execute the callback in.
+ * @example
+ * // Displays an confirm box and an alert message will be displayed depending on what you choose in the confirm
+ * tinymce.activeEditor.windowManager.confirm("Do you want to do something", function(s) {
+ * if (s)
+ * tinymce.activeEditor.windowManager.alert("Ok");
+ * else
+ * tinymce.activeEditor.windowManager.alert("Cancel");
+ * });
+ */
+ self.confirm = function (message, callback, scope) {
+ var win;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- win = MessageBox.confirm(message, function(state) {
- callback.call(scope || this, state);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ win = MessageBox.confirm(message, function (state) {
+ callback.call(scope || this, state);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- win.on('close', function() {
- fireCloseEvent(win);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ win.on('close', function () {
+ fireCloseEvent(win);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- fireOpenEvent(win);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ fireOpenEvent(win);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Closes the top most window.
- *
- * @method close
- */
- self.close = function() {
- if (getTopMostWindow()) {
- getTopMostWindow().close();
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Closes the top most window.
+ *
+ * @method close
+ */
+ self.close = function () {
+ if (getTopMostWindow()) {
+ getTopMostWindow().close();
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the params of the last window open call. This can be used in iframe based
- * dialog to get params passed from the tinymce plugin.
- *
- * @example
- * var dialogArguments = top.tinymce.activeEditor.windowManager.getParams();
- *
- * @method getParams
- * @return {Object} Name/value object with parameters passed from windowManager.open call.
- */
- self.getParams = function() {
- return getTopMostWindow() ? getTopMostWindow().params : null;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the params of the last window open call. This can be used in iframe based
+ * dialog to get params passed from the tinymce plugin.
+ *
+ * @example
+ * var dialogArguments = top.tinymce.activeEditor.windowManager.getParams();
+ *
+ * @method getParams
+ * @return {Object} Name/value object with parameters passed from windowManager.open call.
+ */
+ self.getParams = function () {
+ return getTopMostWindow() ? getTopMostWindow().params : null;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets the params of the last opened window.
- *
- * @method setParams
- * @param {Object} params Params object to set for the last opened window.
- */
- self.setParams = function(params) {
- if (getTopMostWindow()) {
- getTopMostWindow().params = params;
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets the params of the last opened window.
+ *
+ * @method setParams
+ * @param {Object} params Params object to set for the last opened window.
+ */
+ self.setParams = function (params) {
+ if (getTopMostWindow()) {
+ getTopMostWindow().params = params;
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the currently opened window objects.
- *
- * @method getWindows
- * @return {Array} Array of the currently opened windows.
- */
- self.getWindows = function() {
- return windows;
- };
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the currently opened window objects.
+ *
+ * @method getWindows
+ * @return {Array} Array of the currently opened windows.
+ */
+ self.getWindows = function () {
+ return windows;
+ };
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/Tooltip.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Tooltip.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -32183,69 +36308,70 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Control
</span><span class="cx" style="display: block; padding: 0 10px"> * @mixes tinymce.ui.Movable
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Tooltip", [
- "tinymce/ui/Control",
- "tinymce/ui/Movable"
-], function(Control, Movable) {
- return Control.extend({
- Mixins: [Movable],
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Tooltip',
+ [
+ "tinymce.core.ui.Control",
+ "tinymce.core.ui.Movable"
+ ],
+ function (Control, Movable) {
+ return Control.extend({
+ Mixins: [Movable],
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Defaults: {
- classes: 'widget tooltip tooltip-n'
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Defaults: {
+ classes: 'widget tooltip tooltip-n'
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this, prefix = self.classPrefix;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this, prefix = self.classPrefix;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<div id="' + self._id + '" class="' + self.classes + '" role="presentation">' +
- '<div class="' + prefix + 'tooltip-arrow"></div>' +
- '<div class="' + prefix + 'tooltip-inner">' + self.encode(self.state.get('text')) + '</div>' +
- '</div>'
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<div id="' + self._id + '" class="' + self.classes + '" role="presentation">' +
+ '<div class="' + prefix + 'tooltip-arrow"></div>' +
+ '<div class="' + prefix + 'tooltip-inner">' + self.encode(self.state.get('text')) + '</div>' +
+ '</div>'
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bindStates: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bindStates: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:text', function(e) {
- self.getEl().lastChild.innerHTML = self.encode(e.value);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:text', function (e) {
+ self.getEl().lastChild.innerHTML = self.encode(e.value);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Repaints the control after a layout operation.
- *
- * @method repaint
- */
- repaint: function() {
- var self = this, style, rect;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Repaints the control after a layout operation.
+ *
+ * @method repaint
+ */
+ repaint: function () {
+ var self = this, style, rect;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- style = self.getEl().style;
- rect = self._layoutRect;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ style = self.getEl().style;
+ rect = self._layoutRect;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- style.left = rect.x + 'px';
- style.top = rect.y + 'px';
- style.zIndex = 0xFFFF + 0xFFFF;
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/Widget.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ style.left = rect.x + 'px';
+ style.top = rect.y + 'px';
+ style.zIndex = 0xFFFF + 0xFFFF;
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Widget.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -32257,149 +36383,151 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.Widget
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Control
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Widget", [
- "tinymce/ui/Control",
- "tinymce/ui/Tooltip"
-], function(Control, Tooltip) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Widget',
+ [
+ "tinymce.core.ui.Control",
+ "tinymce.core.ui.Tooltip"
+ ],
+ function (Control, Tooltip) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var tooltip;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var tooltip;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var Widget = Control.extend({
- /**
- * Constructs a instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- * @setting {String} tooltip Tooltip text to display when hovering.
- * @setting {Boolean} autofocus True if the control should be focused when rendered.
- * @setting {String} text Text to display inside widget.
- */
- init: function(settings) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var Widget = Control.extend({
+ /**
+ * Constructs a instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ * @setting {String} tooltip Tooltip text to display when hovering.
+ * @setting {Boolean} autofocus True if the control should be focused when rendered.
+ * @setting {String} text Text to display inside widget.
+ */
+ init: function (settings) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super(settings);
- settings = self.settings;
- self.canFocus = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super(settings);
+ settings = self.settings;
+ self.canFocus = true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.tooltip && Widget.tooltips !== false) {
- self.on('mouseenter', function(e) {
- var tooltip = self.tooltip().moveTo(-0xFFFF);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.tooltip && Widget.tooltips !== false) {
+ self.on('mouseenter', function (e) {
+ var tooltip = self.tooltip().moveTo(-0xFFFF);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.control == self) {
- var rel = tooltip.text(settings.tooltip).show().testMoveRel(self.getEl(), ['bc-tc', 'bc-tl', 'bc-tr']);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.control == self) {
+ var rel = tooltip.text(settings.tooltip).show().testMoveRel(self.getEl(), ['bc-tc', 'bc-tl', 'bc-tr']);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tooltip.classes.toggle('tooltip-n', rel == 'bc-tc');
- tooltip.classes.toggle('tooltip-nw', rel == 'bc-tl');
- tooltip.classes.toggle('tooltip-ne', rel == 'bc-tr');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ tooltip.classes.toggle('tooltip-n', rel == 'bc-tc');
+ tooltip.classes.toggle('tooltip-nw', rel == 'bc-tl');
+ tooltip.classes.toggle('tooltip-ne', rel == 'bc-tr');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tooltip.moveRel(self.getEl(), rel);
- } else {
- tooltip.hide();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ tooltip.moveRel(self.getEl(), rel);
+ } else {
+ tooltip.hide();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('mouseleave mousedown click', function() {
- self.tooltip().hide();
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('mouseleave mousedown click', function () {
+ self.tooltip().hide();
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.aria('label', settings.ariaLabel || settings.tooltip);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.aria('label', settings.ariaLabel || settings.tooltip);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the current tooltip instance.
- *
- * @method tooltip
- * @return {tinymce.ui.Tooltip} Tooltip instance.
- */
- tooltip: function() {
- if (!tooltip) {
- tooltip = new Tooltip({type: 'tooltip'});
- tooltip.renderTo();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the current tooltip instance.
+ *
+ * @method tooltip
+ * @return {tinymce.ui.Tooltip} Tooltip instance.
+ */
+ tooltip: function () {
+ if (!tooltip) {
+ tooltip = new Tooltip({ type: 'tooltip' });
+ tooltip.renderTo();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return tooltip;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return tooltip;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Called after the control has been rendered.
- *
- * @method postRender
- */
- postRender: function() {
- var self = this, settings = self.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Called after the control has been rendered.
+ *
+ * @method postRender
+ */
+ postRender: function () {
+ var self = this, settings = self.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.parent() && (settings.width || settings.height)) {
- self.initLayoutRect();
- self.repaint();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.parent() && (settings.width || settings.height)) {
+ self.initLayoutRect();
+ self.repaint();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.autofocus) {
- self.focus();
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.autofocus) {
+ self.focus();
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bindStates: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bindStates: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function disable(state) {
- self.aria('disabled', state);
- self.classes.toggle('disabled', state);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function disable(state) {
+ self.aria('disabled', state);
+ self.classes.toggle('disabled', state);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function active(state) {
- self.aria('pressed', state);
- self.classes.toggle('active', state);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function active(state) {
+ self.aria('pressed', state);
+ self.classes.toggle('active', state);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:disabled', function(e) {
- disable(e.value);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:disabled', function (e) {
+ disable(e.value);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:active', function(e) {
- active(e.value);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:active', function (e) {
+ active(e.value);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.state.get('disabled')) {
- disable(true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.state.get('disabled')) {
+ disable(true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.state.get('active')) {
- active(true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.state.get('active')) {
+ active(true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes the current control from DOM and from UI collections.
- *
- * @method remove
- * @return {tinymce.ui.Control} Current control instance.
- */
- remove: function() {
- this._super();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes the current control from DOM and from UI collections.
+ *
+ * @method remove
+ * @return {tinymce.ui.Control} Current control instance.
+ */
+ remove: function () {
+ this._super();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (tooltip) {
- tooltip.remove();
- tooltip = null;
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (tooltip) {
+ tooltip.remove();
+ tooltip = null;
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Widget;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Widget;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/Progress.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Progress.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -32412,78 +36540,79 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.Progress
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Control
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Progress", [
- "tinymce/ui/Widget"
-], function(Widget) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Progress',
+ [
+ "tinymce.core.ui.Widget"
+ ],
+ function (Widget) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Widget.extend({
- Defaults: {
- value: 0
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Widget.extend({
+ Defaults: {
+ value: 0
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- init: function(settings) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ init: function (settings) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super(settings);
- self.classes.add('progress');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super(settings);
+ self.classes.add('progress');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.settings.filter) {
- self.settings.filter = function(value) {
- return Math.round(value);
- };
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.settings.filter) {
+ self.settings.filter = function (value) {
+ return Math.round(value);
+ };
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- renderHtml: function() {
- var self = this, id = self._id, prefix = this.classPrefix;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ renderHtml: function () {
+ var self = this, id = self._id, prefix = this.classPrefix;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<div id="' + id + '" class="' + self.classes + '">' +
- '<div class="' + prefix + 'bar-container">' +
- '<div class="' + prefix + 'bar"></div>' +
- '</div>' +
- '<div class="' + prefix + 'text">0%</div>' +
- '</div>'
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<div id="' + id + '" class="' + self.classes + '">' +
+ '<div class="' + prefix + 'bar-container">' +
+ '<div class="' + prefix + 'bar"></div>' +
+ '</div>' +
+ '<div class="' + prefix + 'text">0%</div>' +
+ '</div>'
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- postRender: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ postRender: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super();
- self.value(self.settings.value);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super();
+ self.value(self.settings.value);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bindStates: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bindStates: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setValue(value) {
- value = self.settings.filter(value);
- self.getEl().lastChild.innerHTML = value + '%';
- self.getEl().firstChild.firstChild.style.width = value + '%';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setValue(value) {
+ value = self.settings.filter(value);
+ self.getEl().lastChild.innerHTML = value + '%';
+ self.getEl().firstChild.firstChild.style.width = value + '%';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:value', function(e) {
- setValue(e.value);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:value', function (e) {
+ setValue(e.value);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- setValue(self.state.get('value'));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ setValue(self.state.get('value'));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/Notification.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Notification.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -32497,153 +36626,154 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Container
</span><span class="cx" style="display: block; padding: 0 10px"> * @mixes tinymce.ui.Movable
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Notification", [
- "tinymce/ui/Control",
- "tinymce/ui/Movable",
- "tinymce/ui/Progress",
- "tinymce/util/Delay"
-], function(Control, Movable, Progress, Delay) {
- return Control.extend({
- Mixins: [Movable],
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Notification',
+ [
+ "tinymce.core.ui.Control",
+ "tinymce.core.ui.Movable",
+ "tinymce.core.ui.Progress",
+ "tinymce.core.util.Delay"
+ ],
+ function (Control, Movable, Progress, Delay) {
+ return Control.extend({
+ Mixins: [Movable],
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Defaults: {
- classes: 'widget notification'
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Defaults: {
+ classes: 'widget notification'
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- init: function(settings) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ init: function (settings) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super(settings);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super(settings);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.text) {
- self.text(settings.text);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.text) {
+ self.text(settings.text);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.icon) {
- self.icon = settings.icon;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.icon) {
+ self.icon = settings.icon;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.color) {
- self.color = settings.color;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.color) {
+ self.color = settings.color;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.type) {
- self.classes.add('notification-' + settings.type);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.type) {
+ self.classes.add('notification-' + settings.type);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.timeout && (settings.timeout < 0 || settings.timeout > 0) && !settings.closeButton) {
- self.closeButton = false;
- } else {
- self.classes.add('has-close');
- self.closeButton = true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.timeout && (settings.timeout < 0 || settings.timeout > 0) && !settings.closeButton) {
+ self.closeButton = false;
+ } else {
+ self.classes.add('has-close');
+ self.closeButton = true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.progressBar) {
- self.progressBar = new Progress();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.progressBar) {
+ self.progressBar = new Progress();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('click', function(e) {
- if (e.target.className.indexOf(self.classPrefix + 'close') != -1) {
- self.close();
- }
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('click', function (e) {
+ if (e.target.className.indexOf(self.classPrefix + 'close') != -1) {
+ self.close();
+ }
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this, prefix = self.classPrefix, icon = '', closeButton = '', progressBar = '', notificationStyle = '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this, prefix = self.classPrefix, icon = '', closeButton = '', progressBar = '', notificationStyle = '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.icon) {
- icon = '<i class="' + prefix + 'ico' + ' ' + prefix + 'i-' + self.icon + '"></i>';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.icon) {
+ icon = '<i class="' + prefix + 'ico' + ' ' + prefix + 'i-' + self.icon + '"></i>';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.color) {
- notificationStyle = ' style="background-color: ' + self.color + '"';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.color) {
+ notificationStyle = ' style="background-color: ' + self.color + '"';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.closeButton) {
- closeButton = '<button type="button" class="' + prefix + 'close" aria-hidden="true">\u00d7</button>';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.closeButton) {
+ closeButton = '<button type="button" class="' + prefix + 'close" aria-hidden="true">\u00d7</button>';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.progressBar) {
- progressBar = self.progressBar.renderHtml();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.progressBar) {
+ progressBar = self.progressBar.renderHtml();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<div id="' + self._id + '" class="' + self.classes + '"' + notificationStyle + ' role="presentation">' +
- icon +
- '<div class="' + prefix + 'notification-inner">' + self.state.get('text') + '</div>' +
- progressBar +
- closeButton +
- '</div>'
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<div id="' + self._id + '" class="' + self.classes + '"' + notificationStyle + ' role="presentation">' +
+ icon +
+ '<div class="' + prefix + 'notification-inner">' + self.state.get('text') + '</div>' +
+ progressBar +
+ closeButton +
+ '</div>'
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- postRender: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ postRender: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Delay.setTimeout(function() {
- self.$el.addClass(self.classPrefix + 'in');
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Delay.setTimeout(function () {
+ self.$el.addClass(self.classPrefix + 'in');
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bindStates: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bindStates: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:text', function(e) {
- self.getEl().childNodes[1].innerHTML = e.value;
- });
- if (self.progressBar) {
- self.progressBar.bindStates();
- }
- return self._super();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:text', function (e) {
+ self.getEl().childNodes[1].innerHTML = e.value;
+ });
+ if (self.progressBar) {
+ self.progressBar.bindStates();
+ }
+ return self._super();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- close: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ close: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.fire('close').isDefaultPrevented()) {
- self.remove();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.fire('close').isDefaultPrevented()) {
+ self.remove();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Repaints the control after a layout operation.
- *
- * @method repaint
- */
- repaint: function() {
- var self = this, style, rect;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Repaints the control after a layout operation.
+ *
+ * @method repaint
+ */
+ repaint: function () {
+ var self = this, style, rect;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- style = self.getEl().style;
- rect = self._layoutRect;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ style = self.getEl().style;
+ rect = self._layoutRect;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- style.left = rect.x + 'px';
- style.top = rect.y + 'px';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ style.left = rect.x + 'px';
+ style.top = rect.y + 'px';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Hardcoded arbitrary z-value because we want the
- // notifications under the other windows
- style.zIndex = 0xFFFF - 1;
- }
- });
-});
-
-// Included from: js/tinymce/classes/NotificationManager.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Hardcoded arbitrary z-value because we want the
+ // notifications under the other windows
+ style.zIndex = 0xFFFF - 1;
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * NotificationManager.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -32652,7 +36782,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * This class handles the creation of TinyMCE's notifications.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @class tinymce.notificationManager
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @class tinymce.NotificationManager
</ins><span class="cx" style="display: block; padding: 0 10px"> * @example
</span><span class="cx" style="display: block; padding: 0 10px"> * // Opens a new notification of type "error" with text "An error occurred."
</span><span class="cx" style="display: block; padding: 0 10px"> * tinymce.activeEditor.notificationManager.open({
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -32660,7791 +36790,8537 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * type: 'error'
</span><span class="cx" style="display: block; padding: 0 10px"> * });
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/NotificationManager", [
- "tinymce/ui/Notification",
- "tinymce/util/Delay",
- "tinymce/util/Tools"
-], function(Notification, Delay, Tools) {
- return function(editor) {
- var self = this, notifications = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.NotificationManager',
+ [
+ "tinymce.core.ui.Notification",
+ "tinymce.core.util.Delay",
+ "tinymce.core.util.Tools"
+ ],
+ function (Notification, Delay, Tools) {
+ return function (editor) {
+ var self = this, notifications = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getLastNotification() {
- if (notifications.length) {
- return notifications[notifications.length - 1];
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getLastNotification() {
+ if (notifications.length) {
+ return notifications[notifications.length - 1];
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.notifications = notifications;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.notifications = notifications;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function resizeWindowEvent() {
- Delay.requestAnimationFrame(function() {
- prePositionNotifications();
- positionNotifications();
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function resizeWindowEvent() {
+ Delay.requestAnimationFrame(function () {
+ prePositionNotifications();
+ positionNotifications();
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Since the viewport will change based on the present notifications, we need to move them all to the
- // top left of the viewport to give an accurate size measurement so we can position them later.
- function prePositionNotifications() {
- for (var i = 0; i < notifications.length; i++) {
- notifications[i].moveTo(0, 0);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Since the viewport will change based on the present notifications, we need to move them all to the
+ // top left of the viewport to give an accurate size measurement so we can position them later.
+ function prePositionNotifications() {
+ for (var i = 0; i < notifications.length; i++) {
+ notifications[i].moveTo(0, 0);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function positionNotifications() {
- if (notifications.length > 0) {
- var firstItem = notifications.slice(0, 1)[0];
- var container = editor.inline ? editor.getElement() : editor.getContentAreaContainer();
- firstItem.moveRel(container, 'tc-tc');
- if (notifications.length > 1) {
- for (var i = 1; i < notifications.length; i++) {
- notifications[i].moveRel(notifications[i - 1].getEl(), 'bc-tc');
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function positionNotifications() {
+ if (notifications.length > 0) {
+ var firstItem = notifications.slice(0, 1)[0];
+ var container = editor.inline ? editor.getElement() : editor.getContentAreaContainer();
+ firstItem.moveRel(container, 'tc-tc');
+ if (notifications.length > 1) {
+ for (var i = 1; i < notifications.length; i++) {
+ notifications[i].moveRel(notifications[i - 1].getEl(), 'bc-tc');
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('remove', function() {
- var i = notifications.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('remove', function () {
+ var i = notifications.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- notifications[i].close();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ notifications[i].close();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('ResizeEditor', positionNotifications);
- editor.on('ResizeWindow', resizeWindowEvent);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('ResizeEditor', positionNotifications);
+ editor.on('ResizeWindow', resizeWindowEvent);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Opens a new notification.
- *
- * @method open
- * @param {Object} args Optional name/value settings collection contains things like timeout/color/message etc.
- */
- self.open = function(args) {
- // Never open notification if editor has been removed.
- if (editor.removed) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Opens a new notification.
+ *
+ * @method open
+ * @param {Object} args Optional name/value settings collection contains things like timeout/color/message etc.
+ */
+ self.open = function (args) {
+ // Never open notification if editor has been removed.
+ if (editor.removed) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var notif;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var notif;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.editorManager.setActive(editor);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.editorManager.setActive(editor);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var duplicate = findDuplicateMessage(notifications, args);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var duplicate = findDuplicateMessage(notifications, args);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (duplicate === null) {
- notif = new Notification(args);
- notifications.push(notif);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (duplicate === null) {
+ notif = new Notification(args);
+ notifications.push(notif);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- //If we have a timeout value
- if (args.timeout > 0) {
- notif.timer = setTimeout(function() {
- notif.close();
- }, args.timeout);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ //If we have a timeout value
+ if (args.timeout > 0) {
+ notif.timer = setTimeout(function () {
+ notif.close();
+ }, args.timeout);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- notif.on('close', function() {
- var i = notifications.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ notif.on('close', function () {
+ var i = notifications.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (notif.timer) {
- editor.getWin().clearTimeout(notif.timer);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (notif.timer) {
+ editor.getWin().clearTimeout(notif.timer);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- if (notifications[i] === notif) {
- notifications.splice(i, 1);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ if (notifications[i] === notif) {
+ notifications.splice(i, 1);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- positionNotifications();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ positionNotifications();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- notif.renderTo();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ notif.renderTo();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- positionNotifications();
- } else {
- notif = duplicate;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ positionNotifications();
+ } else {
+ notif = duplicate;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return notif;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return notif;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Closes the top most notification.
- *
- * @method close
- */
- self.close = function() {
- if (getLastNotification()) {
- getLastNotification().close();
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Closes the top most notification.
+ *
+ * @method close
+ */
+ self.close = function () {
+ if (getLastNotification()) {
+ getLastNotification().close();
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the currently opened notification objects.
- *
- * @method getNotifications
- * @return {Array} Array of the currently opened notifications.
- */
- self.getNotifications = function() {
- return notifications;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the currently opened notification objects.
+ *
+ * @method getNotifications
+ * @return {Array} Array of the currently opened notifications.
+ */
+ self.getNotifications = function () {
+ return notifications;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('SkinLoaded', function() {
- var serviceMessage = editor.settings.service_message;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('SkinLoaded', function () {
+ var serviceMessage = editor.settings.service_message;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (serviceMessage) {
- editor.notificationManager.open({
- text: serviceMessage,
- type: 'warning',
- timeout: 0,
- icon: ''
- });
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (serviceMessage) {
+ editor.notificationManager.open({
+ text: serviceMessage,
+ type: 'warning',
+ timeout: 0,
+ icon: ''
+ });
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Finds any existing notification with the same properties as the new one.
- * Returns either the found notification or null.
- *
- * @param {Notification[]} notificationArray - Array of current notifications
- * @param {type: string, } newNotification - New notification object
- * @returns {?Notification}
- */
- function findDuplicateMessage(notificationArray, newNotification) {
- if (!isPlainTextNotification(newNotification)) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Finds any existing notification with the same properties as the new one.
+ * Returns either the found notification or null.
+ *
+ * @param {Notification[]} notificationArray - Array of current notifications
+ * @param {type: string, } newNotification - New notification object
+ * @returns {?Notification}
+ */
+ function findDuplicateMessage(notificationArray, newNotification) {
+ if (!isPlainTextNotification(newNotification)) {
+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var filteredNotifications = Tools.grep(notificationArray, function (notification) {
- return isSameNotification(newNotification, notification);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var filteredNotifications = Tools.grep(notificationArray, function (notification) {
+ return isSameNotification(newNotification, notification);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return filteredNotifications.length === 0 ? null : filteredNotifications[0];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return filteredNotifications.length === 0 ? null : filteredNotifications[0];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Checks if the passed in args object has the same
- * type and text properties as the sent in notification.
- *
- * @param {type: string, text: string} a - New notification args object
- * @param {Notification} b - Old notification
- * @returns {boolean}
- */
- function isSameNotification(a, b) {
- return a.type === b.settings.type && a.text === b.settings.text;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Checks if the passed in args object has the same
+ * type and text properties as the sent in notification.
+ *
+ * @param {type: string, text: string} a - New notification args object
+ * @param {Notification} b - Old notification
+ * @returns {boolean}
+ */
+ function isSameNotification(a, b) {
+ return a.type === b.settings.type && a.text === b.settings.text;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Checks that the notification does not have a progressBar
- * or timeour property.
- *
- * @param {Notification} notification - Notification to check
- * @returns {boolean}
- */
- function isPlainTextNotification(notification) {
- return !notification.progressBar && !notification.timeout;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Checks that the notification does not have a progressBar
+ * or timeour property.
+ *
+ * @param {Notification} notification - Notification to check
+ * @returns {boolean}
+ */
+ function isPlainTextNotification(notification) {
+ return !notification.progressBar && !notification.timeout;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- //self.positionNotifications = positionNotifications;
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ //self.positionNotifications = positionNotifications;
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/dom/NodePath.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * NodePath.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * EditorObservable.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Handles paths of nodes within an element.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * This mixin contains the event logic for the tinymce.Editor class.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @private
- * @class tinymce.dom.NodePath
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @mixin tinymce.EditorObservable
+ * @extends tinymce.util.Observable
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/dom/NodePath", [
- "tinymce/dom/DOMUtils"
-], function(DOMUtils) {
- function create(rootNode, targetNode, normalized) {
- var path = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.EditorObservable',
+ [
+ "tinymce.core.util.Observable",
+ "tinymce.core.dom.DOMUtils",
+ "tinymce.core.util.Tools"
+ ],
+ function (Observable, DOMUtils, Tools) {
+ var DOM = DOMUtils.DOM, customEventRootDelegates;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (; targetNode && targetNode != rootNode; targetNode = targetNode.parentNode) {
- path.push(DOMUtils.nodeIndex(targetNode, normalized));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the event target so for the specified event. Some events fire
+ * only on document, some fire on documentElement etc. This also handles the
+ * custom event root setting where it returns that element instead of the body.
+ *
+ * @private
+ * @param {tinymce.Editor} editor Editor instance to get event target from.
+ * @param {String} eventName Name of the event for example "click".
+ * @return {Element/Document} HTML Element or document target to bind on.
+ */
+ function getEventTarget(editor, eventName) {
+ if (eventName == 'selectionchange') {
+ return editor.getDoc();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return path;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Need to bind mousedown/mouseup etc to document not body in iframe mode
+ // Since the user might click on the HTML element not the BODY
+ if (!editor.inline && /^mouse|touch|click|contextmenu|drop|dragover|dragend/.test(eventName)) {
+ return editor.getDoc().documentElement;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function resolve(rootNode, path) {
- var i, node, children;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Bind to event root instead of body if it's defined
+ if (editor.settings.event_root) {
+ if (!editor.eventRoot) {
+ editor.eventRoot = DOM.select(editor.settings.event_root)[0];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (node = rootNode, i = path.length - 1; i >= 0; i--) {
- children = node.childNodes;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return editor.eventRoot;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (path[i] > children.length - 1) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return editor.getBody();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = children[path[i]];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Binds a event delegate for the specified name this delegate will fire
+ * the event to the editor dispatcher.
+ *
+ * @private
+ * @param {tinymce.Editor} editor Editor instance to get event target from.
+ * @param {String} eventName Name of the event for example "click".
+ */
+ function bindEventDelegate(editor, eventName) {
+ var eventRootElm = getEventTarget(editor, eventName), delegate;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isListening(editor) {
+ return !editor.hidden && !editor.readonly;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- create: create,
- resolve: resolve
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!editor.delegates) {
+ editor.delegates = {};
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/util/Quirks.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.delegates[eventName]) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Quirks.js
- *
- * Released under LGPL License.
- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- *
- * @ignore-file
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.settings.event_root) {
+ if (!customEventRootDelegates) {
+ customEventRootDelegates = {};
+ editor.editorManager.on('removeEditor', function () {
+ var name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * This file includes fixes for various browser quirks it's made to make it easy to add/remove browser specific fixes.
- *
- * @private
- * @class tinymce.util.Quirks
- */
-define("tinymce/util/Quirks", [
- "tinymce/util/VK",
- "tinymce/dom/RangeUtils",
- "tinymce/dom/TreeWalker",
- "tinymce/dom/NodePath",
- "tinymce/html/Node",
- "tinymce/html/Entities",
- "tinymce/Env",
- "tinymce/util/Tools",
- "tinymce/util/Delay",
- "tinymce/caret/CaretContainer",
- "tinymce/caret/CaretPosition",
- "tinymce/caret/CaretWalker"
-], function(VK, RangeUtils, TreeWalker, NodePath, Node, Entities, Env, Tools, Delay, CaretContainer, CaretPosition, CaretWalker) {
- return function(editor) {
- var each = Tools.each, $ = editor.$;
- var BACKSPACE = VK.BACKSPACE, DELETE = VK.DELETE, dom = editor.dom, selection = editor.selection,
- settings = editor.settings, parser = editor.parser, serializer = editor.serializer;
- var isGecko = Env.gecko, isIE = Env.ie, isWebKit = Env.webkit;
- var mceInternalUrlPrefix = 'data:text/mce-internal,';
- var mceInternalDataType = isIE ? 'Text' : 'URL';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!editor.editorManager.activeEditor) {
+ if (customEventRootDelegates) {
+ for (name in customEventRootDelegates) {
+ editor.dom.unbind(getEventTarget(editor, name));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Executes a command with a specific state this can be to enable/disable browser editing features.
- */
- function setEditorCommandState(cmd, state) {
- try {
- editor.getDoc().execCommand(cmd, false, state);
- } catch (ex) {
- // Ignore
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ customEventRootDelegates = null;
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns current IE document mode.
- */
- function getDocumentMode() {
- var documentMode = editor.getDoc().documentMode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (customEventRootDelegates[eventName]) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return documentMode ? documentMode : 6;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ delegate = function (e) {
+ var target = e.target, editors = editor.editorManager.editors, i = editors.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the event is prevented or not.
- *
- * @private
- * @param {Event} e Event object.
- * @return {Boolean} true/false if the event is prevented or not.
- */
- function isDefaultPrevented(e) {
- return e.isDefaultPrevented();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ var body = editors[i].getBody();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets Text/URL data on the event's dataTransfer object to a special data:text/mce-internal url.
- * This is to workaround the inability to set custom contentType on IE and Safari.
- * The editor's selected content is encoded into this url so drag and drop between editors will work.
- *
- * @private
- * @param {DragEvent} e Event object
- */
- function setMceInternalContent(e) {
- var selectionHtml, internalContent;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (body === target || DOM.isChildOf(target, body)) {
+ if (isListening(editors[i])) {
+ editors[i].fire(eventName, e);
+ }
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.dataTransfer) {
- if (editor.selection.isCollapsed() && e.target.tagName == 'IMG') {
- selection.select(e.target);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ customEventRootDelegates[eventName] = delegate;
+ DOM.bind(eventRootElm, eventName, delegate);
+ } else {
+ delegate = function (e) {
+ if (isListening(editor)) {
+ editor.fire(eventName, e);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- selectionHtml = editor.selection.getContent();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOM.bind(eventRootElm, eventName, delegate);
+ editor.delegates[eventName] = delegate;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Safari/IE doesn't support custom dataTransfer items so we can only use URL and Text
- if (selectionHtml.length > 0) {
- internalContent = mceInternalUrlPrefix + escape(editor.id) + ',' + escape(selectionHtml);
- e.dataTransfer.setData(mceInternalDataType, internalContent);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var EditorObservable = {
+ /**
+ * Bind any pending event delegates. This gets executed after the target body/document is created.
+ *
+ * @private
+ */
+ bindPendingEventDelegates: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Gets content of special data:text/mce-internal url on the event's dataTransfer object.
- * This is to workaround the inability to set custom contentType on IE and Safari.
- * The editor's selected content is encoded into this url so drag and drop between editors will work.
- *
- * @private
- * @param {DragEvent} e Event object
- * @returns {String} mce-internal content
- */
- function getMceInternalContent(e) {
- var internalContent;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(self._pendingNativeEvents, function (name) {
+ bindEventDelegate(self, name);
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.dataTransfer) {
- internalContent = e.dataTransfer.getData(mceInternalDataType);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Toggles a native event on/off this is called by the EventDispatcher when
+ * the first native event handler is added and when the last native event handler is removed.
+ *
+ * @private
+ */
+ toggleNativeEvent: function (name, state) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (internalContent && internalContent.indexOf(mceInternalUrlPrefix) >= 0) {
- internalContent = internalContent.substr(mceInternalUrlPrefix.length).split(',');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Never bind focus/blur since the FocusManager fakes those
+ if (name == "focus" || name == "blur") {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- id: unescape(internalContent[0]),
- html: unescape(internalContent[1])
- };
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (state) {
+ if (self.initialized) {
+ bindEventDelegate(self, name);
+ } else {
+ if (!self._pendingNativeEvents) {
+ self._pendingNativeEvents = [name];
+ } else {
+ self._pendingNativeEvents.push(name);
+ }
+ }
+ } else if (self.initialized) {
+ self.dom.unbind(getEventTarget(self, name), name, self.delegates[name]);
+ delete self.delegates[name];
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Unbinds all native event handlers that means delegates, custom events bound using the Events API etc.
+ *
+ * @private
+ */
+ unbindAllNativeEvents: function () {
+ var self = this, name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Inserts contents using the paste clipboard command if it's available if it isn't it will fallback
- * to the core command.
- *
- * @private
- * @param {String} content Content to insert at selection.
- */
- function insertClipboardContents(content) {
- if (editor.queryCommandSupported('mceInsertClipboardContent')) {
- editor.execCommand('mceInsertClipboardContent', false, {content: content});
- } else {
- editor.execCommand('mceInsertContent', false, content);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.delegates) {
+ for (name in self.delegates) {
+ self.dom.unbind(getEventTarget(self, name), name, self.delegates[name]);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Fixes a WebKit bug when deleting contents using backspace or delete key.
- * WebKit will produce a span element if you delete across two block elements.
- *
- * Example:
- * <h1>a</h1><p>|b</p>
- *
- * Will produce this on backspace:
- * <h1>a<span style="<all runtime styles>">b</span></p>
- *
- * This fixes the backspace to produce:
- * <h1>a|b</p>
- *
- * See bug: https://bugs.webkit.org/show_bug.cgi?id=45784
- *
- * This fixes the following delete scenarios:
- * 1. Delete by pressing backspace key.
- * 2. Delete by pressing delete key.
- * 3. Delete by pressing backspace key with ctrl/cmd (Word delete).
- * 4. Delete by pressing delete key with ctrl/cmd (Word delete).
- * 5. Delete by drag/dropping contents inside the editor.
- * 6. Delete by using Cut Ctrl+X/Cmd+X.
- * 7. Delete by selecting contents and writing a character.
- *
- * This code is a ugly hack since writing full custom delete logic for just this bug
- * fix seemed like a huge task. I hope we can remove this before the year 2030.
- */
- function cleanupStylesWhenDeleting() {
- var doc = editor.getDoc(), dom = editor.dom, selection = editor.selection;
- var MutationObserver = window.MutationObserver, olderWebKit, dragStartRng;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ delete self.delegates;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add mini polyfill for older WebKits
- // TODO: Remove this when old Safari versions gets updated
- if (!MutationObserver) {
- olderWebKit = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.inline) {
+ self.getBody().onload = null;
+ self.dom.unbind(self.getWin());
+ self.dom.unbind(self.getDoc());
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- MutationObserver = function() {
- var records = [], target;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.dom.unbind(self.getBody());
+ self.dom.unbind(self.getContainer());
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function nodeInsert(e) {
- var target = e.relatedNode || e.target;
- records.push({target: target, addedNodes: [target]});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ EditorObservable = Tools.extend({}, Observable, EditorObservable);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function attrModified(e) {
- var target = e.relatedNode || e.target;
- records.push({target: target, attributeName: e.attrName});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return EditorObservable;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.observe = function(node) {
- target = node;
- target.addEventListener('DOMSubtreeModified', nodeInsert, false);
- target.addEventListener('DOMNodeInsertedIntoDocument', nodeInsert, false);
- target.addEventListener('DOMNodeInserted', nodeInsert, false);
- target.addEventListener('DOMAttrModified', attrModified, false);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Shortcuts.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.disconnect = function() {
- target.removeEventListener('DOMSubtreeModified', nodeInsert, false);
- target.removeEventListener('DOMNodeInsertedIntoDocument', nodeInsert, false);
- target.removeEventListener('DOMNodeInserted', nodeInsert, false);
- target.removeEventListener('DOMAttrModified', attrModified, false);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Contains all logic for handling of keyboard shortcuts.
+ *
+ * @class tinymce.Shortcuts
+ * @example
+ * editor.shortcuts.add('ctrl+a', function() {});
+ * editor.shortcuts.add('meta+a', function() {}); // "meta" maps to Command on Mac and Ctrl on PC
+ * editor.shortcuts.add('ctrl+alt+a', function() {});
+ * editor.shortcuts.add('access+a', function() {}); // "access" maps to ctrl+alt on Mac and shift+alt on PC
+ */
+define(
+ 'tinymce.core.Shortcuts',
+ [
+ "tinymce.core.util.Tools",
+ "tinymce.core.Env"
+ ],
+ function (Tools, Env) {
+ var each = Tools.each, explode = Tools.explode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.takeRecords = function() {
- return records;
- };
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var keyCodeLookup = {
+ "f9": 120,
+ "f10": 121,
+ "f11": 122
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isTrailingBr(node) {
- var blockElements = dom.schema.getBlockElements(), rootNode = editor.getBody();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var modifierNames = Tools.makeMap('alt,ctrl,shift,meta,access');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.nodeName != 'BR') {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function (editor) {
+ var self = this, shortcuts = {}, pendingPatterns = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (; node != rootNode && !blockElements[node.nodeName]; node = node.parentNode) {
- if (node.nextSibling) {
- return false;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function parseShortcut(pattern) {
+ var id, key, shortcut = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Parse modifiers and keys ctrl+alt+b for example
+ each(explode(pattern, '+'), function (value) {
+ if (value in modifierNames) {
+ shortcut[value] = true;
+ } else {
+ // Allow numeric keycodes like ctrl+219 for ctrl+[
+ if (/^[0-9]{2,}$/.test(value)) {
+ shortcut.keyCode = parseInt(value, 10);
+ } else {
+ shortcut.charCode = value.charCodeAt(0);
+ shortcut.keyCode = keyCodeLookup[value] || value.toUpperCase().charCodeAt(0);
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isSiblingsIgnoreWhiteSpace(node1, node2) {
- var node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Generate unique id for modifier combination and set default state for unused modifiers
+ id = [shortcut.keyCode];
+ for (key in modifierNames) {
+ if (shortcut[key]) {
+ id.push(key);
+ } else {
+ shortcut[key] = false;
+ }
+ }
+ shortcut.id = id.join(',');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (node = node1.nextSibling; node && node != node2; node = node.nextSibling) {
- if (node.nodeType == 3 && $.trim(node.data).length === 0) {
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handle special access modifier differently depending on Mac/Win
+ if (shortcut.access) {
+ shortcut.alt = true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node !== node2) {
- return false;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (Env.mac) {
+ shortcut.ctrl = true;
+ } else {
+ shortcut.shift = true;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return node === node2;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handle special meta modifier differently depending on Mac/Win
+ if (shortcut.meta) {
+ if (Env.mac) {
+ shortcut.meta = true;
+ } else {
+ shortcut.ctrl = true;
+ shortcut.meta = false;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function findCaretNode(node, forward, startNode) {
- var walker, current, nonEmptyElements;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return shortcut;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Protect against the possibility we are asked to find a caret node relative
- // to a node that is no longer in the DOM tree. In this case attempting to
- // select on any match leads to a scenario where selection is completely removed
- // from the editor. This scenario is met in real world at a minimum on
- // WebKit browsers when selecting all and Cmd-X cutting to delete content.
- if (!dom.isChildOf(node, editor.getBody())) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function createShortcut(pattern, desc, cmdFunc, scope) {
+ var shortcuts;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- nonEmptyElements = dom.schema.getNonEmptyElements();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ shortcuts = Tools.map(explode(pattern, '>'), parseShortcut);
+ shortcuts[shortcuts.length - 1] = Tools.extend(shortcuts[shortcuts.length - 1], {
+ func: cmdFunc,
+ scope: scope || editor
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- walker = new TreeWalker(startNode || node, node);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Tools.extend(shortcuts[0], {
+ desc: editor.translate(desc),
+ subpatterns: shortcuts.slice(1)
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while ((current = walker[forward ? 'next' : 'prev']())) {
- if (nonEmptyElements[current.nodeName] && !isTrailingBr(current)) {
- return current;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hasModifier(e) {
+ return e.altKey || e.ctrlKey || e.metaKey;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (current.nodeType == 3 && current.data.length > 0) {
- return current;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isFunctionKey(e) {
+ return e.type === "keydown" && e.keyCode >= 112 && e.keyCode <= 123;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function deleteRangeBetweenTextBlocks(rng) {
- var startBlock, endBlock, caretNodeBefore, caretNodeAfter, textBlockElements;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function matchShortcut(e, shortcut) {
+ if (!shortcut) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rng.collapsed) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (shortcut.ctrl != e.ctrlKey || shortcut.meta != e.metaKey) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- startBlock = dom.getParent(RangeUtils.getNode(rng.startContainer, rng.startOffset), dom.isBlock);
- endBlock = dom.getParent(RangeUtils.getNode(rng.endContainer, rng.endOffset), dom.isBlock);
- textBlockElements = editor.schema.getTextBlockElements();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (shortcut.alt != e.altKey || shortcut.shift != e.shiftKey) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (startBlock == endBlock) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.keyCode == shortcut.keyCode || (e.charCode && e.charCode == shortcut.charCode)) {
+ e.preventDefault();
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!textBlockElements[startBlock.nodeName] || !textBlockElements[endBlock.nodeName]) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (dom.getContentEditable(startBlock) === "false" || dom.getContentEditable(endBlock) === "false") {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function executeShortcutAction(shortcut) {
+ return shortcut.func ? shortcut.func.call(shortcut.scope) : null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng.deleteContents();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('keyup keypress keydown', function (e) {
+ if ((hasModifier(e) || isFunctionKey(e)) && !e.isDefaultPrevented()) {
+ each(shortcuts, function (shortcut) {
+ if (matchShortcut(e, shortcut)) {
+ pendingPatterns = shortcut.subpatterns.slice(0);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- caretNodeBefore = findCaretNode(startBlock, false);
- caretNodeAfter = findCaretNode(endBlock, true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.type == "keydown") {
+ executeShortcutAction(shortcut);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!dom.isEmpty(endBlock)) {
- $(startBlock).append(endBlock.childNodes);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $(endBlock).remove();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (matchShortcut(e, pendingPatterns[0])) {
+ if (pendingPatterns.length === 1) {
+ if (e.type == "keydown") {
+ executeShortcutAction(pendingPatterns[0]);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (caretNodeBefore) {
- if (caretNodeBefore.nodeType == 1) {
- if (caretNodeBefore.nodeName == "BR") {
- rng.setStartBefore(caretNodeBefore);
- rng.setEndBefore(caretNodeBefore);
- } else {
- rng.setStartAfter(caretNodeBefore);
- rng.setEndAfter(caretNodeBefore);
- }
- } else {
- rng.setStart(caretNodeBefore, caretNodeBefore.data.length);
- rng.setEnd(caretNodeBefore, caretNodeBefore.data.length);
- }
- } else if (caretNodeAfter) {
- if (caretNodeAfter.nodeType == 1) {
- rng.setStartBefore(caretNodeAfter);
- rng.setEndBefore(caretNodeAfter);
- } else {
- rng.setStart(caretNodeAfter, 0);
- rng.setEnd(caretNodeAfter, 0);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ pendingPatterns.shift();
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- selection.setRng(rng);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds a keyboard shortcut for some command or function.
+ *
+ * @method add
+ * @param {String} pattern Shortcut pattern. Like for example: ctrl+alt+o.
+ * @param {String} desc Text description for the command.
+ * @param {String/Function} cmdFunc Command name string or function to execute when the key is pressed.
+ * @param {Object} scope Optional scope to execute the function in.
+ * @return {Boolean} true/false state if the shortcut was added or not.
+ */
+ self.add = function (pattern, desc, cmdFunc, scope) {
+ var cmd;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ cmd = cmdFunc;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function expandBetweenBlocks(rng, isForward) {
- var caretNode, targetCaretNode, textBlock, targetTextBlock, container, offset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof cmdFunc === 'string') {
+ cmdFunc = function () {
+ editor.execCommand(cmd, false, null);
+ };
+ } else if (Tools.isArray(cmd)) {
+ cmdFunc = function () {
+ editor.execCommand(cmd[0], cmd[1], cmd[2]);
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!rng.collapsed) {
- return rng;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(explode(Tools.trim(pattern.toLowerCase())), function (pattern) {
+ var shortcut = createShortcut(pattern, desc, cmdFunc, scope);
+ shortcuts[shortcut.id] = shortcut;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = rng.startContainer;
- offset = rng.startOffset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (container.nodeType == 3) {
- if (isForward) {
- if (offset < container.data.length) {
- return rng;
- }
- } else {
- if (offset > 0) {
- return rng;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Remove a keyboard shortcut by pattern.
+ *
+ * @method remove
+ * @param {String} pattern Shortcut pattern. Like for example: ctrl+alt+o.
+ * @return {Boolean} true/false state if the shortcut was removed or not.
+ */
+ self.remove = function (pattern) {
+ var shortcut = createShortcut(pattern);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- caretNode = RangeUtils.getNode(container, offset);
- textBlock = dom.getParent(caretNode, dom.isBlock);
- targetCaretNode = findCaretNode(editor.getBody(), isForward, caretNode);
- targetTextBlock = dom.getParent(targetCaretNode, dom.isBlock);
- var isAfter = container.nodeType === 1 && offset > container.childNodes.length - 1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (shortcuts[shortcut.id]) {
+ delete shortcuts[shortcut.id];
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!caretNode || !targetCaretNode) {
- return rng;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ };
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (targetTextBlock && textBlock != targetTextBlock) {
- if (!isForward) {
- if (!isSiblingsIgnoreWhiteSpace(targetTextBlock, textBlock)) {
- return rng;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+defineGlobal("global!window", window);
+/**
+ * ErrorReporter.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (targetCaretNode.nodeType == 1) {
- if (targetCaretNode.nodeName == "BR") {
- rng.setStartBefore(targetCaretNode);
- } else {
- rng.setStartAfter(targetCaretNode);
- }
- } else {
- rng.setStart(targetCaretNode, targetCaretNode.data.length);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Various error reporting helper functions.
+ *
+ * @class tinymce.ErrorReporter
+ * @private
+ */
+define(
+ 'tinymce.core.ErrorReporter',
+ [
+ "tinymce.core.AddOnManager"
+ ],
+ function (AddOnManager) {
+ var PluginManager = AddOnManager.PluginManager;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (caretNode.nodeType == 1) {
- if (isAfter) {
- rng.setEndAfter(caretNode);
- } else {
- rng.setEndBefore(caretNode);
- }
- } else {
- rng.setEndBefore(caretNode);
- }
- } else {
- if (!isSiblingsIgnoreWhiteSpace(textBlock, targetTextBlock)) {
- return rng;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var resolvePluginName = function (targetUrl, suffix) {
+ for (var name in PluginManager.urls) {
+ var matchUrl = PluginManager.urls[name] + '/plugin' + suffix + '.js';
+ if (matchUrl === targetUrl) {
+ return name;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (caretNode.nodeType == 1) {
- if (caretNode.nodeName == "BR") {
- rng.setStartBefore(caretNode);
- } else {
- rng.setStartAfter(caretNode);
- }
- } else {
- rng.setStart(caretNode, caretNode.data.length);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (targetCaretNode.nodeType == 1) {
- rng.setEnd(targetCaretNode, 0);
- } else {
- rng.setEndBefore(targetCaretNode);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var pluginUrlToMessage = function (editor, url) {
+ var plugin = resolvePluginName(url, editor.suffix);
+ return plugin ?
+ 'Failed to load plugin: ' + plugin + ' from url ' + url :
+ 'Failed to load plugin url: ' + url;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return rng;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var displayNotification = function (editor, message) {
+ editor.notificationManager.open({
+ type: 'error',
+ text: message
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function handleTextBlockMergeDelete(isForward) {
- var rng = selection.getRng();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var displayError = function (editor, message) {
+ if (editor._skinLoaded) {
+ displayNotification(editor, message);
+ } else {
+ editor.on('SkinLoaded', function () {
+ displayNotification(editor, message);
+ });
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng = expandBetweenBlocks(rng, isForward);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var uploadError = function (editor, message) {
+ displayError(editor, 'Failed to upload image: ' + message);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (deleteRangeBetweenTextBlocks(rng)) {
- return true;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var pluginLoadError = function (editor, url) {
+ displayError(editor, pluginUrlToMessage(editor, url));
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * This retains the formatting if the last character is to be deleted.
- *
- * Backspace on this: <p><b><i>a|</i></b></p> would become <p>|</p> in WebKit.
- * With this patch: <p><b><i>|<br></i></b></p>
- */
- function handleLastBlockCharacterDelete(isForward, rng) {
- var path, blockElm, newBlockElm, clonedBlockElm, sibling,
- container, offset, br, currentFormatNodes;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var contentCssError = function (editor, urls) {
+ displayError(editor, 'Failed to load content css: ' + urls[0]);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function cloneTextBlockWithFormats(blockElm, node) {
- currentFormatNodes = $(node).parents().filter(function(idx, node) {
- return !!editor.schema.getTextInlineElements()[node.nodeName];
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var initError = function (message) {
+ var console = window.console;
+ if (console && !window.test) { // Skip test env
+ if (console.error) {
+ console.error.apply(console, arguments);
+ } else {
+ console.log.apply(console, arguments);
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- newBlockElm = blockElm.cloneNode(false);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ pluginLoadError: pluginLoadError,
+ uploadError: uploadError,
+ displayError: displayError,
+ contentCssError: contentCssError,
+ initError: initError
+ };
+ }
+);
+/**
+ * CaretContainerInput.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- currentFormatNodes = Tools.map(currentFormatNodes, function(formatNode) {
- formatNode = formatNode.cloneNode(false);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * This module shows the invisble block that the caret is currently in when contents is added to that block.
+ */
+define(
+ 'tinymce.core.caret.CaretContainerInput',
+ [
+ 'ephox.katamari.api.Fun',
+ 'tinymce.core.caret.CaretContainer'
+ ],
+ function (Fun, CaretContainer) {
+ var findBlockCaretContainer = function (editor) {
+ return editor.dom.select('*[data-mce-caret]')[0];
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (newBlockElm.hasChildNodes()) {
- formatNode.appendChild(newBlockElm.firstChild);
- newBlockElm.appendChild(formatNode);
- } else {
- newBlockElm.appendChild(formatNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var removeIeControlRect = function (editor) {
+ editor.selection.setRng(editor.selection.getRng());
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- newBlockElm.appendChild(formatNode);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var showBlockCaretContainer = function (editor, blockCaretContainer) {
+ if (blockCaretContainer.hasAttribute('data-mce-caret')) {
+ CaretContainer.showCaretContainerBlock(blockCaretContainer);
+ removeIeControlRect(editor);
+ editor.selection.scrollIntoView(blockCaretContainer);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return formatNode;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var handleBlockContainer = function (editor, e) {
+ var blockCaretContainer = findBlockCaretContainer(editor);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (currentFormatNodes.length) {
- br = dom.create('br');
- currentFormatNodes[0].appendChild(br);
- dom.replace(newBlockElm, blockElm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!blockCaretContainer) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng.setStartBefore(br);
- rng.setEndBefore(br);
- editor.selection.setRng(rng);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.type === 'compositionstart') {
+ e.preventDefault();
+ e.stopPropagation();
+ showBlockCaretContainer(blockCaretContainer);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return br;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (CaretContainer.hasContent(blockCaretContainer)) {
+ showBlockCaretContainer(editor, blockCaretContainer);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var setup = function (editor) {
+ editor.on('keyup compositionstart', Fun.curry(handleBlockContainer, editor));
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isTextBlock(node) {
- return node && editor.schema.getTextBlockElements()[node.tagName];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ setup: setup
+ };
+ }
+);
+/**
+ * Uploader.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!rng.collapsed) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Upload blobs or blob infos to the specified URL or handler.
+ *
+ * @private
+ * @class tinymce.file.Uploader
+ * @example
+ * var uploader = new Uploader({
+ * url: '/upload.php',
+ * basePath: '/base/path',
+ * credentials: true,
+ * handler: function(data, success, failure) {
+ * ...
+ * }
+ * });
+ *
+ * uploader.upload(blobInfos).then(function(result) {
+ * ...
+ * });
+ */
+define(
+ 'tinymce.core.file.Uploader',
+ [
+ "tinymce.core.util.Promise",
+ "tinymce.core.util.Tools",
+ "tinymce.core.util.Fun"
+ ],
+ function (Promise, Tools, Fun) {
+ return function (uploadStatus, settings) {
+ var pendingPromises = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container = rng.startContainer;
- offset = rng.startOffset;
- blockElm = dom.getParent(container, dom.isBlock);
- if (!isTextBlock(blockElm)) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function pathJoin(path1, path2) {
+ if (path1) {
+ return path1.replace(/\/$/, '') + '/' + path2.replace(/^\//, '');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (container.nodeType == 1) {
- container = container.childNodes[offset];
- if (container && container.tagName != 'BR') {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return path2;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isForward) {
- sibling = blockElm.nextSibling;
- } else {
- sibling = blockElm.previousSibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function defaultHandler(blobInfo, success, failure, progress) {
+ var xhr, formData;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (dom.isEmpty(blockElm) && isTextBlock(sibling) && dom.isEmpty(sibling)) {
- if (cloneTextBlockWithFormats(blockElm, container)) {
- dom.remove(sibling);
- return true;
- }
- }
- } else if (container.nodeType == 3) {
- path = NodePath.create(blockElm, container);
- clonedBlockElm = blockElm.cloneNode(true);
- container = NodePath.resolve(clonedBlockElm, path);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ xhr = new XMLHttpRequest();
+ xhr.open('POST', settings.url);
+ xhr.withCredentials = settings.credentials;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isForward) {
- if (offset >= container.data.length) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ xhr.upload.onprogress = function (e) {
+ progress(e.loaded / e.total * 100);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container.deleteData(offset, 1);
- } else {
- if (offset <= 0) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ xhr.onerror = function () {
+ failure("Image upload failed due to a XHR Transport error. Code: " + xhr.status);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container.deleteData(offset - 1, 1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ xhr.onload = function () {
+ var json;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (dom.isEmpty(clonedBlockElm)) {
- return cloneTextBlockWithFormats(blockElm, container);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (xhr.status != 200) {
+ failure("HTTP Error: " + xhr.status);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function customDelete(isForward) {
- var mutationObserver, rng, caretElement;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ json = JSON.parse(xhr.responseText);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (handleTextBlockMergeDelete(isForward)) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!json || typeof json.location != "string") {
+ failure("Invalid JSON: " + xhr.responseText);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(editor.getBody().getElementsByTagName('*'), function(elm) {
- // Mark existing spans
- if (elm.tagName == 'SPAN') {
- elm.setAttribute('mce-data-marked', 1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ success(pathJoin(settings.basePath, json.location));
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Make sure all elements has a data-mce-style attribute
- if (!elm.hasAttribute('data-mce-style') && elm.hasAttribute('style')) {
- editor.dom.setAttrib(elm, 'style', editor.dom.getAttrib(elm, 'style'));
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ formData = new FormData();
+ formData.append('file', blobInfo.blob(), blobInfo.filename());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Observe added nodes and style attribute changes
- mutationObserver = new MutationObserver(function() {});
- mutationObserver.observe(editor.getDoc(), {
- childList: true,
- attributes: true,
- subtree: true,
- attributeFilter: ['style']
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ xhr.send(formData);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.getDoc().execCommand(isForward ? 'ForwardDelete' : 'Delete', false, null);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function noUpload() {
+ return new Promise(function (resolve) {
+ resolve([]);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng = editor.selection.getRng();
- caretElement = rng.startContainer.parentNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function handlerSuccess(blobInfo, url) {
+ return {
+ url: url,
+ blobInfo: blobInfo,
+ status: true
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(mutationObserver.takeRecords(), function(record) {
- if (!dom.isChildOf(record.target, editor.getBody())) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function handlerFailure(blobInfo, error) {
+ return {
+ url: '',
+ blobInfo: blobInfo,
+ status: false,
+ error: error
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Restore style attribute to previous value
- if (record.attributeName == "style") {
- var oldValue = record.target.getAttribute('data-mce-style');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function resolvePending(blobUri, result) {
+ Tools.each(pendingPromises[blobUri], function (resolve) {
+ resolve(result);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (oldValue) {
- record.target.setAttribute("style", oldValue);
- } else {
- record.target.removeAttribute("style");
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ delete pendingPromises[blobUri];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove all spans that aren't marked and retain selection
- Tools.each(record.addedNodes, function(node) {
- if (node.nodeName == "SPAN" && !node.getAttribute('mce-data-marked')) {
- var offset, container;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function uploadBlobInfo(blobInfo, handler, openNotification) {
+ uploadStatus.markPending(blobInfo.blobUri());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node == caretElement) {
- offset = rng.startOffset;
- container = node.firstChild;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return new Promise(function (resolve) {
+ var notification, progress;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.remove(node, true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var noop = function () {
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (container) {
- rng.setStart(container, offset);
- rng.setEnd(container, offset);
- editor.selection.setRng(rng);
- }
- }
- });
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ try {
+ var closeNotification = function () {
+ if (notification) {
+ notification.close();
+ progress = noop; // Once it's closed it's closed
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- mutationObserver.disconnect();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var success = function (url) {
+ closeNotification();
+ uploadStatus.markUploaded(blobInfo.blobUri(), url);
+ resolvePending(blobInfo.blobUri(), handlerSuccess(blobInfo, url));
+ resolve(handlerSuccess(blobInfo, url));
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove any left over marks
- Tools.each(editor.dom.select('span[mce-data-marked]'), function(span) {
- span.removeAttribute('mce-data-marked');
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var failure = function (error) {
+ closeNotification();
+ uploadStatus.removeFailed(blobInfo.blobUri());
+ resolvePending(blobInfo.blobUri(), handlerFailure(blobInfo, error));
+ resolve(handlerFailure(blobInfo, error));
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function transactCustomDelete(isForward) {
- editor.undoManager.transact(function () {
- customDelete(isForward);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ progress = function (percent) {
+ if (percent < 0 || percent > 100) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('keydown', function(e) {
- var isForward = e.keyCode == DELETE, isMetaOrCtrl = e.ctrlKey || e.metaKey;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!notification) {
+ notification = openNotification();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isDefaultPrevented(e) && (isForward || e.keyCode == BACKSPACE)) {
- var rng = editor.selection.getRng(), container = rng.startContainer, offset = rng.startOffset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ notification.progressBar.value(percent);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Shift+Delete is cut
- if (isForward && e.shiftKey) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ handler(blobInfo, success, failure, progress);
+ } catch (ex) {
+ resolve(handlerFailure(blobInfo, ex.message));
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (handleLastBlockCharacterDelete(isForward, rng)) {
- e.preventDefault();
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isDefaultHandler(handler) {
+ return handler === defaultHandler;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Ignore non meta delete in the where there is text before/after the caret
- if (!isMetaOrCtrl && rng.collapsed && container.nodeType == 3) {
- if (isForward ? offset < container.data.length : offset > 0) {
- return;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function pendingUploadBlobInfo(blobInfo) {
+ var blobUri = blobInfo.blobUri();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- e.preventDefault();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return new Promise(function (resolve) {
+ pendingPromises[blobUri] = pendingPromises[blobUri] || [];
+ pendingPromises[blobUri].push(resolve);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isMetaOrCtrl) {
- editor.selection.getSel().modify("extend", isForward ? "forward" : "backward", e.metaKey ? "lineboundary" : "word");
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function uploadBlobs(blobInfos, openNotification) {
+ blobInfos = Tools.grep(blobInfos, function (blobInfo) {
+ return !uploadStatus.isUploaded(blobInfo.blobUri());
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- customDelete(isForward);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Promise.all(Tools.map(blobInfos, function (blobInfo) {
+ return uploadStatus.isPending(blobInfo.blobUri()) ?
+ pendingUploadBlobInfo(blobInfo) : uploadBlobInfo(blobInfo, settings.handler, openNotification);
+ }));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle case where text is deleted by typing over
- editor.on('keypress', function(e) {
- if (!isDefaultPrevented(e) && !selection.isCollapsed() && e.charCode > 31 && !VK.metaKeyPressed(e)) {
- var rng, currentFormatNodes, fragmentNode, blockParent, caretNode, charText;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function upload(blobInfos, openNotification) {
+ return (!settings.url && isDefaultHandler(settings.handler)) ? noUpload() : uploadBlobs(blobInfos, openNotification);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng = editor.selection.getRng();
- charText = String.fromCharCode(e.charCode);
- e.preventDefault();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ settings = Tools.extend({
+ credentials: false,
+ // We are adding a notify argument to this (at the moment, until it doesn't work)
+ handler: defaultHandler
+ }, settings);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Keep track of current format nodes
- currentFormatNodes = $(rng.startContainer).parents().filter(function(idx, node) {
- return !!editor.schema.getTextInlineElements()[node.nodeName];
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ upload: upload
+ };
+ };
+ }
+);
+/**
+ * Conversions.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- customDelete(true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Converts blob/uris back and forth.
+ *
+ * @private
+ * @class tinymce.file.Conversions
+ */
+define(
+ 'tinymce.core.file.Conversions',
+ [
+ "tinymce.core.util.Promise"
+ ],
+ function (Promise) {
+ function blobUriToBlob(url) {
+ return new Promise(function (resolve, reject) {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if the browser removed them
- currentFormatNodes = currentFormatNodes.filter(function(idx, node) {
- return !$.contains(editor.getBody(), node);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var rejectWithError = function () {
+ reject("Cannot convert " + url + " to Blob. Resource might not exist or is inaccessible.");
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Then re-add them
- if (currentFormatNodes.length) {
- fragmentNode = dom.createFragment();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ try {
+ var xhr = new XMLHttpRequest();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- currentFormatNodes.each(function(idx, formatNode) {
- formatNode = formatNode.cloneNode(false);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ xhr.open('GET', url, true);
+ xhr.responseType = 'blob';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (fragmentNode.hasChildNodes()) {
- formatNode.appendChild(fragmentNode.firstChild);
- fragmentNode.appendChild(formatNode);
- } else {
- caretNode = formatNode;
- fragmentNode.appendChild(formatNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ xhr.onload = function () {
+ if (this.status == 200) {
+ resolve(this.response);
+ } else {
+ // IE11 makes it into onload but responds with status 500
+ rejectWithError();
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- fragmentNode.appendChild(formatNode);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Chrome fires an error event instead of the exception
+ // Also there seems to be no way to intercept the message that is logged to the console
+ xhr.onerror = rejectWithError;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- caretNode.appendChild(editor.getDoc().createTextNode(charText));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ xhr.send();
+ } catch (ex) {
+ rejectWithError();
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Prevent edge case where older WebKit would add an extra BR element
- blockParent = dom.getParent(rng.startContainer, dom.isBlock);
- if (dom.isEmpty(blockParent)) {
- $(blockParent).empty().append(fragmentNode);
- } else {
- rng.insertNode(fragmentNode);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function parseDataUri(uri) {
+ var type, matches;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng.setStart(caretNode.firstChild, 1);
- rng.setEnd(caretNode.firstChild, 1);
- editor.selection.setRng(rng);
- } else {
- editor.selection.setContent(charText);
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ uri = decodeURIComponent(uri).split(',');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addCommand('Delete', function() {
- customDelete();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ matches = /data:([^;]+)/.exec(uri[0]);
+ if (matches) {
+ type = matches[1];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addCommand('ForwardDelete', function() {
- customDelete(true);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ type: type,
+ data: uri[1]
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Older WebKits doesn't properly handle the clipboard so we can't add the rest
- if (olderWebKit) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function dataUriToBlob(uri) {
+ return new Promise(function (resolve) {
+ var str, arr, i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('dragstart', function(e) {
- dragStartRng = selection.getRng();
- setMceInternalContent(e);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ uri = parseDataUri(uri);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('drop', function(e) {
- if (!isDefaultPrevented(e)) {
- var internalContent = getMceInternalContent(e);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Might throw error if data isn't proper base64
+ try {
+ str = atob(uri.data);
+ } catch (e) {
+ resolve(new Blob([]));
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (internalContent) {
- e.preventDefault();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ arr = new Uint8Array(str.length);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Safari has a weird issue where drag/dropping images sometimes
- // produces a green plus icon. When this happens the caretRangeFromPoint
- // will return "null" even though the x, y coordinate is correct.
- // But if we detach the insert from the drop event we will get a proper range
- Delay.setEditorTimeout(editor, function() {
- var pointRng = RangeUtils.getCaretRangeFromPoint(e.x, e.y, doc);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0; i < arr.length; i++) {
+ arr[i] = str.charCodeAt(i);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (dragStartRng) {
- selection.setRng(dragStartRng);
- dragStartRng = null;
- transactCustomDelete();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ resolve(new Blob([arr], { type: uri.type }));
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- selection.setRng(pointRng);
- insertClipboardContents(internalContent.html);
- });
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function uriToBlob(url) {
+ if (url.indexOf('blob:') === 0) {
+ return blobUriToBlob(url);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('cut', function(e) {
- if (!isDefaultPrevented(e) && e.clipboardData && !editor.selection.isCollapsed()) {
- e.preventDefault();
- e.clipboardData.clearData();
- e.clipboardData.setData('text/html', editor.selection.getContent());
- e.clipboardData.setData('text/plain', editor.selection.getContent({format: 'text'}));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (url.indexOf('data:') === 0) {
+ return dataUriToBlob(url);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Needed delay for https://code.google.com/p/chromium/issues/detail?id=363288#c3
- // Nested delete/forwardDelete not allowed on execCommand("cut")
- // This is ugly but not sure how to work around it otherwise
- Delay.setEditorTimeout(editor, function() {
- transactCustomDelete(true);
- });
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Makes sure that the editor body becomes empty when backspace or delete is pressed in empty editors.
- *
- * For example:
- * <p><b>|</b></p>
- *
- * Or:
- * <h1>|</h1>
- *
- * Or:
- * [<h1></h1>]
- */
- function emptyEditorWhenDeleting() {
- function serializeRng(rng) {
- var body = dom.create("body");
- var contents = rng.cloneContents();
- body.appendChild(contents);
- return selection.serializer.serialize(body, {format: 'html'});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function blobToDataUri(blob) {
+ return new Promise(function (resolve) {
+ var reader = new FileReader();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function allContentsSelected(rng) {
- if (!rng.setStart) {
- if (rng.item) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ reader.onloadend = function () {
+ resolve(reader.result);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var bodyRng = rng.duplicate();
- bodyRng.moveToElementText(editor.getBody());
- return RangeUtils.compareRanges(rng, bodyRng);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ reader.readAsDataURL(blob);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var selection = serializeRng(rng);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ uriToBlob: uriToBlob,
+ blobToDataUri: blobToDataUri,
+ parseDataUri: parseDataUri
+ };
+ }
+);
+/**
+ * ImageScanner.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var allRng = dom.createRng();
- allRng.selectNode(editor.getBody());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Finds images with data uris or blob uris. If data uris are found it will convert them into blob uris.
+ *
+ * @private
+ * @class tinymce.file.ImageScanner
+ */
+define(
+ 'tinymce.core.file.ImageScanner',
+ [
+ "tinymce.core.util.Promise",
+ "tinymce.core.util.Arr",
+ "tinymce.core.util.Fun",
+ "tinymce.core.file.Conversions",
+ "tinymce.core.Env"
+ ],
+ function (Promise, Arr, Fun, Conversions, Env) {
+ var count = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var allSelection = serializeRng(allRng);
- return selection === allSelection;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var uniqueId = function (prefix) {
+ return (prefix || 'blobid') + (count++);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('keydown', function(e) {
- var keyCode = e.keyCode, isCollapsed, body;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function (uploadStatus, blobCache) {
+ var cachedPromises = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Empty the editor if it's needed for example backspace at <p><b>|</b></p>
- if (!isDefaultPrevented(e) && (keyCode == DELETE || keyCode == BACKSPACE)) {
- isCollapsed = editor.selection.isCollapsed();
- body = editor.getBody();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function findAll(elm, predicate) {
+ var images, promises;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Selection is collapsed but the editor isn't empty
- if (isCollapsed && !dom.isEmpty(body)) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function imageToBlobInfo(img, resolve, reject) {
+ var base64, blobInfo;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Selection isn't collapsed but not all the contents is selected
- if (!isCollapsed && !allContentsSelected(editor.selection.getRng())) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (img.src.indexOf('blob:') === 0) {
+ blobInfo = blobCache.getByUri(img.src);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Manually empty the editor
- e.preventDefault();
- editor.setContent('');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (blobInfo) {
+ resolve({
+ image: img,
+ blobInfo: blobInfo
+ });
+ } else {
+ Conversions.uriToBlob(img.src).then(function (blob) {
+ Conversions.blobToDataUri(blob).then(function (dataUri) {
+ base64 = Conversions.parseDataUri(dataUri).data;
+ blobInfo = blobCache.create(uniqueId(), blob, base64);
+ blobCache.add(blobInfo);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (body.firstChild && dom.isBlock(body.firstChild)) {
- editor.selection.setCursorLocation(body.firstChild, 0);
- } else {
- editor.selection.setCursorLocation(body, 0);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ resolve({
+ image: img,
+ blobInfo: blobInfo
+ });
+ });
+ }, function (err) {
+ reject(err);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.nodeChanged();
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * WebKit doesn't select all the nodes in the body when you press Ctrl+A.
- * IE selects more than the contents <body>[<p>a</p>]</body> instead of <body><p>[a]</p]</body> see bug #6438
- * This selects the whole body so that backspace/delete logic will delete everything
- */
- function selectAll() {
- editor.shortcuts.add('meta+a', null, 'SelectAll');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ base64 = Conversions.parseDataUri(img.src).data;
+ blobInfo = blobCache.findFirst(function (cachedBlobInfo) {
+ return cachedBlobInfo.base64() === base64;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * WebKit has a weird issue where it some times fails to properly convert keypresses to input method keystrokes.
- * The IME on Mac doesn't initialize when it doesn't fire a proper focus event.
- *
- * This seems to happen when the user manages to click the documentElement element then the window doesn't get proper focus until
- * you enter a character into the editor.
- *
- * It also happens when the first focus in made to the body.
- *
- * See: https://bugs.webkit.org/show_bug.cgi?id=83566
- */
- function inputMethodFocus() {
- if (!editor.settings.content_editable) {
- // Case 1 IME doesn't initialize if you focus the document
- // Disabled since it was interferring with the cE=false logic
- // Also coultn't reproduce the issue on Safari 9
- /*dom.bind(editor.getDoc(), 'focusin', function() {
- selection.setRng(selection.getRng());
- });*/
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (blobInfo) {
+ resolve({
+ image: img,
+ blobInfo: blobInfo
+ });
+ } else {
+ Conversions.uriToBlob(img.src).then(function (blob) {
+ blobInfo = blobCache.create(uniqueId(), blob, base64);
+ blobCache.add(blobInfo);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Case 2 IME doesn't initialize if you click the documentElement it also doesn't properly fire the focusin event
- // Needs to be both down/up due to weird rendering bug on Chrome Windows
- dom.bind(editor.getDoc(), 'mousedown mouseup', function(e) {
- var rng;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ resolve({
+ image: img,
+ blobInfo: blobInfo
+ });
+ }, function (err) {
+ reject(err);
+ });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.target == editor.getDoc().documentElement) {
- rng = selection.getRng();
- editor.getBody().focus();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!predicate) {
+ predicate = Fun.constant(true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.type == 'mousedown') {
- if (CaretContainer.isCaretContainer(rng.startContainer)) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ images = Arr.filter(elm.getElementsByTagName('img'), function (img) {
+ var src = img.src;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Edge case for mousedown, drag select and mousedown again within selection on Chrome Windows to render caret
- selection.placeCaretAt(e.clientX, e.clientY);
- } else {
- selection.setRng(rng);
- }
- }
- });
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!Env.fileApi) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Backspacing in FireFox/IE from a paragraph into a horizontal rule results in a floating text node because the
- * browser just deletes the paragraph - the browser fails to merge the text node with a horizontal rule so it is
- * left there. TinyMCE sees a floating text node and wraps it in a paragraph on the key up event (ForceBlocks.js
- * addRootBlocks), meaning the action does nothing. With this code, FireFox/IE matche the behaviour of other
- * browsers.
- *
- * It also fixes a bug on Firefox where it's impossible to delete HR elements.
- */
- function removeHrOnBackspace() {
- editor.on('keydown', function(e) {
- if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {
- // Check if there is any HR elements this is faster since getRng on IE 7 & 8 is slow
- if (!editor.getBody().getElementsByTagName('hr').length) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (img.hasAttribute('data-mce-bogus')) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (selection.isCollapsed() && selection.getRng(true).startOffset === 0) {
- var node = selection.getNode();
- var previousSibling = node.previousSibling;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (img.hasAttribute('data-mce-placeholder')) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.nodeName == 'HR') {
- dom.remove(node);
- e.preventDefault();
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!src || src == Env.transparentSrc) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === "hr") {
- dom.remove(previousSibling);
- e.preventDefault();
- }
- }
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (src.indexOf('blob:') === 0) {
+ return !uploadStatus.isUploaded(src);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Firefox 3.x has an issue where the body element won't get proper focus if you click out
- * side it's rectangle.
- */
- function focusBody() {
- // Fix for a focus bug in FF 3.x where the body element
- // wouldn't get proper focus if the user clicked on the HTML element
- if (!window.Range.prototype.getClientRects) { // Detect getClientRects got introduced in FF 4
- editor.on('mousedown', function(e) {
- if (!isDefaultPrevented(e) && e.target.nodeName === "HTML") {
- var body = editor.getBody();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (src.indexOf('data:') === 0) {
+ return predicate(img);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Blur the body it's focused but not correctly focused
- body.blur();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Refocus the body after a little while
- Delay.setEditorTimeout(editor, function() {
- body.focus();
- });
- }
- });
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ promises = Arr.map(images, function (img) {
+ var newPromise;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * WebKit has a bug where it isn't possible to select image, hr or anchor elements
- * by clicking on them so we need to fake that.
- */
- function selectControlElements() {
- editor.on('click', function(e) {
- var target = e.target;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (cachedPromises[img.src]) {
+ // Since the cached promise will return the cached image
+ // We need to wrap it and resolve with the actual image
+ return new Promise(function (resolve) {
+ cachedPromises[img.src].then(function (imageInfo) {
+ if (typeof imageInfo === 'string') { // error apparently
+ return imageInfo;
+ }
+ resolve({
+ image: img,
+ blobInfo: imageInfo.blobInfo
+ });
+ });
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Workaround for bug, http://bugs.webkit.org/show_bug.cgi?id=12250
- // WebKit can't even do simple things like selecting an image
- if (/^(IMG|HR)$/.test(target.nodeName) && dom.getContentEditableParent(target) !== "false") {
- e.preventDefault();
- selection.select(target);
- editor.nodeChanged();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ newPromise = new Promise(function (resolve, reject) {
+ imageToBlobInfo(img, resolve, reject);
+ }).then(function (result) {
+ delete cachedPromises[result.image.src];
+ return result;
+ })['catch'](function (error) {
+ delete cachedPromises[img.src];
+ return error;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (target.nodeName == 'A' && dom.hasClass(target, 'mce-item-anchor')) {
- e.preventDefault();
- selection.select(target);
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ cachedPromises[img.src] = newPromise;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Fixes a Gecko bug where the style attribute gets added to the wrong element when deleting between two block elements.
- *
- * Fixes do backspace/delete on this:
- * <p>bla[ck</p><p style="color:red">r]ed</p>
- *
- * Would become:
- * <p>bla|ed</p>
- *
- * Instead of:
- * <p style="color:red">bla|ed</p>
- */
- function removeStylesWhenDeletingAcrossBlockElements() {
- function getAttributeApplyFunction() {
- var template = dom.getAttribs(selection.getStart().cloneNode(false));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return newPromise;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function() {
- var target = selection.getStart();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Promise.all(promises);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (target !== editor.getBody()) {
- dom.setAttrib(target, "style", null);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ findAll: findAll
+ };
+ };
+ }
+);
+/**
+ * Uuid.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(template, function(attr) {
- target.setAttributeNode(attr.cloneNode(true));
- });
- }
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Generates unique ids.
+ *
+ * @class tinymce.util.Uuid
+ * @private
+ */
+define(
+ 'tinymce.core.util.Uuid',
+ [
+ ],
+ function () {
+ var count = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isSelectionAcrossElements() {
- return !selection.isCollapsed() &&
- dom.getParent(selection.getStart(), dom.isBlock) != dom.getParent(selection.getEnd(), dom.isBlock);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var seed = function () {
+ var rnd = function () {
+ return Math.round(Math.random() * 0xFFFFFFFF).toString(36);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('keypress', function(e) {
- var applyAttributes;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var now = new Date().getTime();
+ return 's' + now.toString(36) + rnd() + rnd() + rnd();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isDefaultPrevented(e) && (e.keyCode == 8 || e.keyCode == 46) && isSelectionAcrossElements()) {
- applyAttributes = getAttributeApplyFunction();
- editor.getDoc().execCommand('delete', false, null);
- applyAttributes();
- e.preventDefault();
- return false;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var uuid = function (prefix) {
+ return prefix + (count++) + seed();
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.bind(editor.getDoc(), 'cut', function(e) {
- var applyAttributes;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ uuid: uuid
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isDefaultPrevented(e) && isSelectionAcrossElements()) {
- applyAttributes = getAttributeApplyFunction();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+defineGlobal("global!URL", URL);
+/**
+ * BlobCache.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Delay.setEditorTimeout(editor, function() {
- applyAttributes();
- });
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Hold blob info objects where a blob has extra internal information.
+ *
+ * @private
+ * @class tinymce.file.BlobCache
+ */
+define(
+ 'tinymce.core.file.BlobCache',
+ [
+ 'tinymce.core.util.Arr',
+ 'tinymce.core.util.Fun',
+ 'tinymce.core.util.Uuid',
+ 'global!URL'
+ ],
+ function (Arr, Fun, Uuid, URL) {
+ return function () {
+ var cache = [], constant = Fun.constant;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Screen readers on IE needs to have the role application set on the body.
- */
- function ensureBodyHasRoleApplication() {
- document.body.setAttribute("role", "application");
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function mimeToExt(mime) {
+ var mimes = {
+ 'image/jpeg': 'jpg',
+ 'image/jpg': 'jpg',
+ 'image/gif': 'gif',
+ 'image/png': 'png'
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Backspacing into a table behaves differently depending upon browser type.
- * Therefore, disable Backspace when cursor immediately follows a table.
- */
- function disableBackspaceIntoATable() {
- editor.on('keydown', function(e) {
- if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {
- if (selection.isCollapsed() && selection.getRng(true).startOffset === 0) {
- var previousSibling = selection.getNode().previousSibling;
- if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === "table") {
- e.preventDefault();
- return false;
- }
- }
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return mimes[mime.toLowerCase()] || 'dat';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Old IE versions can't properly render BR elements in PRE tags white in contentEditable mode. So this
- * logic adds a \n before the BR so that it will get rendered.
- */
- function addNewLinesBeforeBrInPre() {
- // IE8+ rendering mode does the right thing with BR in PRE
- if (getDocumentMode() > 7) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function create(o, blob, base64, filename) {
+ return typeof o === 'object' ? toBlobInfo(o) : toBlobInfo({
+ id: o,
+ name: filename,
+ blob: blob,
+ base64: base64
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Enable display: none in area and add a specific class that hides all BR elements in PRE to
- // avoid the caret from getting stuck at the BR elements while pressing the right arrow key
- setEditorCommandState('RespectVisibilityInDesign', true);
- editor.contentStyles.push('.mceHideBrInPre pre br {display: none}');
- dom.addClass(editor.getBody(), 'mceHideBrInPre');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function toBlobInfo(o) {
+ var id, name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Adds a \n before all BR elements in PRE to get them visual
- parser.addNodeFilter('pre', function(nodes) {
- var i = nodes.length, brNodes, j, brElm, sibling;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!o.blob || !o.base64) {
+ throw "blob and base64 representations of the image are required for BlobInfo to be created";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- brNodes = nodes[i].getAll('br');
- j = brNodes.length;
- while (j--) {
- brElm = brNodes[j];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ id = o.id || Uuid.uuid('blobid');
+ name = o.name || id;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add \n before BR in PRE elements on older IE:s so the new lines get rendered
- sibling = brElm.prev;
- if (sibling && sibling.type === 3 && sibling.value.charAt(sibling.value - 1) != '\n') {
- sibling.value += '\n';
- } else {
- brElm.parent.insert(new Node('#text', 3), brElm, true).value = '\n';
- }
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ id: constant(id),
+ name: constant(name),
+ filename: constant(name + '.' + mimeToExt(o.blob.type)),
+ blob: constant(o.blob),
+ base64: constant(o.base64),
+ blobUri: constant(o.blobUri || URL.createObjectURL(o.blob)),
+ uri: constant(o.uri)
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Removes any \n before BR elements in PRE since other browsers and in contentEditable=false mode they will be visible
- serializer.addNodeFilter('pre', function(nodes) {
- var i = nodes.length, brNodes, j, brElm, sibling;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function add(blobInfo) {
+ if (!get(blobInfo.id())) {
+ cache.push(blobInfo);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- brNodes = nodes[i].getAll('br');
- j = brNodes.length;
- while (j--) {
- brElm = brNodes[j];
- sibling = brElm.prev;
- if (sibling && sibling.type == 3) {
- sibling.value = sibling.value.replace(/\r?\n$/, '');
- }
- }
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function get(id) {
+ return findFirst(function (cachedBlobInfo) {
+ return cachedBlobInfo.id() === id;
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Moves style width/height to attribute width/height when the user resizes an image on IE.
- */
- function removePreSerializedStylesWhenSelectingControls() {
- dom.bind(editor.getBody(), 'mouseup', function() {
- var value, node = selection.getNode();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function findFirst(predicate) {
+ return Arr.filter(cache, predicate)[0];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Moved styles to attributes on IMG eements
- if (node.nodeName == 'IMG') {
- // Convert style width to width attribute
- if ((value = dom.getStyle(node, 'width'))) {
- dom.setAttrib(node, 'width', value.replace(/[^0-9%]+/g, ''));
- dom.setStyle(node, 'width', '');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getByUri(blobUri) {
+ return findFirst(function (blobInfo) {
+ return blobInfo.blobUri() == blobUri;
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Convert style height to height attribute
- if ((value = dom.getStyle(node, 'height'))) {
- dom.setAttrib(node, 'height', value.replace(/[^0-9%]+/g, ''));
- dom.setStyle(node, 'height', '');
- }
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function removeByUri(blobUri) {
+ cache = Arr.filter(cache, function (blobInfo) {
+ if (blobInfo.blobUri() === blobUri) {
+ URL.revokeObjectURL(blobInfo.blobUri());
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes a blockquote when backspace is pressed at the beginning of it.
- *
- * For example:
- * <blockquote><p>|x</p></blockquote>
- *
- * Becomes:
- * <p>|x</p>
- */
- function removeBlockQuoteOnBackSpace() {
- // Add block quote deletion handler
- editor.on('keydown', function(e) {
- var rng, container, offset, root, parent;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isDefaultPrevented(e) || e.keyCode != VK.BACKSPACE) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function destroy() {
+ Arr.each(cache, function (cachedBlobInfo) {
+ URL.revokeObjectURL(cachedBlobInfo.blobUri());
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng = selection.getRng();
- container = rng.startContainer;
- offset = rng.startOffset;
- root = dom.getRoot();
- parent = container;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ cache = [];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!rng.collapsed || offset !== 0) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ create: create,
+ add: add,
+ get: get,
+ getByUri: getByUri,
+ findFirst: findFirst,
+ removeByUri: removeByUri,
+ destroy: destroy
+ };
+ };
+ }
+);
+/**
+ * UploadStatus.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (parent && parent.parentNode && parent.parentNode.firstChild == parent && parent.parentNode != root) {
- parent = parent.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Holds the current status of a blob uri, if it's pending or uploaded and what the result urls was.
+ *
+ * @private
+ * @class tinymce.file.UploadStatus
+ */
+define(
+ 'tinymce.core.file.UploadStatus',
+ [
+ ],
+ function () {
+ return function () {
+ var PENDING = 1, UPLOADED = 2;
+ var blobUriStatuses = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Is the cursor at the beginning of a blockquote?
- if (parent.tagName === 'BLOCKQUOTE') {
- // Remove the blockquote
- editor.formatter.toggle('blockquote', null, parent);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function createStatus(status, resultUri) {
+ return {
+ status: status,
+ resultUri: resultUri
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move the caret to the beginning of container
- rng = dom.createRng();
- rng.setStart(container, 0);
- rng.setEnd(container, 0);
- selection.setRng(rng);
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hasBlobUri(blobUri) {
+ return blobUri in blobUriStatuses;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets various Gecko editing options on mouse down and before a execCommand to disable inline table editing that is broken etc.
- */
- function setGeckoEditingOptions() {
- function setOpts() {
- refreshContentEditable();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getResultUri(blobUri) {
+ var result = blobUriStatuses[blobUri];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- setEditorCommandState("StyleWithCSS", false);
- setEditorCommandState("enableInlineTableEditing", false);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return result ? result.resultUri : null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!settings.object_resizing) {
- setEditorCommandState("enableObjectResizing", false);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isPending(blobUri) {
+ return hasBlobUri(blobUri) ? blobUriStatuses[blobUri].status === PENDING : false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!settings.readonly) {
- editor.on('BeforeExecCommand MouseDown', setOpts);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isUploaded(blobUri) {
+ return hasBlobUri(blobUri) ? blobUriStatuses[blobUri].status === UPLOADED : false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Fixes a gecko link bug, when a link is placed at the end of block elements there is
- * no way to move the caret behind the link. This fix adds a bogus br element after the link.
- *
- * For example this:
- * <p><b><a href="#">x</a></b></p>
- *
- * Becomes this:
- * <p><b><a href="#">x</a></b><br></p>
- */
- function addBrAfterLastLinks() {
- function fixLinks() {
- each(dom.select('a'), function(node) {
- var parentNode = node.parentNode, root = dom.getRoot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function markPending(blobUri) {
+ blobUriStatuses[blobUri] = createStatus(PENDING, null);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (parentNode.lastChild === node) {
- while (parentNode && !dom.isBlock(parentNode)) {
- if (parentNode.parentNode.lastChild !== parentNode || parentNode === root) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function markUploaded(blobUri, resultUri) {
+ blobUriStatuses[blobUri] = createStatus(UPLOADED, resultUri);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parentNode = parentNode.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function removeFailed(blobUri) {
+ delete blobUriStatuses[blobUri];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.add(parentNode, 'br', {'data-mce-bogus': 1});
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function destroy() {
+ blobUriStatuses = {};
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('SetContent ExecCommand', function(e) {
- if (e.type == "setcontent" || e.command === 'mceInsertLink') {
- fixLinks();
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ hasBlobUri: hasBlobUri,
+ getResultUri: getResultUri,
+ isPending: isPending,
+ isUploaded: isUploaded,
+ markPending: markPending,
+ markUploaded: markUploaded,
+ removeFailed: removeFailed,
+ destroy: destroy
+ };
+ };
+ }
+);
+/**
+ * EditorUpload.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * WebKit will produce DIV elements here and there by default. But since TinyMCE uses paragraphs by
- * default we want to change that behavior.
- */
- function setDefaultBlockType() {
- if (settings.forced_root_block) {
- editor.on('init', function() {
- setEditorCommandState('DefaultParagraphSeparator', settings.forced_root_block);
- });
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Handles image uploads, updates undo stack and patches over various internal functions.
+ *
+ * @private
+ * @class tinymce.EditorUpload
+ */
+define(
+ 'tinymce.core.EditorUpload',
+ [
+ "tinymce.core.util.Arr",
+ "tinymce.core.file.Uploader",
+ "tinymce.core.file.ImageScanner",
+ "tinymce.core.file.BlobCache",
+ "tinymce.core.file.UploadStatus",
+ "tinymce.core.ErrorReporter"
+ ],
+ function (Arr, Uploader, ImageScanner, BlobCache, UploadStatus, ErrorReporter) {
+ return function (editor) {
+ var blobCache = new BlobCache(), uploader, imageScanner, settings = editor.settings;
+ var uploadStatus = new UploadStatus();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Deletes the selected image on IE instead of navigating to previous page.
- */
- function deleteControlItemOnBackSpace() {
- editor.on('keydown', function(e) {
- var rng;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function aliveGuard(callback) {
+ return function (result) {
+ if (editor.selection) {
+ return callback(result);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isDefaultPrevented(e) && e.keyCode == BACKSPACE) {
- rng = editor.getDoc().selection.createRange();
- if (rng && rng.item) {
- e.preventDefault();
- editor.undoManager.beforeChange();
- dom.remove(rng.item(0));
- editor.undoManager.add();
- }
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return [];
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * IE10 doesn't properly render block elements with the right height until you add contents to them.
- * This fixes that by adding a padding-right to all empty text block elements.
- * See: https://connect.microsoft.com/IE/feedback/details/743881
- */
- function renderEmptyBlocksFix() {
- var emptyBlocksCSS;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function cacheInvalidator() {
+ return '?' + (new Date()).getTime();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // IE10+
- if (getDocumentMode() >= 10) {
- emptyBlocksCSS = '';
- each('p div h1 h2 h3 h4 h5 h6'.split(' '), function(name, i) {
- emptyBlocksCSS += (i > 0 ? ',' : '') + name + ':empty';
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Replaces strings without regexps to avoid FF regexp to big issue
+ function replaceString(content, search, replace) {
+ var index = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.contentStyles.push(emptyBlocksCSS + '{padding-right: 1px !important}');
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ do {
+ index = content.indexOf(search, index);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Old IE versions can't retain contents within noscript elements so this logic will store the contents
- * as a attribute and the insert that value as it's raw text when the DOM is serialized.
- */
- function keepNoScriptContents() {
- if (getDocumentMode() < 9) {
- parser.addNodeFilter('noscript', function(nodes) {
- var i = nodes.length, node, textNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (index !== -1) {
+ content = content.substring(0, index) + replace + content.substr(index + search.length);
+ index += replace.length - search.length + 1;
+ }
+ } while (index !== -1);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i];
- textNode = node.firstChild;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return content;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (textNode) {
- node.attr('data-mce-innertext', textNode.value);
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function replaceImageUrl(content, targetUrl, replacementUrl) {
+ content = replaceString(content, 'src="' + targetUrl + '"', 'src="' + replacementUrl + '"');
+ content = replaceString(content, 'data-mce-src="' + targetUrl + '"', 'data-mce-src="' + replacementUrl + '"');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- serializer.addNodeFilter('noscript', function(nodes) {
- var i = nodes.length, node, textNode, value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return content;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i];
- textNode = nodes[i].firstChild;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function replaceUrlInUndoStack(targetUrl, replacementUrl) {
+ Arr.each(editor.undoManager.data, function (level) {
+ if (level.type === 'fragmented') {
+ level.fragments = Arr.map(level.fragments, function (fragment) {
+ return replaceImageUrl(fragment, targetUrl, replacementUrl);
+ });
+ } else {
+ level.content = replaceImageUrl(level.content, targetUrl, replacementUrl);
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (textNode) {
- textNode.value = Entities.decode(textNode.value);
- } else {
- // Old IE can't retain noscript value so an attribute is used to store it
- value = node.attributes.map['data-mce-innertext'];
- if (value) {
- node.attr('data-mce-innertext', null);
- textNode = new Node('#text', 3);
- textNode.value = value;
- textNode.raw = true;
- node.append(textNode);
- }
- }
- }
- });
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function openNotification() {
+ return editor.notificationManager.open({
+ text: editor.translate('Image uploading...'),
+ type: 'info',
+ timeout: -1,
+ progressBar: true
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * IE has an issue where you can't select/move the caret by clicking outside the body if the document is in standards mode.
- */
- function fixCaretSelectionOfDocumentElementOnIe() {
- var doc = dom.doc, body = doc.body, started, startRng, htmlElm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function replaceImageUri(image, resultUri) {
+ blobCache.removeByUri(image.src);
+ replaceUrlInUndoStack(image.src, resultUri);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Return range from point or null if it failed
- function rngFromPoint(x, y) {
- var rng = body.createTextRange();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.$(image).attr({
+ src: settings.images_reuse_filename ? resultUri + cacheInvalidator() : resultUri,
+ 'data-mce-src': editor.convertURL(resultUri, 'src')
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- try {
- rng.moveToPoint(x, y);
- } catch (ex) {
- // IE sometimes throws and exception, so lets just ignore it
- rng = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function uploadImages(callback) {
+ if (!uploader) {
+ uploader = new Uploader(uploadStatus, {
+ url: settings.images_upload_url,
+ basePath: settings.images_upload_base_path,
+ credentials: settings.images_upload_credentials,
+ handler: settings.images_upload_handler
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return rng;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return scanForImages().then(aliveGuard(function (imageInfos) {
+ var blobInfos;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Fires while the selection is changing
- function selectionChange(e) {
- var pointRng;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ blobInfos = Arr.map(imageInfos, function (imageInfo) {
+ return imageInfo.blobInfo;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if the button is down or not
- if (e.button) {
- // Create range from mouse position
- pointRng = rngFromPoint(e.x, e.y);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return uploader.upload(blobInfos, openNotification).then(aliveGuard(function (result) {
+ var filteredResult = Arr.map(result, function (uploadInfo, index) {
+ var image = imageInfos[index].image;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (pointRng) {
- // Check if pointRange is before/after selection then change the endPoint
- if (pointRng.compareEndPoints('StartToStart', startRng) > 0) {
- pointRng.setEndPoint('StartToStart', startRng);
- } else {
- pointRng.setEndPoint('EndToEnd', startRng);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (uploadInfo.status && editor.settings.images_replace_blob_uris !== false) {
+ replaceImageUri(image, uploadInfo.url);
+ } else if (uploadInfo.error) {
+ ErrorReporter.uploadError(editor, uploadInfo.error);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- pointRng.select();
- }
- } else {
- endSelection();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ element: image,
+ status: uploadInfo.status
+ };
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Removes listeners
- function endSelection() {
- var rng = doc.selection.createRange();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (callback) {
+ callback(filteredResult);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If the range is collapsed then use the last start range
- if (startRng && !rng.item && rng.compareEndPoints('StartToEnd', rng) === 0) {
- startRng.select();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return filteredResult;
+ }));
+ }));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.unbind(doc, 'mouseup', endSelection);
- dom.unbind(doc, 'mousemove', selectionChange);
- startRng = started = 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function uploadImagesAuto(callback) {
+ if (settings.automatic_uploads !== false) {
+ return uploadImages(callback);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Make HTML element unselectable since we are going to handle selection by hand
- doc.documentElement.unselectable = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isValidDataUriImage(imgElm) {
+ return settings.images_dataimg_filter ? settings.images_dataimg_filter(imgElm) : true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Detect when user selects outside BODY
- dom.bind(doc, 'mousedown contextmenu', function(e) {
- if (e.target.nodeName === 'HTML') {
- if (started) {
- endSelection();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function scanForImages() {
+ if (!imageScanner) {
+ imageScanner = new ImageScanner(uploadStatus, blobCache);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Detect vertical scrollbar, since IE will fire a mousedown on the scrollbar and have target set as HTML
- htmlElm = doc.documentElement;
- if (htmlElm.scrollHeight > htmlElm.clientHeight) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return imageScanner.findAll(editor.getBody(), isValidDataUriImage).then(aliveGuard(function (result) {
+ result = Arr.filter(result, function (resultItem) {
+ // ImageScanner internally converts images that it finds, but it may fail to do so if image source is inaccessible.
+ // In such case resultItem will contain appropriate text error message, instead of image data.
+ if (typeof resultItem === 'string') {
+ ErrorReporter.displayError(editor, resultItem);
+ return false;
+ }
+ return true;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- started = 1;
- // Setup start position
- startRng = rngFromPoint(e.x, e.y);
- if (startRng) {
- // Listen for selection change events
- dom.bind(doc, 'mouseup', endSelection);
- dom.bind(doc, 'mousemove', selectionChange);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Arr.each(result, function (resultItem) {
+ replaceUrlInUndoStack(resultItem.image.src, resultItem.blobInfo.blobUri());
+ resultItem.image.src = resultItem.blobInfo.blobUri();
+ resultItem.image.removeAttribute('data-mce-src');
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.getRoot().focus();
- startRng.select();
- }
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return result;
+ }));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Fixes selection issues where the caret can be placed between two inline elements like <b>a</b>|<b>b</b>
- * this fix will lean the caret right into the closest inline element.
- */
- function normalizeSelection() {
- // Normalize selection for example <b>a</b><i>|a</i> becomes <b>a|</b><i>a</i> except for Ctrl+A since it selects everything
- editor.on('keyup focusin mouseup', function(e) {
- if (e.keyCode != 65 || !VK.metaKeyPressed(e)) {
- selection.normalize();
- }
- }, true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function destroy() {
+ blobCache.destroy();
+ uploadStatus.destroy();
+ imageScanner = uploader = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Forces Gecko to render a broken image icon if it fails to load an image.
- */
- function showBrokenImageIcon() {
- editor.contentStyles.push(
- 'img:-moz-broken {' +
- '-moz-force-broken-image-icon:1;' +
- 'min-width:24px;' +
- 'min-height:24px' +
- '}'
- );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function replaceBlobUris(content) {
+ return content.replace(/src="(blob:[^"]+)"/g, function (match, blobUri) {
+ var resultUri = uploadStatus.getResultUri(blobUri);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * iOS has a bug where it's impossible to type if the document has a touchstart event
- * bound and the user touches the document while having the on screen keyboard visible.
- *
- * The touch event moves the focus to the parent document while having the caret inside the iframe
- * this fix moves the focus back into the iframe document.
- */
- function restoreFocusOnKeyDown() {
- if (!editor.inline) {
- editor.on('keydown', function() {
- if (document.activeElement == document.body) {
- editor.getWin().focus();
- }
- });
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (resultUri) {
+ return 'src="' + resultUri + '"';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * IE 11 has an annoying issue where you can't move focus into the editor
- * by clicking on the white area HTML element. We used to be able to to fix this with
- * the fixCaretSelectionOfDocumentElementOnIe fix. But since M$ removed the selection
- * object it's not possible anymore. So we need to hack in a ungly CSS to force the
- * body to be at least 150px. If the user clicks the HTML element out side this 150px region
- * we simply move the focus into the first paragraph. Not ideal since you loose the
- * positioning of the caret but goot enough for most cases.
- */
- function bodyHeight() {
- if (!editor.inline) {
- editor.contentStyles.push('body {min-height: 150px}');
- editor.on('click', function(e) {
- var rng;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var blobInfo = blobCache.getByUri(blobUri);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.target.nodeName == 'HTML') {
- // Edge seems to only need focus if we set the range
- // the caret will become invisible and moved out of the iframe!!
- if (Env.ie > 11) {
- editor.getBody().focus();
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!blobInfo) {
+ blobInfo = Arr.reduce(editor.editorManager.editors, function (result, editor) {
+ return result || editor.editorUpload && editor.editorUpload.blobCache.getByUri(blobUri);
+ }, null);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Need to store away non collapsed ranges since the focus call will mess that up see #7382
- rng = editor.selection.getRng();
- editor.getBody().focus();
- editor.selection.setRng(rng);
- editor.selection.normalize();
- editor.nodeChanged();
- }
- });
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (blobInfo) {
+ return 'src="data:' + blobInfo.blob().type + ';base64,' + blobInfo.base64() + '"';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Firefox on Mac OS will move the browser back to the previous page if you press CMD+Left arrow.
- * You might then loose all your work so we need to block that behavior and replace it with our own.
- */
- function blockCmdArrowNavigation() {
- if (Env.mac) {
- editor.on('keydown', function(e) {
- if (VK.metaKeyPressed(e) && !e.shiftKey && (e.keyCode == 37 || e.keyCode == 39)) {
- e.preventDefault();
- editor.selection.getSel().modify('move', e.keyCode == 37 ? 'backward' : 'forward', 'lineboundary');
- }
- });
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return match;
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Disables the autolinking in IE 9+ this is then re-enabled by the autolink plugin.
- */
- function disableAutoUrlDetect() {
- setEditorCommandState("AutoUrlDetect", false);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('setContent', function () {
+ if (editor.settings.automatic_uploads !== false) {
+ uploadImagesAuto();
+ } else {
+ scanForImages();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * iOS 7.1 introduced two new bugs:
- * 1) It's possible to open links within a contentEditable area by clicking on them.
- * 2) If you hold down the finger it will display the link/image touch callout menu.
- */
- function tapLinksAndImages() {
- editor.on('click', function(e) {
- var elm = e.target;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('RawSaveContent', function (e) {
+ e.content = replaceBlobUris(e.content);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- do {
- if (elm.tagName === 'A') {
- e.preventDefault();
- return;
- }
- } while ((elm = elm.parentNode));
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('getContent', function (e) {
+ if (e.source_view || e.format == 'raw') {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.contentStyles.push('.mce-content-body {-webkit-touch-callout: none}');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ e.content = replaceBlobUris(e.content);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * iOS Safari and possible other browsers have a bug where it won't fire
- * a click event when a contentEditable is focused. This function fakes click events
- * by using touchstart/touchend and measuring the time and distance travelled.
- */
- /*
- function touchClickEvent() {
- editor.on('touchstart', function(e) {
- var elm, time, startTouch, changedTouches;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('PostRender', function () {
+ editor.parser.addNodeFilter('img', function (images) {
+ Arr.each(images, function (img) {
+ var src = img.attr('src');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elm = e.target;
- time = new Date().getTime();
- changedTouches = e.changedTouches;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (blobCache.getByUri(src)) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!changedTouches || changedTouches.length > 1) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var resultUri = uploadStatus.getResultUri(src);
+ if (resultUri) {
+ img.attr('src', resultUri);
+ }
+ });
+ });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- startTouch = changedTouches[0];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ blobCache: blobCache,
+ uploadImages: uploadImages,
+ uploadImagesAuto: uploadImagesAuto,
+ scanForImages: scanForImages,
+ destroy: destroy
+ };
+ };
+ }
+);
+/**
+ * ForceBlocks.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.once('touchend', function(e) {
- var endTouch = e.changedTouches[0], args;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Makes sure that everything gets wrapped in paragraphs.
+ *
+ * @private
+ * @class tinymce.ForceBlocks
+ */
+define(
+ 'tinymce.core.ForceBlocks',
+ [
+ 'ephox.katamari.api.Fun'
+ ],
+ function (Fun) {
+ var addRootBlocks = function (editor) {
+ var settings = editor.settings, dom = editor.dom, selection = editor.selection;
+ var schema = editor.schema, blockElements = schema.getBlockElements();
+ var node = selection.getStart(), rootNode = editor.getBody(), rng;
+ var startContainer, startOffset, endContainer, endOffset, rootBlockNode;
+ var tempNode, offset = -0xFFFFFF, wrapped, restoreSelection;
+ var tmpRng, rootNodeName, forcedRootBlock;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (new Date().getTime() - time > 500) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ forcedRootBlock = settings.forced_root_block;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (Math.abs(startTouch.clientX - endTouch.clientX) > 5) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!node || node.nodeType !== 1 || !forcedRootBlock) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (Math.abs(startTouch.clientY - endTouch.clientY) > 5) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if node is wrapped in block
+ while (node && node !== rootNode) {
+ if (blockElements[node.nodeName]) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args = {
- target: elm
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each('pageX pageY clientX clientY screenX screenY'.split(' '), function(key) {
- args[key] = endTouch[key];
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get current selection
+ rng = selection.getRng();
+ if (rng.setStart) {
+ startContainer = rng.startContainer;
+ startOffset = rng.startOffset;
+ endContainer = rng.endContainer;
+ endOffset = rng.endOffset;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args = editor.fire('click', args);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ try {
+ restoreSelection = editor.getDoc().activeElement === rootNode;
+ } catch (ex) {
+ // IE throws unspecified error here sometimes
+ }
+ } else {
+ // Force control range into text range
+ if (rng.item) {
+ node = rng.item(0);
+ rng = editor.getDoc().body.createTextRange();
+ rng.moveToElementText(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!args.isDefaultPrevented()) {
- // iOS WebKit can't place the caret properly once
- // you bind touch events so we need to do this manually
- // TODO: Expand to the closest word? Touble tap still works.
- editor.selection.placeCaretAt(endTouch.clientX, endTouch.clientY);
- editor.nodeChanged();
- }
- });
- });
- }
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ restoreSelection = rng.parentElement().ownerDocument === editor.getDoc();
+ tmpRng = rng.duplicate();
+ tmpRng.collapse(true);
+ startOffset = tmpRng.move('character', offset) * -1;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * WebKit has a bug where it will allow forms to be submitted if they are inside a contentEditable element.
- * For example this: <form><button></form>
- */
- function blockFormSubmitInsideEditor() {
- editor.on('init', function() {
- editor.dom.bind(editor.getBody(), 'submit', function(e) {
- e.preventDefault();
- });
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!tmpRng.collapsed) {
+ tmpRng = rng.duplicate();
+ tmpRng.collapse(false);
+ endOffset = (tmpRng.move('character', offset) * -1) - startOffset;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sometimes WebKit/Blink generates BR elements with the Apple-interchange-newline class.
- *
- * Scenario:
- * 1) Create a table 2x2.
- * 2) Select and copy cells A2-B2.
- * 3) Paste and it will add BR element to table cell.
- */
- function removeAppleInterchangeBrs() {
- parser.addNodeFilter('br', function(nodes) {
- var i = nodes.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Wrap non block elements and text nodes
+ node = rootNode.firstChild;
+ rootNodeName = rootNode.nodeName.toLowerCase();
+ while (node) {
+ // TODO: Break this up, too complex
+ if (((node.nodeType === 3 || (node.nodeType == 1 && !blockElements[node.nodeName]))) &&
+ schema.isValidChild(rootNodeName, forcedRootBlock.toLowerCase())) {
+ // Remove empty text nodes
+ if (node.nodeType === 3 && node.nodeValue.length === 0) {
+ tempNode = node;
+ node = node.nextSibling;
+ dom.remove(tempNode);
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- if (nodes[i].attr('class') == 'Apple-interchange-newline') {
- nodes[i].remove();
- }
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!rootBlockNode) {
+ rootBlockNode = dom.create(forcedRootBlock, editor.settings.forced_root_block_attrs);
+ node.parentNode.insertBefore(rootBlockNode, node);
+ wrapped = true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * IE cannot set custom contentType's on drag events, and also does not properly drag/drop between
- * editors. This uses a special data:text/mce-internal URL to pass data when drag/drop between editors.
- */
- function ieInternalDragAndDrop() {
- editor.on('dragstart', function(e) {
- setMceInternalContent(e);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ tempNode = node;
+ node = node.nextSibling;
+ rootBlockNode.appendChild(tempNode);
+ } else {
+ rootBlockNode = null;
+ node = node.nextSibling;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('drop', function(e) {
- if (!isDefaultPrevented(e)) {
- var internalContent = getMceInternalContent(e);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (wrapped && restoreSelection) {
+ if (rng.setStart) {
+ rng.setStart(startContainer, startOffset);
+ rng.setEnd(endContainer, endOffset);
+ selection.setRng(rng);
+ } else {
+ // Only select if the previous selection was inside the document to prevent auto focus in quirks mode
+ try {
+ rng = editor.getDoc().body.createTextRange();
+ rng.moveToElementText(rootNode);
+ rng.collapse(true);
+ rng.moveStart('character', startOffset);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (internalContent && internalContent.id != editor.id) {
- e.preventDefault();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (endOffset > 0) {
+ rng.moveEnd('character', endOffset);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var rng = RangeUtils.getCaretRangeFromPoint(e.x, e.y, editor.getDoc());
- selection.setRng(rng);
- insertClipboardContents(internalContent.html);
- }
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng.select();
+ } catch (ex) {
+ // Ignore
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function refreshContentEditable() {
- // No-op since Mozilla seems to have fixed the caret repaint issues
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.nodeChanged();
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isHidden() {
- var sel;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var setup = function (editor) {
+ if (editor.settings.forced_root_block) {
+ editor.on('NodeChange', Fun.curry(addRootBlocks, editor));
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isGecko) {
- return 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ setup: setup
+ };
+ }
+);
+define(
+ 'ephox.katamari.api.Merger',
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Weird, wheres that cursor selection?
- sel = editor.selection.getSel();
- return (!sel || !sel.rangeCount || sel.rangeCount === 0);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ [
+ 'ephox.katamari.api.Type',
+ 'global!Array',
+ 'global!Error'
+ ],
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Properly empties the editor if all contents is selected and deleted this to
- * prevent empty paragraphs from being produced at beginning/end of contents.
- */
- function emptyEditorOnDeleteEverything() {
- function isEverythingSelected(editor) {
- var caretWalker = new CaretWalker(editor.getBody());
- var rng = editor.selection.getRng();
- var startCaretPos = CaretPosition.fromRangeStart(rng);
- var endCaretPos = CaretPosition.fromRangeEnd(rng);
- var prev = caretWalker.prev(startCaretPos);
- var next = caretWalker.next(endCaretPos);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function (Type, Array, Error) {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return !editor.selection.isCollapsed() &&
- (!prev || (prev.isAtStart() && startCaretPos.isEqual(prev))) &&
- (!next || (next.isAtEnd() && startCaretPos.isEqual(next)));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var shallow = function (old, nu) {
+ return nu;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Type over case delete and insert this won't cover typeover with a IME but at least it covers the common case
- editor.on('keypress', function (e) {
- if (!isDefaultPrevented(e) && !selection.isCollapsed() && e.charCode > 31 && !VK.metaKeyPressed(e)) {
- if (isEverythingSelected(editor)) {
- e.preventDefault();
- editor.setContent(String.fromCharCode(e.charCode));
- editor.selection.select(editor.getBody(), true);
- editor.selection.collapse(false);
- editor.nodeChanged();
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var deep = function (old, nu) {
+ var bothObjects = Type.isObject(old) && Type.isObject(nu);
+ return bothObjects ? deepMerge(old, nu) : nu;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('keydown', function (e) {
- var keyCode = e.keyCode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var baseMerge = function (merger) {
+ return function() {
+ // Don't use array slice(arguments), makes the whole function unoptimisable on Chrome
+ var objects = new Array(arguments.length);
+ for (var i = 0; i < objects.length; i++) objects[i] = arguments[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isDefaultPrevented(e) && (keyCode == DELETE || keyCode == BACKSPACE)) {
- if (isEverythingSelected(editor)) {
- e.preventDefault();
- editor.setContent('');
- editor.nodeChanged();
- }
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (objects.length === 0) throw new Error('Can\'t merge zero objects');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // All browsers
- removeBlockQuoteOnBackSpace();
- emptyEditorWhenDeleting();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var ret = {};
+ for (var j = 0; j < objects.length; j++) {
+ var curObject = objects[j];
+ for (var key in curObject) if (curObject.hasOwnProperty(key)) {
+ ret[key] = merger(ret[key], curObject[key]);
+ }
+ }
+ return ret;
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Windows phone will return a range like [body, 0] on mousedown so
- // it will always normalize to the wrong location
- if (!Env.windowsPhone) {
- normalizeSelection();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var deepMerge = baseMerge(deep);
+ var merge = baseMerge(shallow);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // WebKit
- if (isWebKit) {
- emptyEditorOnDeleteEverything();
- cleanupStylesWhenDeleting();
- inputMethodFocus();
- selectControlElements();
- setDefaultBlockType();
- blockFormSubmitInsideEditor();
- disableBackspaceIntoATable();
- removeAppleInterchangeBrs();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ deepMerge: deepMerge,
+ merge: merge
+ };
+ }
+);
+/**
+ * MatchKeys.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- //touchClickEvent();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.keyboard.MatchKeys',
+ [
+ 'ephox.katamari.api.Arr',
+ 'ephox.katamari.api.Fun',
+ 'ephox.katamari.api.Merger'
+ ],
+ function (Arr, Fun, Merger) {
+ var defaultPatterns = function (patterns) {
+ return Arr.map(patterns, function (pattern) {
+ return Merger.merge({
+ shiftKey: false,
+ altKey: false,
+ ctrlKey: false,
+ metaKey: false,
+ keyCode: 0,
+ action: Fun.noop
+ }, pattern);
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // iOS
- if (Env.iOS) {
- restoreFocusOnKeyDown();
- bodyHeight();
- tapLinksAndImages();
- } else {
- selectAll();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var matchesEvent = function (pattern, evt) {
+ return (
+ evt.keyCode === pattern.keyCode &&
+ evt.shiftKey === pattern.shiftKey &&
+ evt.altKey === pattern.altKey &&
+ evt.ctrlKey === pattern.ctrlKey &&
+ evt.metaKey === pattern.metaKey
+ );
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // IE
- if (isIE && Env.ie < 11) {
- removeHrOnBackspace();
- ensureBodyHasRoleApplication();
- addNewLinesBeforeBrInPre();
- removePreSerializedStylesWhenSelectingControls();
- deleteControlItemOnBackSpace();
- renderEmptyBlocksFix();
- keepNoScriptContents();
- fixCaretSelectionOfDocumentElementOnIe();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var match = function (patterns, evt) {
+ return Arr.bind(defaultPatterns(patterns), function (pattern) {
+ return matchesEvent(pattern, evt) ? [pattern] : [ ];
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (Env.ie >= 11) {
- bodyHeight();
- disableBackspaceIntoATable();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var action = function (f) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ return function () {
+ return f.apply(null, args);
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (Env.ie) {
- selectAll();
- disableAutoUrlDetect();
- ieInternalDragAndDrop();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ match: match,
+ action: action
+ };
+ }
+);
+/**
+ * ArrowKeys.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Gecko
- if (isGecko) {
- emptyEditorOnDeleteEverything();
- removeHrOnBackspace();
- focusBody();
- removeStylesWhenDeletingAcrossBlockElements();
- setGeckoEditingOptions();
- addBrAfterLastLinks();
- showBrokenImageIcon();
- blockCmdArrowNavigation();
- disableBackspaceIntoATable();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.keyboard.ArrowKeys',
+ [
+ 'ephox.katamari.api.Arr',
+ 'ephox.katamari.api.Cell',
+ 'tinymce.core.keyboard.BoundarySelection',
+ 'tinymce.core.keyboard.MatchKeys',
+ 'tinymce.core.util.VK'
+ ],
+ function (Arr, Cell, BoundarySelection, MatchKeys, VK) {
+ var setup = function (editor, caret) {
+ editor.on('keydown', function (evt) {
+ var matches = MatchKeys.match([
+ { keyCode: VK.RIGHT, action: BoundarySelection.move(editor, caret, true) },
+ { keyCode: VK.LEFT, action: BoundarySelection.move(editor, caret, false) }
+ ], evt);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- refreshContentEditable: refreshContentEditable,
- isHidden: isHidden
- };
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Arr.find(matches, function (pattern) {
+ return pattern.action();
+ }).each(function (_) {
+ evt.preventDefault();
+ });
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/EditorObservable.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ setup: setup
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * EditorObservable.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * DeleteBackspaceKeys.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.keyboard.DeleteBackspaceKeys',
+ [
+ 'ephox.katamari.api.Arr',
+ 'tinymce.core.delete.BlockBoundaryDelete',
+ 'tinymce.core.delete.BlockRangeDelete',
+ 'tinymce.core.delete.CefDelete',
+ 'tinymce.core.delete.InlineBoundaryDelete',
+ 'tinymce.core.keyboard.MatchKeys',
+ 'tinymce.core.util.VK'
+ ],
+ function (Arr, BlockBoundaryDelete, BlockRangeDelete, CefDelete, BoundaryDelete, MatchKeys, VK) {
+ var setupKeyDownHandler = function (editor, caret) {
+ editor.on('keydown', function (evt) {
+ var matches = MatchKeys.match([
+ { keyCode: VK.BACKSPACE, action: MatchKeys.action(BoundaryDelete.backspaceDelete, editor, caret, false) },
+ { keyCode: VK.DELETE, action: MatchKeys.action(BoundaryDelete.backspaceDelete, editor, caret, true) },
+ { keyCode: VK.BACKSPACE, action: MatchKeys.action(CefDelete.backspaceDelete, editor, false) },
+ { keyCode: VK.DELETE, action: MatchKeys.action(CefDelete.backspaceDelete, editor, true) },
+ { keyCode: VK.BACKSPACE, action: MatchKeys.action(BlockRangeDelete.backspaceDelete, editor, false) },
+ { keyCode: VK.DELETE, action: MatchKeys.action(BlockRangeDelete.backspaceDelete, editor, true) },
+ { keyCode: VK.BACKSPACE, action: MatchKeys.action(BlockBoundaryDelete.backspaceDelete, editor, false) },
+ { keyCode: VK.DELETE, action: MatchKeys.action(BlockBoundaryDelete.backspaceDelete, editor, true) }
+ ], evt);
+
+ Arr.find(matches, function (pattern) {
+ return pattern.action();
+ }).each(function (_) {
+ evt.preventDefault();
+ });
+ });
+ };
+
+ var setupKeyUpHandler = function (editor) {
+ editor.on('keyup', function (evt) {
+ var matches = MatchKeys.match([
+ { keyCode: VK.BACKSPACE, action: MatchKeys.action(CefDelete.paddEmptyElement, editor) },
+ { keyCode: VK.DELETE, action: MatchKeys.action(CefDelete.paddEmptyElement, editor) }
+ ], evt);
+
+ Arr.find(matches, function (pattern) {
+ return pattern.action();
+ });
+ });
+ };
+
+ var setup = function (editor, caret) {
+ setupKeyDownHandler(editor, caret);
+ setupKeyUpHandler(editor);
+ };
+
+ return {
+ setup: setup
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * This mixin contains the event logic for the tinymce.Editor class.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * EnterKey.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @mixin tinymce.EditorObservable
- * @extends tinymce.util.Observable
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/EditorObservable", [
- "tinymce/util/Observable",
- "tinymce/dom/DOMUtils",
- "tinymce/util/Tools"
-], function(Observable, DOMUtils, Tools) {
- var DOM = DOMUtils.DOM, customEventRootDelegates;
</del><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the event target so for the specified event. Some events fire
- * only on document, some fire on documentElement etc. This also handles the
- * custom event root setting where it returns that element instead of the body.
- *
- * @private
- * @param {tinymce.Editor} editor Editor instance to get event target from.
- * @param {String} eventName Name of the event for example "click".
- * @return {Element/Document} HTML Element or document target to bind on.
- */
- function getEventTarget(editor, eventName) {
- if (eventName == 'selectionchange') {
- return editor.getDoc();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Contains logic for handling the enter key to split/generate block elements.
+ */
+define(
+ 'tinymce.core.keyboard.EnterKey',
+ [
+ 'tinymce.core.caret.CaretContainer',
+ 'tinymce.core.dom.NodeType',
+ 'tinymce.core.dom.RangeUtils',
+ 'tinymce.core.dom.TreeWalker',
+ 'tinymce.core.Env',
+ 'tinymce.core.text.Zwsp',
+ 'tinymce.core.util.Tools'
+ ],
+ function (CaretContainer, NodeType, RangeUtils, TreeWalker, Env, Zwsp, Tools) {
+ var isIE = Env.ie && Env.ie < 11;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Need to bind mousedown/mouseup etc to document not body in iframe mode
- // Since the user might click on the HTML element not the BODY
- if (!editor.inline && /^mouse|touch|click|contextmenu|drop|dragover|dragend/.test(eventName)) {
- return editor.getDoc().documentElement;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isEmptyAnchor = function (elm) {
+ return elm && elm.nodeName === "A" && Tools.trim(Zwsp.trim(elm.innerText || elm.textContent)).length === 0;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Bind to event root instead of body if it's defined
- if (editor.settings.event_root) {
- if (!editor.eventRoot) {
- editor.eventRoot = DOM.select(editor.settings.event_root)[0];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isTableCell = function (node) {
+ return node && /^(TD|TH|CAPTION)$/.test(node.nodeName);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return editor.eventRoot;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var emptyBlock = function (elm) {
+ // BR is needed in empty blocks on non IE browsers
+ elm.innerHTML = !isIE ? '<br data-mce-bogus="1">' : '';
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return editor.getBody();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Returns true if the block can be split into two blocks or not
+ var canSplitBlock = function (dom, node) {
+ return node &&
+ dom.isBlock(node) &&
+ !/^(TD|TH|CAPTION|FORM)$/.test(node.nodeName) &&
+ !/^(fixed|absolute)/i.test(node.style.position) &&
+ dom.getContentEditable(node) !== "true";
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Binds a event delegate for the specified name this delegate will fire
- * the event to the editor dispatcher.
- *
- * @private
- * @param {tinymce.Editor} editor Editor instance to get event target from.
- * @param {String} eventName Name of the event for example "click".
- */
- function bindEventDelegate(editor, eventName) {
- var eventRootElm = getEventTarget(editor, eventName), delegate;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Renders empty block on IE
+ var renderBlockOnIE = function (dom, selection, block) {
+ var oldRng;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isListening(editor) {
- return !editor.hidden && !editor.readonly;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (dom.isBlock(block)) {
+ oldRng = selection.getRng();
+ block.appendChild(dom.create('span', null, '\u00a0'));
+ selection.select(block);
+ block.lastChild.outerHTML = '';
+ selection.setRng(oldRng);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!editor.delegates) {
- editor.delegates = {};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove the first empty inline element of the block so this: <p><b><em></em></b>x</p> becomes this: <p>x</p>
+ var trimInlineElementsOnLeftSideOfBlock = function (dom, nonEmptyElementsMap, block) {
+ var node = block, firstChilds = [], i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.delegates[eventName]) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!node) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.settings.event_root) {
- if (!customEventRootDelegates) {
- customEventRootDelegates = {};
- editor.editorManager.on('removeEditor', function() {
- var name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find inner most first child ex: <p><i><b>*</b></i></p>
+ while ((node = node.firstChild)) {
+ if (dom.isBlock(node)) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!editor.editorManager.activeEditor) {
- if (customEventRootDelegates) {
- for (name in customEventRootDelegates) {
- editor.dom.unbind(getEventTarget(editor, name));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.nodeType == 1 && !nonEmptyElementsMap[node.nodeName.toLowerCase()]) {
+ firstChilds.push(node);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- customEventRootDelegates = null;
- }
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ i = firstChilds.length;
+ while (i--) {
+ node = firstChilds[i];
+ if (!node.hasChildNodes() || (node.firstChild == node.lastChild && node.firstChild.nodeValue === '')) {
+ dom.remove(node);
+ } else {
+ if (isEmptyAnchor(node)) {
+ dom.remove(node);
+ }
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (customEventRootDelegates[eventName]) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var normalizeZwspOffset = function (start, container, offset) {
+ if (NodeType.isText(container) === false) {
+ return offset;
+ } if (start) {
+ return offset === 1 && container.data.charAt(offset - 1) === Zwsp.ZWSP ? 0 : offset;
+ } else {
+ return offset === container.data.length - 1 && container.data.charAt(offset) === Zwsp.ZWSP ? container.data.length : offset;
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- delegate = function(e) {
- var target = e.target, editors = editor.editorManager.editors, i = editors.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var includeZwspInRange = function (rng) {
+ var newRng = rng.cloneRange();
+ newRng.setStart(rng.startContainer, normalizeZwspOffset(true, rng.startContainer, rng.startOffset));
+ newRng.setEnd(rng.endContainer, normalizeZwspOffset(false, rng.endContainer, rng.endOffset));
+ return newRng;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- var body = editors[i].getBody();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var firstNonWhiteSpaceNodeSibling = function (node) {
+ while (node) {
+ if (node.nodeType === 1 || (node.nodeType === 3 && node.data && /[\r\n\s]/.test(node.data))) {
+ return node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (body === target || DOM.isChildOf(target, body)) {
- if (isListening(editors[i])) {
- editors[i].fire(eventName, e);
- }
- }
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node.nextSibling;
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- customEventRootDelegates[eventName] = delegate;
- DOM.bind(eventRootElm, eventName, delegate);
- } else {
- delegate = function(e) {
- if (isListening(editor)) {
- editor.fire(eventName, e);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var setup = function (editor) {
+ var dom = editor.dom, selection = editor.selection, settings = editor.settings;
+ var undoManager = editor.undoManager, schema = editor.schema, nonEmptyElementsMap = schema.getNonEmptyElements(),
+ moveCaretBeforeOnEnterElementsMap = schema.getMoveCaretBeforeOnEnterElements();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DOM.bind(eventRootElm, eventName, delegate);
- editor.delegates[eventName] = delegate;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function handleEnterKey(evt) {
+ var rng, tmpRng, editableRoot, container, offset, parentBlock, documentMode, shiftKey,
+ newBlock, fragment, containerBlock, parentBlockName, containerBlockName, newBlockName, isAfterLastNodeInContainer;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var EditorObservable = {
- /**
- * Bind any pending event delegates. This gets executed after the target body/document is created.
- *
- * @private
- */
- bindPendingEventDelegates: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Moves the caret to a suitable position within the root for example in the first non
+ // pure whitespace text node or before an image
+ function moveToCaretPosition(root) {
+ var walker, node, rng, lastNode = root, tempElm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(self._pendingNativeEvents, function(name) {
- bindEventDelegate(self, name);
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!root) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Toggles a native event on/off this is called by the EventDispatcher when
- * the first native event handler is added and when the last native event handler is removed.
- *
- * @private
- */
- toggleNativeEvent: function(name, state) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Old IE versions doesn't properly render blocks with br elements in them
+ // For example <p><br></p> wont be rendered correctly in a contentEditable area
+ // until you remove the br producing <p></p>
+ if (Env.ie && Env.ie < 9 && parentBlock && parentBlock.firstChild) {
+ if (parentBlock.firstChild == parentBlock.lastChild && parentBlock.firstChild.tagName == 'BR') {
+ dom.remove(parentBlock.firstChild);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Never bind focus/blur since the FocusManager fakes those
- if (name == "focus" || name == "blur") {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (/^(LI|DT|DD)$/.test(root.nodeName)) {
+ var firstChild = firstNonWhiteSpaceNodeSibling(root.firstChild);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (state) {
- if (self.initialized) {
- bindEventDelegate(self, name);
- } else {
- if (!self._pendingNativeEvents) {
- self._pendingNativeEvents = [name];
- } else {
- self._pendingNativeEvents.push(name);
- }
- }
- } else if (self.initialized) {
- self.dom.unbind(getEventTarget(self, name), name, self.delegates[name]);
- delete self.delegates[name];
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (firstChild && /^(UL|OL|DL)$/.test(firstChild.nodeName)) {
+ root.insertBefore(dom.doc.createTextNode('\u00a0'), root.firstChild);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Unbinds all native event handlers that means delegates, custom events bound using the Events API etc.
- *
- * @private
- */
- unbindAllNativeEvents: function() {
- var self = this, name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng = dom.createRng();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.delegates) {
- for (name in self.delegates) {
- self.dom.unbind(getEventTarget(self, name), name, self.delegates[name]);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Normalize whitespace to remove empty text nodes. Fix for: #6904
+ // Gecko will be able to place the caret in empty text nodes but it won't render propery
+ // Older IE versions will sometimes crash so for now ignore all IE versions
+ if (!Env.ie) {
+ root.normalize();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- delete self.delegates;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (root.hasChildNodes()) {
+ walker = new TreeWalker(root, root);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.inline) {
- self.getBody().onload = null;
- self.dom.unbind(self.getWin());
- self.dom.unbind(self.getDoc());
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while ((node = walker.current())) {
+ if (node.nodeType == 3) {
+ rng.setStart(node, 0);
+ rng.setEnd(node, 0);
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.dom.unbind(self.getBody());
- self.dom.unbind(self.getContainer());
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (moveCaretBeforeOnEnterElementsMap[node.nodeName.toLowerCase()]) {
+ rng.setStartBefore(node);
+ rng.setEndBefore(node);
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- EditorObservable = Tools.extend({}, Observable, EditorObservable);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ lastNode = node;
+ node = walker.next();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return EditorObservable;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!node) {
+ rng.setStart(lastNode, 0);
+ rng.setEnd(lastNode, 0);
+ }
+ } else {
+ if (root.nodeName == 'BR') {
+ if (root.nextSibling && dom.isBlock(root.nextSibling)) {
+ // Trick on older IE versions to render the caret before the BR between two lists
+ if (!documentMode || documentMode < 9) {
+ tempElm = dom.create('br');
+ root.parentNode.insertBefore(tempElm, root);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/Mode.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng.setStartBefore(root);
+ rng.setEndBefore(root);
+ } else {
+ rng.setStartAfter(root);
+ rng.setEndAfter(root);
+ }
+ } else {
+ rng.setStart(root, 0);
+ rng.setEnd(root, 0);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Mode.js
- *
- * Released under LGPL License.
- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ selection.setRng(rng);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Mode switcher logic.
- *
- * @private
- * @class tinymce.Mode
- */
-define("tinymce/Mode", [], function() {
- function setEditorCommandState(editor, cmd, state) {
- try {
- editor.getDoc().execCommand(cmd, false, state);
- } catch (ex) {
- // Ignore
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove tempElm created for old IE:s
+ dom.remove(tempElm);
+ selection.scrollIntoView(root);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function clickBlocker(editor) {
- var target, handler;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setForcedBlockAttrs(node) {
+ var forcedRootBlockName = settings.forced_root_block;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- target = editor.getBody();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (forcedRootBlockName && forcedRootBlockName.toLowerCase() === node.tagName.toLowerCase()) {
+ dom.setAttribs(node, settings.forced_root_block_attrs);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- handler = function(e) {
- if (editor.dom.getParents(e.target, 'a').length > 0) {
- e.preventDefault();
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Creates a new block element by cloning the current one or creating a new one if the name is specified
+ // This function will also copy any text formatting from the parent block and add it to the new one
+ function createNewBlock(name) {
+ var node = container, block, clonedNode, caretNode, textInlineElements = schema.getTextInlineElements();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.dom.bind(target, 'click', handler);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name || parentBlockName == "TABLE") {
+ block = dom.create(name || newBlockName);
+ setForcedBlockAttrs(block);
+ } else {
+ block = parentBlock.cloneNode(false);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- unbind: function() {
- editor.dom.unbind(target, 'click', handler);
- }
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ caretNode = block;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function toggleReadOnly(editor, state) {
- if (editor._clickBlocker) {
- editor._clickBlocker.unbind();
- editor._clickBlocker = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.keep_styles === false) {
+ dom.setAttrib(block, 'style', null); // wipe out any styles that came over with the block
+ dom.setAttrib(block, 'class', null);
+ } else {
+ // Clone any parent styles
+ do {
+ if (textInlineElements[node.nodeName]) {
+ // Never clone a caret containers
+ if (node.id == '_mce_caret') {
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (state) {
- editor._clickBlocker = clickBlocker(editor);
- editor.selection.controlSelection.hideResizeRect();
- editor.readonly = true;
- editor.getBody().contentEditable = false;
- } else {
- editor.readonly = false;
- editor.getBody().contentEditable = true;
- setEditorCommandState(editor, "StyleWithCSS", false);
- setEditorCommandState(editor, "enableInlineTableEditing", false);
- setEditorCommandState(editor, "enableObjectResizing", false);
- editor.focus();
- editor.nodeChanged();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ clonedNode = node.cloneNode(false);
+ dom.setAttrib(clonedNode, 'id', ''); // Remove ID since it needs to be document unique
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setMode(editor, mode) {
- var currentMode = editor.readonly ? 'readonly' : 'design';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (block.hasChildNodes()) {
+ clonedNode.appendChild(block.firstChild);
+ block.appendChild(clonedNode);
+ } else {
+ caretNode = clonedNode;
+ block.appendChild(clonedNode);
+ }
+ }
+ } while ((node = node.parentNode) && node != editableRoot);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (mode == currentMode) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // BR is needed in empty blocks on non IE browsers
+ if (!isIE) {
+ caretNode.innerHTML = '<br data-mce-bogus="1">';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.initialized) {
- toggleReadOnly(editor, mode == 'readonly');
- } else {
- editor.on('init', function() {
- toggleReadOnly(editor, mode == 'readonly');
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return block;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Event is NOT preventable
- editor.fire('SwitchMode', {mode: mode});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Returns true/false if the caret is at the start/end of the parent block element
+ function isCaretAtStartOrEndOfBlock(start) {
+ var walker, node, name, normalizedOffset;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- setMode: setMode
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ normalizedOffset = normalizeZwspOffset(start, container, offset);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/Shortcuts.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Caret is in the middle of a text node like "a|b"
+ if (container.nodeType == 3 && (start ? normalizedOffset > 0 : normalizedOffset < container.nodeValue.length)) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Shortcuts.js
- *
- * Released under LGPL License.
- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If after the last element in block node edge case for #5091
+ if (container.parentNode == parentBlock && isAfterLastNodeInContainer && !start) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Contains all logic for handling of keyboard shortcuts.
- *
- * @class tinymce.Shortcuts
- * @example
- * editor.shortcuts.add('ctrl+a', function() {});
- * editor.shortcuts.add('meta+a', function() {}); // "meta" maps to Command on Mac and Ctrl on PC
- * editor.shortcuts.add('ctrl+alt+a', function() {});
- * editor.shortcuts.add('access+a', function() {}); // "access" maps to ctrl+alt on Mac and shift+alt on PC
- */
-define("tinymce/Shortcuts", [
- "tinymce/util/Tools",
- "tinymce/Env"
-], function(Tools, Env) {
- var each = Tools.each, explode = Tools.explode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If the caret if before the first element in parentBlock
+ if (start && container.nodeType == 1 && container == parentBlock.firstChild) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var keyCodeLookup = {
- "f9": 120,
- "f10": 121,
- "f11": 122
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Caret can be before/after a table
+ if (container.nodeName === "TABLE" || (container.previousSibling && container.previousSibling.nodeName == "TABLE")) {
+ return (isAfterLastNodeInContainer && !start) || (!isAfterLastNodeInContainer && start);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var modifierNames = Tools.makeMap('alt,ctrl,shift,meta,access');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Walk the DOM and look for text nodes or non empty elements
+ walker = new TreeWalker(container, parentBlock);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function(editor) {
- var self = this, shortcuts = {}, pendingPatterns = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If caret is in beginning or end of a text block then jump to the next/previous node
+ if (container.nodeType == 3) {
+ if (start && normalizedOffset === 0) {
+ walker.prev();
+ } else if (!start && normalizedOffset == container.nodeValue.length) {
+ walker.next();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function parseShortcut(pattern) {
- var id, key, shortcut = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while ((node = walker.current())) {
+ if (node.nodeType === 1) {
+ // Ignore bogus elements
+ if (!node.getAttribute('data-mce-bogus')) {
+ // Keep empty elements like <img /> <input /> but not trailing br:s like <p>text|<br></p>
+ name = node.nodeName.toLowerCase();
+ if (nonEmptyElementsMap[name] && name !== 'br') {
+ return false;
+ }
+ }
+ } else if (node.nodeType === 3 && !/^[ \t\r\n]*$/.test(node.nodeValue)) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Parse modifiers and keys ctrl+alt+b for example
- each(explode(pattern, '+'), function(value) {
- if (value in modifierNames) {
- shortcut[value] = true;
- } else {
- // Allow numeric keycodes like ctrl+219 for ctrl+[
- if (/^[0-9]{2,}$/.test(value)) {
- shortcut.keyCode = parseInt(value, 10);
- } else {
- shortcut.charCode = value.charCodeAt(0);
- shortcut.keyCode = keyCodeLookup[value] || value.toUpperCase().charCodeAt(0);
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (start) {
+ walker.prev();
+ } else {
+ walker.next();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Generate unique id for modifier combination and set default state for unused modifiers
- id = [shortcut.keyCode];
- for (key in modifierNames) {
- if (shortcut[key]) {
- id.push(key);
- } else {
- shortcut[key] = false;
- }
- }
- shortcut.id = id.join(',');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle special access modifier differently depending on Mac/Win
- if (shortcut.access) {
- shortcut.alt = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Wraps any text nodes or inline elements in the specified forced root block name
+ function wrapSelfAndSiblingsInDefaultBlock(container, offset) {
+ var newBlock, parentBlock, startNode, node, next, rootBlockName, blockName = newBlockName || 'P';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (Env.mac) {
- shortcut.ctrl = true;
- } else {
- shortcut.shift = true;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Not in a block element or in a table cell or caption
+ parentBlock = dom.getParent(container, dom.isBlock);
+ if (!parentBlock || !canSplitBlock(dom, parentBlock)) {
+ parentBlock = parentBlock || editableRoot;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle special meta modifier differently depending on Mac/Win
- if (shortcut.meta) {
- if (Env.mac) {
- shortcut.meta = true;
- } else {
- shortcut.ctrl = true;
- shortcut.meta = false;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parentBlock == editor.getBody() || isTableCell(parentBlock)) {
+ rootBlockName = parentBlock.nodeName.toLowerCase();
+ } else {
+ rootBlockName = parentBlock.parentNode.nodeName.toLowerCase();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return shortcut;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!parentBlock.hasChildNodes()) {
+ newBlock = dom.create(blockName);
+ setForcedBlockAttrs(newBlock);
+ parentBlock.appendChild(newBlock);
+ rng.setStart(newBlock, 0);
+ rng.setEnd(newBlock, 0);
+ return newBlock;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function createShortcut(pattern, desc, cmdFunc, scope) {
- var shortcuts;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find parent that is the first child of parentBlock
+ node = container;
+ while (node.parentNode != parentBlock) {
+ node = node.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- shortcuts = Tools.map(explode(pattern, '>'), parseShortcut);
- shortcuts[shortcuts.length - 1] = Tools.extend(shortcuts[shortcuts.length - 1], {
- func: cmdFunc,
- scope: scope || editor
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Loop left to find start node start wrapping at
+ while (node && !dom.isBlock(node)) {
+ startNode = node;
+ node = node.previousSibling;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Tools.extend(shortcuts[0], {
- desc: editor.translate(desc),
- subpatterns: shortcuts.slice(1)
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (startNode && schema.isValidChild(rootBlockName, blockName.toLowerCase())) {
+ newBlock = dom.create(blockName);
+ setForcedBlockAttrs(newBlock);
+ startNode.parentNode.insertBefore(newBlock, startNode);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hasModifier(e) {
- return e.altKey || e.ctrlKey || e.metaKey;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Start wrapping until we hit a block
+ node = startNode;
+ while (node && !dom.isBlock(node)) {
+ next = node.nextSibling;
+ newBlock.appendChild(node);
+ node = next;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isFunctionKey(e) {
- return e.type === "keydown" && e.keyCode >= 112 && e.keyCode <= 123;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Restore range to it's past location
+ rng.setStart(container, offset);
+ rng.setEnd(container, offset);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function matchShortcut(e, shortcut) {
- if (!shortcut) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return container;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (shortcut.ctrl != e.ctrlKey || shortcut.meta != e.metaKey) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Inserts a block or br before/after or in the middle of a split list of the LI is empty
+ function handleEmptyListItem() {
+ function isFirstOrLastLi(first) {
+ var node = containerBlock[first ? 'firstChild' : 'lastChild'];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (shortcut.alt != e.altKey || shortcut.shift != e.shiftKey) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find first/last element since there might be whitespace there
+ while (node) {
+ if (node.nodeType == 1) {
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.keyCode == shortcut.keyCode || (e.charCode && e.charCode == shortcut.charCode)) {
- e.preventDefault();
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node[first ? 'nextSibling' : 'previousSibling'];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return node === parentBlock;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function executeShortcutAction(shortcut) {
- return shortcut.func ? shortcut.func.call(shortcut.scope) : null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getContainerBlock() {
+ var containerBlockParent = containerBlock.parentNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('keyup keypress keydown', function(e) {
- if ((hasModifier(e) || isFunctionKey(e)) && !e.isDefaultPrevented()) {
- each(shortcuts, function(shortcut) {
- if (matchShortcut(e, shortcut)) {
- pendingPatterns = shortcut.subpatterns.slice(0);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (/^(LI|DT|DD)$/.test(containerBlockParent.nodeName)) {
+ return containerBlockParent;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.type == "keydown") {
- executeShortcutAction(shortcut);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return containerBlock;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (containerBlock == editor.getBody()) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (matchShortcut(e, pendingPatterns[0])) {
- if (pendingPatterns.length === 1) {
- if (e.type == "keydown") {
- executeShortcutAction(pendingPatterns[0]);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if we are in an nested list
+ var containerBlockParentName = containerBlock.parentNode.nodeName;
+ if (/^(OL|UL|LI)$/.test(containerBlockParentName)) {
+ newBlockName = 'LI';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- pendingPatterns.shift();
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ newBlock = newBlockName ? createNewBlock(newBlockName) : dom.create('BR');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds a keyboard shortcut for some command or function.
- *
- * @method add
- * @param {String} pattern Shortcut pattern. Like for example: ctrl+alt+o.
- * @param {String} desc Text description for the command.
- * @param {String/Function} cmdFunc Command name string or function to execute when the key is pressed.
- * @param {Object} scope Optional scope to execute the function in.
- * @return {Boolean} true/false state if the shortcut was added or not.
- */
- self.add = function(pattern, desc, cmdFunc, scope) {
- var cmd;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isFirstOrLastLi(true) && isFirstOrLastLi()) {
+ if (containerBlockParentName == 'LI') {
+ // Nested list is inside a LI
+ dom.insertAfter(newBlock, getContainerBlock());
+ } else {
+ // Is first and last list item then replace the OL/UL with a text block
+ dom.replace(newBlock, containerBlock);
+ }
+ } else if (isFirstOrLastLi(true)) {
+ if (containerBlockParentName == 'LI') {
+ // List nested in an LI then move the list to a new sibling LI
+ dom.insertAfter(newBlock, getContainerBlock());
+ newBlock.appendChild(dom.doc.createTextNode(' ')); // Needed for IE so the caret can be placed
+ newBlock.appendChild(containerBlock);
+ } else {
+ // First LI in list then remove LI and add text block before list
+ containerBlock.parentNode.insertBefore(newBlock, containerBlock);
+ }
+ } else if (isFirstOrLastLi()) {
+ // Last LI in list then remove LI and add text block after list
+ dom.insertAfter(newBlock, getContainerBlock());
+ renderBlockOnIE(dom, selection, newBlock);
+ } else {
+ // Middle LI in list the split the list and insert a text block in the middle
+ // Extract after fragment and insert it after the current block
+ containerBlock = getContainerBlock();
+ tmpRng = rng.cloneRange();
+ tmpRng.setStartAfter(parentBlock);
+ tmpRng.setEndAfter(containerBlock);
+ fragment = tmpRng.extractContents();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- cmd = cmdFunc;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (newBlockName == 'LI' && fragment.firstChild.nodeName == 'LI') {
+ newBlock = fragment.firstChild;
+ dom.insertAfter(fragment, containerBlock);
+ } else {
+ dom.insertAfter(fragment, containerBlock);
+ dom.insertAfter(newBlock, containerBlock);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof cmdFunc === 'string') {
- cmdFunc = function() {
- editor.execCommand(cmd, false, null);
- };
- } else if (Tools.isArray(cmd)) {
- cmdFunc = function() {
- editor.execCommand(cmd[0], cmd[1], cmd[2]);
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.remove(parentBlock);
+ moveToCaretPosition(newBlock);
+ undoManager.add();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(explode(Tools.trim(pattern.toLowerCase())), function(pattern) {
- var shortcut = createShortcut(pattern, desc, cmdFunc, scope);
- shortcuts[shortcut.id] = shortcut;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Inserts a BR element if the forced_root_block option is set to false or empty string
+ function insertBr() {
+ editor.execCommand("InsertLineBreak", false, evt);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Trims any linebreaks at the beginning of node user for example when pressing enter in a PRE element
+ function trimLeadingLineBreaks(node) {
+ do {
+ if (node.nodeType === 3) {
+ node.nodeValue = node.nodeValue.replace(/^[\r\n]+/, '');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Remove a keyboard shortcut by pattern.
- *
- * @method remove
- * @param {String} pattern Shortcut pattern. Like for example: ctrl+alt+o.
- * @return {Boolean} true/false state if the shortcut was removed or not.
- */
- self.remove = function(pattern) {
- var shortcut = createShortcut(pattern);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node.firstChild;
+ } while (node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (shortcuts[shortcut.id]) {
- delete shortcuts[shortcut.id];
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getEditableRoot(node) {
+ var root = dom.getRoot(), parent, editableRoot;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- };
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get all parents until we hit a non editable parent or the root
+ parent = node;
+ while (parent !== root && dom.getContentEditable(parent) !== "false") {
+ if (dom.getContentEditable(parent) === "true") {
+ editableRoot = parent;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/file/Uploader.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parent = parent.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Uploader.js
- *
- * Released under LGPL License.
- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return parent !== root ? editableRoot : root;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Upload blobs or blob infos to the specified URL or handler.
- *
- * @private
- * @class tinymce.file.Uploader
- * @example
- * var uploader = new Uploader({
- * url: '/upload.php',
- * basePath: '/base/path',
- * credentials: true,
- * handler: function(data, success, failure) {
- * ...
- * }
- * });
- *
- * uploader.upload(blobInfos).then(function(result) {
- * ...
- * });
- */
-define("tinymce/file/Uploader", [
- "tinymce/util/Promise",
- "tinymce/util/Tools",
- "tinymce/util/Fun"
-], function(Promise, Tools, Fun) {
- return function(uploadStatus, settings) {
- var pendingPromises = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Adds a BR at the end of blocks that only contains an IMG or INPUT since
+ // these might be floated and then they won't expand the block
+ function addBrToBlockIfNeeded(block) {
+ var lastChild;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function filename(blobInfo) {
- var ext, extensions;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // IE will render the blocks correctly other browsers needs a BR
+ if (!isIE) {
+ block.normalize(); // Remove empty text nodes that got left behind by the extract
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- extensions = {
- 'image/jpeg': 'jpg',
- 'image/jpg': 'jpg',
- 'image/gif': 'gif',
- 'image/png': 'png'
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if the block is empty or contains a floated last child
+ lastChild = block.lastChild;
+ if (!lastChild || (/^(left|right)$/gi.test(dom.getStyle(lastChild, 'float', true)))) {
+ dom.add(block, 'br');
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ext = extensions[blobInfo.blob().type.toLowerCase()] || 'dat';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function insertNewBlockAfter() {
+ // If the caret is at the end of a header we produce a P tag after it similar to Word unless we are in a hgroup
+ if (/^(H[1-6]|PRE|FIGURE)$/.test(parentBlockName) && containerBlockName != 'HGROUP') {
+ newBlock = createNewBlock(newBlockName);
+ } else {
+ newBlock = createNewBlock();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return blobInfo.filename() + '.' + ext;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Split the current container block element if enter is pressed inside an empty inner block element
+ if (settings.end_container_on_empty_block && canSplitBlock(dom, containerBlock) && dom.isEmpty(parentBlock)) {
+ // Split container block for example a BLOCKQUOTE at the current blockParent location for example a P
+ newBlock = dom.split(containerBlock, parentBlock);
+ } else {
+ dom.insertAfter(newBlock, parentBlock);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function pathJoin(path1, path2) {
- if (path1) {
- return path1.replace(/\/$/, '') + '/' + path2.replace(/^\//, '');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ moveToCaretPosition(newBlock);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return path2;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng = selection.getRng(true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function blobInfoToData(blobInfo) {
- return {
- id: blobInfo.id,
- blob: blobInfo.blob,
- base64: blobInfo.base64,
- filename: Fun.constant(filename(blobInfo))
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Event is blocked by some other handler for example the lists plugin
+ if (evt.isDefaultPrevented()) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function defaultHandler(blobInfo, success, failure, progress) {
- var xhr, formData;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Delete any selected contents
+ if (!rng.collapsed) {
+ editor.execCommand('Delete');
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- xhr = new XMLHttpRequest();
- xhr.open('POST', settings.url);
- xhr.withCredentials = settings.credentials;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup range items and newBlockName
+ new RangeUtils(dom).normalize(rng);
+ container = rng.startContainer;
+ offset = rng.startOffset;
+ newBlockName = (settings.force_p_newlines ? 'p' : '') || settings.forced_root_block;
+ newBlockName = newBlockName ? newBlockName.toUpperCase() : '';
+ documentMode = dom.doc.documentMode;
+ shiftKey = evt.shiftKey;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- xhr.upload.onprogress = function(e) {
- progress(e.loaded / e.total * 100);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Resolve node index
+ if (container.nodeType == 1 && container.hasChildNodes()) {
+ isAfterLastNodeInContainer = offset > container.childNodes.length - 1;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- xhr.onerror = function() {
- failure("Image upload failed due to a XHR Transport error. Code: " + xhr.status);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container;
+ if (isAfterLastNodeInContainer && container.nodeType == 3) {
+ offset = container.nodeValue.length;
+ } else {
+ offset = 0;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- xhr.onload = function() {
- var json;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get editable root node, normally the body element but sometimes a div or span
+ editableRoot = getEditableRoot(container);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (xhr.status != 200) {
- failure("HTTP Error: " + xhr.status);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If there is no editable root then enter is done inside a contentEditable false element
+ if (!editableRoot) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- json = JSON.parse(xhr.responseText);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ undoManager.beforeChange();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!json || typeof json.location != "string") {
- failure("Invalid JSON: " + xhr.responseText);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If editable root isn't block nor the root of the editor
+ if (!dom.isBlock(editableRoot) && editableRoot != dom.getRoot()) {
+ if (!newBlockName || shiftKey) {
+ insertBr();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- success(pathJoin(settings.basePath, json.location));
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- formData = new FormData();
- formData.append('file', blobInfo.blob(), blobInfo.filename());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Wrap the current node and it's sibling in a default block if it's needed.
+ // for example this <td>text|<b>text2</b></td> will become this <td><p>text|<b>text2</p></b></td>
+ // This won't happen if root blocks are disabled or the shiftKey is pressed
+ if ((newBlockName && !shiftKey) || (!newBlockName && shiftKey)) {
+ container = wrapSelfAndSiblingsInDefaultBlock(container, offset);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- xhr.send(formData);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find parent block and setup empty block paddings
+ parentBlock = dom.getParent(container, dom.isBlock);
+ containerBlock = parentBlock ? dom.getParent(parentBlock.parentNode, dom.isBlock) : null;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function noUpload() {
- return new Promise(function(resolve) {
- resolve([]);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup block names
+ parentBlockName = parentBlock ? parentBlock.nodeName.toUpperCase() : ''; // IE < 9 & HTML5
+ containerBlockName = containerBlock ? containerBlock.nodeName.toUpperCase() : ''; // IE < 9 & HTML5
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function handlerSuccess(blobInfo, url) {
- return {
- url: url,
- blobInfo: blobInfo,
- status: true
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Enter inside block contained within a LI then split or insert before/after LI
+ if (containerBlockName == 'LI' && !evt.ctrlKey) {
+ parentBlock = containerBlock;
+ parentBlockName = containerBlockName;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function handlerFailure(blobInfo, error) {
- return {
- url: '',
- blobInfo: blobInfo,
- status: false,
- error: error
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.undoManager.typing) {
+ editor.undoManager.typing = false;
+ editor.undoManager.add();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function resolvePending(blobUri, result) {
- Tools.each(pendingPromises[blobUri], function(resolve) {
- resolve(result);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handle enter in list item
+ if (/^(LI|DT|DD)$/.test(parentBlockName)) {
+ if (!newBlockName && shiftKey) {
+ insertBr();
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- delete pendingPromises[blobUri];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handle enter inside an empty list item
+ if (dom.isEmpty(parentBlock)) {
+ handleEmptyListItem();
+ return;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function uploadBlobInfo(blobInfo, handler, openNotification) {
- uploadStatus.markPending(blobInfo.blobUri());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't split PRE tags but insert a BR instead easier when writing code samples etc
+ if (parentBlockName == 'PRE' && settings.br_in_pre !== false) {
+ if (!shiftKey) {
+ insertBr();
+ return;
+ }
+ } else {
+ // If no root block is configured then insert a BR by default or if the shiftKey is pressed
+ if ((!newBlockName && !shiftKey && parentBlockName != 'LI') || (newBlockName && shiftKey)) {
+ insertBr();
+ return;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return new Promise(function(resolve) {
- var notification, progress;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If parent block is root then never insert new blocks
+ if (newBlockName && parentBlock === editor.getBody()) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var noop = function() {
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Default block name if it's not configured
+ newBlockName = newBlockName || 'P';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- try {
- var closeNotification = function() {
- if (notification) {
- notification.close();
- progress = noop; // Once it's closed it's closed
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Insert new block before/after the parent block depending on caret location
+ if (CaretContainer.isCaretContainerBlock(parentBlock)) {
+ newBlock = CaretContainer.showCaretContainerBlock(parentBlock);
+ if (dom.isEmpty(parentBlock)) {
+ emptyBlock(parentBlock);
+ }
+ moveToCaretPosition(newBlock);
+ } else if (isCaretAtStartOrEndOfBlock()) {
+ insertNewBlockAfter();
+ } else if (isCaretAtStartOrEndOfBlock(true)) {
+ // Insert new block before
+ newBlock = parentBlock.parentNode.insertBefore(createNewBlock(), parentBlock);
+ renderBlockOnIE(dom, selection, newBlock);
+ moveToCaretPosition(parentBlock);
+ } else {
+ // Extract after fragment and insert it after the current block
+ tmpRng = includeZwspInRange(rng).cloneRange();
+ tmpRng.setEndAfter(parentBlock);
+ fragment = tmpRng.extractContents();
+ trimLeadingLineBreaks(fragment);
+ newBlock = fragment.firstChild;
+ dom.insertAfter(fragment, parentBlock);
+ trimInlineElementsOnLeftSideOfBlock(dom, nonEmptyElementsMap, newBlock);
+ addBrToBlockIfNeeded(parentBlock);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var success = function(url) {
- closeNotification();
- uploadStatus.markUploaded(blobInfo.blobUri(), url);
- resolvePending(blobInfo.blobUri(), handlerSuccess(blobInfo, url));
- resolve(handlerSuccess(blobInfo, url));
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (dom.isEmpty(parentBlock)) {
+ emptyBlock(parentBlock);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var failure = function(error) {
- closeNotification();
- uploadStatus.removeFailed(blobInfo.blobUri());
- resolvePending(blobInfo.blobUri(), handlerFailure(blobInfo, error));
- resolve(handlerFailure(blobInfo, error));
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ newBlock.normalize();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- progress = function(percent) {
- if (percent < 0 || percent > 100) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // New block might become empty if it's <p><b>a |</b></p>
+ if (dom.isEmpty(newBlock)) {
+ dom.remove(newBlock);
+ insertNewBlockAfter();
+ } else {
+ moveToCaretPosition(newBlock);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!notification) {
- notification = openNotification();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.setAttrib(newBlock, 'id', ''); // Remove ID since it needs to be document unique
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- notification.progressBar.value(percent);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Allow custom handling of new blocks
+ editor.fire('NewBlock', { newBlock: newBlock });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- handler(blobInfoToData(blobInfo), success, failure, progress);
- } catch (ex) {
- resolve(handlerFailure(blobInfo, ex.message));
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ undoManager.typing = false;
+ undoManager.add();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isDefaultHandler(handler) {
- return handler === defaultHandler;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('keydown', function (evt) {
+ if (evt.keyCode == 13) {
+ if (handleEnterKey(evt) !== false) {
+ evt.preventDefault();
+ }
+ }
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function pendingUploadBlobInfo(blobInfo) {
- var blobUri = blobInfo.blobUri();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ setup: setup
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return new Promise(function(resolve) {
- pendingPromises[blobUri] = pendingPromises[blobUri] || [];
- pendingPromises[blobUri].push(resolve);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * InsertSpace.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function uploadBlobs(blobInfos, openNotification) {
- blobInfos = Tools.grep(blobInfos, function(blobInfo) {
- return !uploadStatus.isUploaded(blobInfo.blobUri());
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.keyboard.InsertSpace',
+ [
+ 'ephox.katamari.api.Fun',
+ 'tinymce.core.caret.CaretPosition',
+ 'tinymce.core.dom.NodeType',
+ 'tinymce.core.keyboard.BoundaryLocation'
+ ],
+ function (Fun, CaretPosition, NodeType, BoundaryLocation) {
+ var isValidInsertPoint = function (location, caretPosition) {
+ return isAtStartOrEnd(location) && NodeType.isText(caretPosition.container());
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Promise.all(Tools.map(blobInfos, function(blobInfo) {
- return uploadStatus.isPending(blobInfo.blobUri()) ?
- pendingUploadBlobInfo(blobInfo) : uploadBlobInfo(blobInfo, settings.handler, openNotification);
- }));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var insertNbspAtPosition = function (editor, caretPosition) {
+ var container = caretPosition.container();
+ var offset = caretPosition.offset();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function upload(blobInfos, openNotification) {
- return (!settings.url && isDefaultHandler(settings.handler)) ? noUpload() : uploadBlobs(blobInfos, openNotification);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container.insertData(offset, '\u00a0');
+ editor.selection.setCursorLocation(container, offset + 1);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- settings = Tools.extend({
- credentials: false,
- // We are adding a notify argument to this (at the moment, until it doesn't work)
- handler: defaultHandler
- }, settings);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var insertAtLocation = function (editor, caretPosition, location) {
+ if (isValidInsertPoint(location, caretPosition)) {
+ insertNbspAtPosition(editor, caretPosition);
+ return true;
+ } else {
+ return false;
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- upload: upload
- };
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var insertAtCaret = function (editor) {
+ var caretPosition = CaretPosition.fromRangeStart(editor.selection.getRng());
+ var boundaryLocation = BoundaryLocation.readLocation(editor.getBody(), caretPosition);
+ return boundaryLocation.map(Fun.curry(insertAtLocation, editor, caretPosition)).getOr(false);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/file/Conversions.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isAtStartOrEnd = function (location) {
+ return location.fold(
+ Fun.constant(false), // Before
+ Fun.constant(true), // Start
+ Fun.constant(true), // End
+ Fun.constant(false) // After
+ );
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var insertAtSelection = function (editor) {
+ return editor.selection.isCollapsed() ? insertAtCaret(editor) : false;
+ };
+
+ return {
+ insertAtSelection: insertAtSelection
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Conversions.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * SpaceKey.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.keyboard.SpaceKey',
+ [
+ 'ephox.katamari.api.Arr',
+ 'tinymce.core.keyboard.InsertSpace',
+ 'tinymce.core.keyboard.MatchKeys',
+ 'tinymce.core.util.VK'
+ ],
+ function (Arr, InsertSpace, MatchKeys, VK) {
+ var setupKeyDownHandler = function (editor, caret) {
+ editor.on('keydown', function (evt) {
+ var matches = MatchKeys.match([
+ { keyCode: VK.SPACEBAR, action: MatchKeys.action(InsertSpace.insertAtSelection, editor) }
+ ], evt);
+
+ Arr.find(matches, function (pattern) {
+ return pattern.action();
+ }).each(function (_) {
+ evt.preventDefault();
+ });
+ });
+ };
+
+ var setup = function (editor) {
+ setupKeyDownHandler(editor);
+ };
+
+ return {
+ setup: setup
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Converts blob/uris back and forth.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * KeyboardOverrides.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.core.keyboard.KeyboardOverrides',
+ [
+ 'tinymce.core.keyboard.ArrowKeys',
+ 'tinymce.core.keyboard.BoundarySelection',
+ 'tinymce.core.keyboard.DeleteBackspaceKeys',
+ 'tinymce.core.keyboard.EnterKey',
+ 'tinymce.core.keyboard.SpaceKey'
+ ],
+ function (ArrowKeys, BoundarySelection, DeleteBackspaceKeys, EnterKey, SpaceKey) {
+ var setup = function (editor) {
+ var caret = BoundarySelection.setupSelectedState(editor);
+
+ ArrowKeys.setup(editor, caret);
+ DeleteBackspaceKeys.setup(editor, caret);
+ EnterKey.setup(editor);
+ SpaceKey.setup(editor);
+ };
+
+ return {
+ setup: setup
+ };
+ }
+);
+/**
+ * NodeChange.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+/**
+ * This class handles the nodechange event dispatching both manual and through selection change events.
+ *
+ * @class tinymce.NodeChange
</ins><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @class tinymce.file.Conversions
</del><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/file/Conversions", [
- "tinymce/util/Promise"
-], function(Promise) {
- function blobUriToBlob(url) {
- return new Promise(function(resolve) {
- var xhr = new XMLHttpRequest();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.NodeChange',
+ [
+ "tinymce.core.dom.RangeUtils",
+ "tinymce.core.Env",
+ "tinymce.core.util.Delay"
+ ],
+ function (RangeUtils, Env, Delay) {
+ return function (editor) {
+ var lastRng, lastPath = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- xhr.open('GET', url, true);
- xhr.responseType = 'blob';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the current element path has been changed or not.
+ *
+ * @private
+ * @return {Boolean} True if the element path is the same false if it's not.
+ */
+ function isSameElementPath(startElm) {
+ var i, currentPath;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- xhr.onload = function() {
- if (this.status == 200) {
- resolve(this.response);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ currentPath = editor.$(startElm).parentsUntil(editor.getBody()).add(startElm);
+ if (currentPath.length === lastPath.length) {
+ for (i = currentPath.length; i >= 0; i--) {
+ if (currentPath[i] !== lastPath[i]) {
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- xhr.send();
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (i === -1) {
+ lastPath = currentPath;
+ return true;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function parseDataUri(uri) {
- var type, matches;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ lastPath = currentPath;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- uri = decodeURIComponent(uri).split(',');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- matches = /data:([^;]+)/.exec(uri[0]);
- if (matches) {
- type = matches[1];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Gecko doesn't support the "selectionchange" event
+ if (!('onselectionchange' in editor.getDoc())) {
+ editor.on('NodeChange Click MouseUp KeyUp Focus', function (e) {
+ var nativeRng, fakeRng;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- type: type,
- data: uri[1]
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Since DOM Ranges mutate on modification
+ // of the DOM we need to clone it's contents
+ nativeRng = editor.selection.getRng();
+ fakeRng = {
+ startContainer: nativeRng.startContainer,
+ startOffset: nativeRng.startOffset,
+ endContainer: nativeRng.endContainer,
+ endOffset: nativeRng.endOffset
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function dataUriToBlob(uri) {
- return new Promise(function(resolve) {
- var str, arr, i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Always treat nodechange as a selectionchange since applying
+ // formatting to the current range wouldn't update the range but it's parent
+ if (e.type == 'nodechange' || !RangeUtils.compareRanges(fakeRng, lastRng)) {
+ editor.fire('SelectionChange');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- uri = parseDataUri(uri);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ lastRng = fakeRng;
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Might throw error if data isn't proper base64
- try {
- str = atob(uri.data);
- } catch (e) {
- resolve(new Blob([]));
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // IE has a bug where it fires a selectionchange on right click that has a range at the start of the body
+ // When the contextmenu event fires the selection is located at the right location
+ editor.on('contextmenu', function () {
+ editor.fire('SelectionChange');
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- arr = new Uint8Array(str.length);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Selection change is delayed ~200ms on IE when you click inside the current range
+ editor.on('SelectionChange', function () {
+ var startElm = editor.selection.getStart(true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0; i < arr.length; i++) {
- arr[i] = str.charCodeAt(i);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // IE 8 will fire a selectionchange event with an incorrect selection
+ // when focusing out of table cells. Click inside cell -> toolbar = Invalid SelectionChange event
+ if (!Env.range && editor.selection.isCollapsed()) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- resolve(new Blob([arr], {type: uri.type}));
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isSameElementPath(startElm) && editor.dom.isChildOf(startElm, editor.getBody())) {
+ editor.nodeChanged({ selectionChange: true });
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function uriToBlob(url) {
- if (url.indexOf('blob:') === 0) {
- return blobUriToBlob(url);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Fire an extra nodeChange on mouseup for compatibility reasons
+ editor.on('MouseUp', function (e) {
+ if (!e.isDefaultPrevented()) {
+ // Delay nodeChanged call for WebKit edge case issue where the range
+ // isn't updated until after you click outside a selected image
+ if (editor.selection.getNode().nodeName == 'IMG') {
+ Delay.setEditorTimeout(editor, function () {
+ editor.nodeChanged();
+ });
+ } else {
+ editor.nodeChanged();
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (url.indexOf('data:') === 0) {
- return dataUriToBlob(url);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Dispatches out a onNodeChange event to all observers. This method should be called when you
+ * need to update the UI states or element path etc.
+ *
+ * @method nodeChanged
+ * @param {Object} args Optional args to pass to NodeChange event handlers.
+ */
+ this.nodeChanged = function (args) {
+ var selection = editor.selection, node, parents, root;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Fix for bug #1896577 it seems that this can not be fired while the editor is loading
+ if (editor.initialized && selection && !editor.settings.disable_nodechange && !editor.readonly) {
+ // Get start node
+ root = editor.getBody();
+ node = selection.getStart(true) || root;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function blobToDataUri(blob) {
- return new Promise(function(resolve) {
- var reader = new FileReader();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Make sure the node is within the editor root or is the editor root
+ if (node.ownerDocument != editor.getDoc() || !editor.dom.isChildOf(node, root)) {
+ node = root;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- reader.onloadend = function() {
- resolve(reader.result);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get parents and add them to object
+ parents = [];
+ editor.dom.getParent(node, function (node) {
+ if (node === root) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- reader.readAsDataURL(blob);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parents.push(node);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- uriToBlob: uriToBlob,
- blobToDataUri: blobToDataUri,
- parseDataUri: parseDataUri
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args = args || {};
+ args.element = node;
+ args.parents = parents;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/file/ImageScanner.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.fire('NodeChange', args);
+ }
+ };
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * ImageScanner.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * FakeCaret.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Finds images with data uris or blob uris. If data uris are found it will convert them into blob uris.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * This module contains logic for rendering a fake visual caret.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @class tinymce.file.ImageScanner
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @class tinymce.caret.FakeCaret
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/file/ImageScanner", [
- "tinymce/util/Promise",
- "tinymce/util/Arr",
- "tinymce/util/Fun",
- "tinymce/file/Conversions",
- "tinymce/Env"
-], function(Promise, Arr, Fun, Conversions, Env) {
- var count = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.caret.FakeCaret',
+ [
+ 'tinymce.core.caret.CaretContainer',
+ 'tinymce.core.caret.CaretContainerRemove',
+ 'tinymce.core.caret.CaretPosition',
+ 'tinymce.core.dom.DomQuery',
+ 'tinymce.core.dom.NodeType',
+ 'tinymce.core.dom.RangeUtils',
+ 'tinymce.core.geom.ClientRect',
+ 'tinymce.core.util.Delay'
+ ],
+ function (CaretContainer, CaretContainerRemove, CaretPosition, DomQuery, NodeType, RangeUtils, ClientRect, Delay) {
+ var isContentEditableFalse = NodeType.isContentEditableFalse;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var uniqueId = function(prefix) {
- return (prefix || 'blobid') + (count++);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function (rootNode, isBlock) {
+ var cursorInterval, $lastVisualCaret, caretContainerNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function(uploadStatus, blobCache) {
- var cachedPromises = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getAbsoluteClientRect(node, before) {
+ var clientRect = ClientRect.collapse(node.getBoundingClientRect(), before),
+ docElm, scrollX, scrollY, margin, rootRect;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function findAll(elm, predicate) {
- var images, promises;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rootNode.tagName == 'BODY') {
+ docElm = rootNode.ownerDocument.documentElement;
+ scrollX = rootNode.scrollLeft || docElm.scrollLeft;
+ scrollY = rootNode.scrollTop || docElm.scrollTop;
+ } else {
+ rootRect = rootNode.getBoundingClientRect();
+ scrollX = rootNode.scrollLeft - rootRect.left;
+ scrollY = rootNode.scrollTop - rootRect.top;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function imageToBlobInfo(img, resolve) {
- var base64, blobInfo;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ clientRect.left += scrollX;
+ clientRect.right += scrollX;
+ clientRect.top += scrollY;
+ clientRect.bottom += scrollY;
+ clientRect.width = 1;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (img.src.indexOf('blob:') === 0) {
- blobInfo = blobCache.getByUri(img.src);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ margin = node.offsetWidth - node.clientWidth;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (blobInfo) {
- resolve({
- image: img,
- blobInfo: blobInfo
- });
- } else {
- Conversions.uriToBlob(img.src).then(function (blob) {
- Conversions.blobToDataUri(blob).then(function (dataUri) {
- base64 = Conversions.parseDataUri(dataUri).data;
- blobInfo = blobCache.create(uniqueId(), blob, base64);
- blobCache.add(blobInfo);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (margin > 0) {
+ if (before) {
+ margin *= -1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- resolve({
- image: img,
- blobInfo: blobInfo
- });
- });
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ clientRect.left += margin;
+ clientRect.right += margin;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return clientRect;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- base64 = Conversions.parseDataUri(img.src).data;
- blobInfo = blobCache.findFirst(function(cachedBlobInfo) {
- return cachedBlobInfo.base64() === base64;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function trimInlineCaretContainers() {
+ var contentEditableFalseNodes, node, sibling, i, data;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (blobInfo) {
- resolve({
- image: img,
- blobInfo: blobInfo
- });
- } else {
- Conversions.uriToBlob(img.src).then(function(blob) {
- blobInfo = blobCache.create(uniqueId(), blob, base64);
- blobCache.add(blobInfo);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ contentEditableFalseNodes = DomQuery('*[contentEditable=false]', rootNode);
+ for (i = 0; i < contentEditableFalseNodes.length; i++) {
+ node = contentEditableFalseNodes[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- resolve({
- image: img,
- blobInfo: blobInfo
- });
- });
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ sibling = node.previousSibling;
+ if (CaretContainer.endsWithCaretContainer(sibling)) {
+ data = sibling.data;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!predicate) {
- predicate = Fun.constant(true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (data.length == 1) {
+ sibling.parentNode.removeChild(sibling);
+ } else {
+ sibling.deleteData(data.length - 1, 1);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- images = Arr.filter(elm.getElementsByTagName('img'), function(img) {
- var src = img.src;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ sibling = node.nextSibling;
+ if (CaretContainer.startsWithCaretContainer(sibling)) {
+ data = sibling.data;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!Env.fileApi) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (data.length == 1) {
+ sibling.parentNode.removeChild(sibling);
+ } else {
+ sibling.deleteData(0, 1);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (img.hasAttribute('data-mce-bogus')) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (img.hasAttribute('data-mce-placeholder')) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function show(before, node) {
+ var clientRect, rng;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!src || src == Env.transparentSrc) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ hide();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (src.indexOf('blob:') === 0) {
- return !uploadStatus.isUploaded(src);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isBlock(node)) {
+ caretContainerNode = CaretContainer.insertBlock('p', node, before);
+ clientRect = getAbsoluteClientRect(node, before);
+ DomQuery(caretContainerNode).css('top', clientRect.top);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (src.indexOf('data:') === 0) {
- return predicate(img);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $lastVisualCaret = DomQuery('<div class="mce-visual-caret" data-mce-bogus="all"></div>').css(clientRect).appendTo(rootNode);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (before) {
+ $lastVisualCaret.addClass('mce-visual-caret-before');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- promises = Arr.map(images, function(img) {
- var newPromise;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ startBlink();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (cachedPromises[img.src]) {
- // Since the cached promise will return the cached image
- // We need to wrap it and resolve with the actual image
- return new Promise(function(resolve) {
- cachedPromises[img.src].then(function(imageInfo) {
- resolve({
- image: img,
- blobInfo: imageInfo.blobInfo
- });
- });
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng = node.ownerDocument.createRange();
+ rng.setStart(caretContainerNode, 0);
+ rng.setEnd(caretContainerNode, 0);
+ } else {
+ caretContainerNode = CaretContainer.insertInline(node, before);
+ rng = node.ownerDocument.createRange();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- newPromise = new Promise(function(resolve) {
- imageToBlobInfo(img, resolve);
- }).then(function(result) {
- delete cachedPromises[result.image.src];
- return result;
- })['catch'](function(error) {
- delete cachedPromises[img.src];
- return error;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isContentEditableFalse(caretContainerNode.nextSibling)) {
+ rng.setStart(caretContainerNode, 0);
+ rng.setEnd(caretContainerNode, 0);
+ } else {
+ rng.setStart(caretContainerNode, 1);
+ rng.setEnd(caretContainerNode, 1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- cachedPromises[img.src] = newPromise;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return rng;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return newPromise;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return rng;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Promise.all(promises);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hide() {
+ trimInlineCaretContainers();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- findAll: findAll
- };
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (caretContainerNode) {
+ CaretContainerRemove.remove(caretContainerNode);
+ caretContainerNode = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/file/BlobCache.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ($lastVisualCaret) {
+ $lastVisualCaret.remove();
+ $lastVisualCaret = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ clearInterval(cursorInterval);
+ }
+
+ function startBlink() {
+ cursorInterval = Delay.setInterval(function () {
+ DomQuery('div.mce-visual-caret', rootNode).toggleClass('mce-visual-caret-hidden');
+ }, 500);
+ }
+
+ function destroy() {
+ Delay.clearInterval(cursorInterval);
+ }
+
+ function getCss() {
+ return (
+ '.mce-visual-caret {' +
+ 'position: absolute;' +
+ 'background-color: black;' +
+ 'background-color: currentcolor;' +
+ '}' +
+ '.mce-visual-caret-hidden {' +
+ 'display: none;' +
+ '}' +
+ '*[data-mce-caret] {' +
+ 'position: absolute;' +
+ 'left: -1000px;' +
+ 'right: auto;' +
+ 'top: 0;' +
+ 'margin: 0;' +
+ 'padding: 0;' +
+ '}'
+ );
+ }
+
+ return {
+ show: show,
+ hide: hide,
+ getCss: getCss,
+ destroy: destroy
+ };
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * BlobCache.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Dimensions.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Hold blob info objects where a blob has extra internal information.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * This module measures nodes and returns client rects. The client rects has an
+ * extra node property.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @class tinymce.file.BlobCache
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @class tinymce.dom.Dimensions
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/file/BlobCache", [
- "tinymce/util/Arr",
- "tinymce/util/Fun"
-], function(Arr, Fun) {
- return function() {
- var cache = [], constant = Fun.constant;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.Dimensions',
+ [
+ "tinymce.core.util.Arr",
+ "tinymce.core.dom.NodeType",
+ "tinymce.core.geom.ClientRect"
+ ],
+ function (Arr, NodeType, ClientRect) {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function create(id, blob, base64, filename) {
- return {
- id: constant(id),
- filename: constant(filename || id),
- blob: constant(blob),
- base64: constant(base64),
- blobUri: constant(URL.createObjectURL(blob))
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getClientRects(node) {
+ function toArrayWithNode(clientRects) {
+ return Arr.map(clientRects, function (clientRect) {
+ clientRect = ClientRect.clone(clientRect);
+ clientRect.node = node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function add(blobInfo) {
- if (!get(blobInfo.id())) {
- cache.push(blobInfo);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return clientRect;
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function get(id) {
- return findFirst(function(cachedBlobInfo) {
- return cachedBlobInfo.id() === id;
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (Arr.isArray(node)) {
+ return Arr.reduce(node, function (result, node) {
+ return result.concat(getClientRects(node));
+ }, []);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function findFirst(predicate) {
- return Arr.filter(cache, predicate)[0];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (NodeType.isElement(node)) {
+ return toArrayWithNode(node.getClientRects());
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getByUri(blobUri) {
- return findFirst(function(blobInfo) {
- return blobInfo.blobUri() == blobUri;
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (NodeType.isText(node)) {
+ var rng = node.ownerDocument.createRange();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function removeByUri(blobUri) {
- cache = Arr.filter(cache, function(blobInfo) {
- if (blobInfo.blobUri() === blobUri) {
- URL.revokeObjectURL(blobInfo.blobUri());
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng.setStart(node, 0);
+ rng.setEnd(node, node.data.length);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return toArrayWithNode(rng.getClientRects());
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function destroy() {
- Arr.each(cache, function(cachedBlobInfo) {
- URL.revokeObjectURL(cachedBlobInfo.blobUri());
- });
-
- cache = [];
- }
-
- return {
- create: create,
- add: add,
- get: get,
- getByUri: getByUri,
- findFirst: findFirst,
- removeByUri: removeByUri,
- destroy: destroy
- };
- };
-});
-
-// Included from: js/tinymce/classes/file/UploadStatus.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ /**
+ * Returns the client rects for a specific node.
+ *
+ * @method getClientRects
+ * @param {Array/DOMNode} node Node or array of nodes to get client rects on.
+ * @param {Array} Array of client rects with a extra node property.
+ */
+ getClientRects: getClientRects
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * UploadStatus.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * LineWalker.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Holds the current status of a blob uri, if it's pending or uploaded and what the result urls was.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * This module lets you walk the document line by line
+ * returing nodes and client rects for each line.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @class tinymce.file.UploadStatus
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @class tinymce.caret.LineWalker
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/file/UploadStatus", [
-], function() {
- return function() {
- var PENDING = 1, UPLOADED = 2;
- var blobUriStatuses = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.caret.LineWalker',
+ [
+ "tinymce.core.util.Fun",
+ "tinymce.core.util.Arr",
+ "tinymce.core.dom.Dimensions",
+ "tinymce.core.caret.CaretCandidate",
+ "tinymce.core.caret.CaretUtils",
+ "tinymce.core.caret.CaretWalker",
+ "tinymce.core.caret.CaretPosition",
+ "tinymce.core.geom.ClientRect"
+ ],
+ function (Fun, Arr, Dimensions, CaretCandidate, CaretUtils, CaretWalker, CaretPosition, ClientRect) {
+ var curry = Fun.curry;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function createStatus(status, resultUri) {
- return {
- status: status,
- resultUri: resultUri
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function findUntil(direction, rootNode, predicateFn, node) {
+ while ((node = CaretUtils.findNode(node, direction, CaretCandidate.isEditableCaretCandidate, rootNode))) {
+ if (predicateFn(node)) {
+ return;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hasBlobUri(blobUri) {
- return blobUri in blobUriStatuses;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function walkUntil(direction, isAboveFn, isBeflowFn, rootNode, predicateFn, caretPosition) {
+ var line = 0, node, result = [], targetClientRect;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getResultUri(blobUri) {
- var result = blobUriStatuses[blobUri];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function add(node) {
+ var i, clientRect, clientRects;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return result ? result.resultUri : null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ clientRects = Dimensions.getClientRects(node);
+ if (direction == -1) {
+ clientRects = clientRects.reverse();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isPending(blobUri) {
- return hasBlobUri(blobUri) ? blobUriStatuses[blobUri].status === PENDING : false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0; i < clientRects.length; i++) {
+ clientRect = clientRects[i];
+ if (isBeflowFn(clientRect, targetClientRect)) {
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isUploaded(blobUri) {
- return hasBlobUri(blobUri) ? blobUriStatuses[blobUri].status === UPLOADED : false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (result.length > 0 && isAboveFn(clientRect, Arr.last(result))) {
+ line++;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function markPending(blobUri) {
- blobUriStatuses[blobUri] = createStatus(PENDING, null);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ clientRect.line = line;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function markUploaded(blobUri, resultUri) {
- blobUriStatuses[blobUri] = createStatus(UPLOADED, resultUri);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (predicateFn(clientRect)) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function removeFailed(blobUri) {
- delete blobUriStatuses[blobUri];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ result.push(clientRect);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function destroy() {
- blobUriStatuses = {};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ targetClientRect = Arr.last(caretPosition.getClientRects());
+ if (!targetClientRect) {
+ return result;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- hasBlobUri: hasBlobUri,
- getResultUri: getResultUri,
- isPending: isPending,
- isUploaded: isUploaded,
- markPending: markPending,
- markUploaded: markUploaded,
- removeFailed: removeFailed,
- destroy: destroy
- };
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = caretPosition.getNode();
+ add(node);
+ findUntil(direction, rootNode, add, node);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ErrorReporter.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return result;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * ErrorReporter.js
- *
- * Released under LGPL License.
- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function aboveLineNumber(lineNumber, clientRect) {
+ return clientRect.line > lineNumber;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Various error reporting helper functions.
- *
- * @class tinymce.ErrorReporter
- * @private
- */
-define("tinymce/ErrorReporter", [
- "tinymce/AddOnManager"
-], function (AddOnManager) {
- var PluginManager = AddOnManager.PluginManager;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isLine(lineNumber, clientRect) {
+ return clientRect.line === lineNumber;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var resolvePluginName = function (targetUrl, suffix) {
- for (var name in PluginManager.urls) {
- var matchUrl = PluginManager.urls[name] + '/plugin' + suffix + '.js';
- if (matchUrl === targetUrl) {
- return name;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var upUntil = curry(walkUntil, -1, ClientRect.isAbove, ClientRect.isBelow);
+ var downUntil = curry(walkUntil, 1, ClientRect.isBelow, ClientRect.isAbove);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function positionsUntil(direction, rootNode, predicateFn, node) {
+ var caretWalker = new CaretWalker(rootNode), walkFn, isBelowFn, isAboveFn,
+ caretPosition, result = [], line = 0, clientRect, targetClientRect;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var pluginUrlToMessage = function (editor, url) {
- var plugin = resolvePluginName(url, editor.suffix);
- return plugin ?
- 'Failed to load plugin: ' + plugin + ' from url ' + url :
- 'Failed to load plugin url: ' + url;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getClientRect(caretPosition) {
+ if (direction == 1) {
+ return Arr.last(caretPosition.getClientRects());
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var displayNotification = function (editor, message) {
- editor.notificationManager.open({
- type: 'error',
- text: message
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Arr.last(caretPosition.getClientRects());
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var displayError = function (editor, message) {
- if (editor._skinLoaded) {
- displayNotification(editor, message);
- } else {
- editor.on('SkinLoaded', function () {
- displayNotification(editor, message);
- });
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (direction == 1) {
+ walkFn = caretWalker.next;
+ isBelowFn = ClientRect.isBelow;
+ isAboveFn = ClientRect.isAbove;
+ caretPosition = CaretPosition.after(node);
+ } else {
+ walkFn = caretWalker.prev;
+ isBelowFn = ClientRect.isAbove;
+ isAboveFn = ClientRect.isBelow;
+ caretPosition = CaretPosition.before(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var uploadError = function (editor, message) {
- displayError(editor, 'Failed to upload image: ' + message);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ targetClientRect = getClientRect(caretPosition);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var pluginLoadError = function (editor, url) {
- displayError(editor, pluginUrlToMessage(editor, url));
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ do {
+ if (!caretPosition.isVisible()) {
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- pluginLoadError: pluginLoadError,
- uploadError: uploadError
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ clientRect = getClientRect(caretPosition);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/EditorUpload.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isAboveFn(clientRect, targetClientRect)) {
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (result.length > 0 && isBelowFn(clientRect, Arr.last(result))) {
+ line++;
+ }
+
+ clientRect = ClientRect.clone(clientRect);
+ clientRect.position = caretPosition;
+ clientRect.line = line;
+
+ if (predicateFn(clientRect)) {
+ return result;
+ }
+
+ result.push(clientRect);
+ } while ((caretPosition = walkFn(caretPosition)));
+
+ return result;
+ }
+
+ return {
+ upUntil: upUntil,
+ downUntil: downUntil,
+
+ /**
+ * Find client rects with line and caret position until the predicate returns true.
+ *
+ * @method positionsUntil
+ * @param {Number} direction Direction forward/backward 1/-1.
+ * @param {DOMNode} rootNode Root node to walk within.
+ * @param {function} predicateFn Gets the client rect as it's input.
+ * @param {DOMNode} node Node to start walking from.
+ * @return {Array} Array of client rects with line and position properties.
+ */
+ positionsUntil: positionsUntil,
+
+ isAboveLine: curry(aboveLineNumber),
+ isLine: curry(isLine)
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * EditorUpload.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * LineUtils.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Handles image uploads, updates undo stack and patches over various internal functions.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Utility functions for working with lines.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @class tinymce.EditorUpload
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @class tinymce.caret.LineUtils
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/EditorUpload", [
- "tinymce/util/Arr",
- "tinymce/file/Uploader",
- "tinymce/file/ImageScanner",
- "tinymce/file/BlobCache",
- "tinymce/file/UploadStatus",
- "tinymce/ErrorReporter"
-], function(Arr, Uploader, ImageScanner, BlobCache, UploadStatus, ErrorReporter) {
- return function(editor) {
- var blobCache = new BlobCache(), uploader, imageScanner, settings = editor.settings;
- var uploadStatus = new UploadStatus();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.caret.LineUtils',
+ [
+ "tinymce.core.util.Fun",
+ "tinymce.core.util.Arr",
+ "tinymce.core.dom.NodeType",
+ "tinymce.core.dom.Dimensions",
+ "tinymce.core.geom.ClientRect",
+ "tinymce.core.caret.CaretUtils",
+ "tinymce.core.caret.CaretCandidate"
+ ],
+ function (Fun, Arr, NodeType, Dimensions, ClientRect, CaretUtils, CaretCandidate) {
+ var isContentEditableFalse = NodeType.isContentEditableFalse,
+ findNode = CaretUtils.findNode,
+ curry = Fun.curry;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function aliveGuard(callback) {
- return function(result) {
- if (editor.selection) {
- return callback(result);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function distanceToRectLeft(clientRect, clientX) {
+ return Math.abs(clientRect.left - clientX);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return [];
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function distanceToRectRight(clientRect, clientX) {
+ return Math.abs(clientRect.right - clientX);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function cacheInvalidator() {
- return '?' + (new Date()).getTime();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function findClosestClientRect(clientRects, clientX) {
+ function isInside(clientX, clientRect) {
+ return clientX >= clientRect.left && clientX <= clientRect.right;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Replaces strings without regexps to avoid FF regexp to big issue
- function replaceString(content, search, replace) {
- var index = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Arr.reduce(clientRects, function (oldClientRect, clientRect) {
+ var oldDistance, newDistance;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- do {
- index = content.indexOf(search, index);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ oldDistance = Math.min(distanceToRectLeft(oldClientRect, clientX), distanceToRectRight(oldClientRect, clientX));
+ newDistance = Math.min(distanceToRectLeft(clientRect, clientX), distanceToRectRight(clientRect, clientX));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (index !== -1) {
- content = content.substring(0, index) + replace + content.substr(index + search.length);
- index += replace.length - search.length + 1;
- }
- } while (index !== -1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isInside(clientX, clientRect)) {
+ return clientRect;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return content;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isInside(clientX, oldClientRect)) {
+ return oldClientRect;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function replaceImageUrl(content, targetUrl, replacementUrl) {
- content = replaceString(content, 'src="' + targetUrl + '"', 'src="' + replacementUrl + '"');
- content = replaceString(content, 'data-mce-src="' + targetUrl + '"', 'data-mce-src="' + replacementUrl + '"');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // cE=false has higher priority
+ if (newDistance == oldDistance && isContentEditableFalse(clientRect.node)) {
+ return clientRect;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return content;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (newDistance < oldDistance) {
+ return clientRect;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function replaceUrlInUndoStack(targetUrl, replacementUrl) {
- Arr.each(editor.undoManager.data, function(level) {
- if (level.type === 'fragmented') {
- level.fragments = Arr.map(level.fragments, function (fragment) {
- return replaceImageUrl(fragment, targetUrl, replacementUrl);
- });
- } else {
- level.content = replaceImageUrl(level.content, targetUrl, replacementUrl);
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return oldClientRect;
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function openNotification() {
- return editor.notificationManager.open({
- text: editor.translate('Image uploading...'),
- type: 'info',
- timeout: -1,
- progressBar: true
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function walkUntil(direction, rootNode, predicateFn, node) {
+ while ((node = findNode(node, direction, CaretCandidate.isEditableCaretCandidate, rootNode))) {
+ if (predicateFn(node)) {
+ return;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function replaceImageUri(image, resultUri) {
- blobCache.removeByUri(image.src);
- replaceUrlInUndoStack(image.src, resultUri);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function findLineNodeRects(rootNode, targetNodeRect) {
+ var clientRects = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.$(image).attr({
- src: settings.images_reuse_filename ? resultUri + cacheInvalidator() : resultUri,
- 'data-mce-src': editor.convertURL(resultUri, 'src')
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function collect(checkPosFn, node) {
+ var lineRects;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function uploadImages(callback) {
- if (!uploader) {
- uploader = new Uploader(uploadStatus, {
- url: settings.images_upload_url,
- basePath: settings.images_upload_base_path,
- credentials: settings.images_upload_credentials,
- handler: settings.images_upload_handler
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ lineRects = Arr.filter(Dimensions.getClientRects(node), function (clientRect) {
+ return !checkPosFn(clientRect, targetNodeRect);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return scanForImages().then(aliveGuard(function(imageInfos) {
- var blobInfos;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ clientRects = clientRects.concat(lineRects);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- blobInfos = Arr.map(imageInfos, function(imageInfo) {
- return imageInfo.blobInfo;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return lineRects.length === 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return uploader.upload(blobInfos, openNotification).then(aliveGuard(function(result) {
- result = Arr.map(result, function(uploadInfo, index) {
- var image = imageInfos[index].image;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ clientRects.push(targetNodeRect);
+ walkUntil(-1, rootNode, curry(collect, ClientRect.isAbove), targetNodeRect.node);
+ walkUntil(1, rootNode, curry(collect, ClientRect.isBelow), targetNodeRect.node);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (uploadInfo.status && editor.settings.images_replace_blob_uris !== false) {
- replaceImageUri(image, uploadInfo.url);
- } else if (uploadInfo.error) {
- ErrorReporter.uploadError(editor, uploadInfo.error);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return clientRects;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- element: image,
- status: uploadInfo.status
- };
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getContentEditableFalseChildren(rootNode) {
+ return Arr.filter(Arr.toArray(rootNode.getElementsByTagName('*')), isContentEditableFalse);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (callback) {
- callback(result);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function caretInfo(clientRect, clientX) {
+ return {
+ node: clientRect.node,
+ before: distanceToRectLeft(clientRect, clientX) < distanceToRectRight(clientRect, clientX)
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return result;
- }));
- }));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function closestCaret(rootNode, clientX, clientY) {
+ var contentEditableFalseNodeRects, closestNodeRect;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function uploadImagesAuto(callback) {
- if (settings.automatic_uploads !== false) {
- return uploadImages(callback);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ contentEditableFalseNodeRects = Dimensions.getClientRects(getContentEditableFalseChildren(rootNode));
+ contentEditableFalseNodeRects = Arr.filter(contentEditableFalseNodeRects, function (clientRect) {
+ return clientY >= clientRect.top && clientY <= clientRect.bottom;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isValidDataUriImage(imgElm) {
- return settings.images_dataimg_filter ? settings.images_dataimg_filter(imgElm) : true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ closestNodeRect = findClosestClientRect(contentEditableFalseNodeRects, clientX);
+ if (closestNodeRect) {
+ closestNodeRect = findClosestClientRect(findLineNodeRects(rootNode, closestNodeRect), clientX);
+ if (closestNodeRect && isContentEditableFalse(closestNodeRect.node)) {
+ return caretInfo(closestNodeRect, clientX);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function scanForImages() {
- if (!imageScanner) {
- imageScanner = new ImageScanner(uploadStatus, blobCache);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return imageScanner.findAll(editor.getBody(), isValidDataUriImage).then(aliveGuard(function(result) {
- Arr.each(result, function(resultItem) {
- replaceUrlInUndoStack(resultItem.image.src, resultItem.blobInfo.blobUri());
- resultItem.image.src = resultItem.blobInfo.blobUri();
- resultItem.image.removeAttribute('data-mce-src');
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ findClosestClientRect: findClosestClientRect,
+ findLineNodeRects: findLineNodeRects,
+ closestCaret: closestCaret
+ };
+ }
+);
+/**
+ * MousePosition.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return result;
- }));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * This module calculates an absolute coordinate inside the editor body for both local and global mouse events.
+ *
+ * @private
+ * @class tinymce.dom.MousePosition
+ */
+define(
+ 'tinymce.core.dom.MousePosition',
+ [
+ ],
+ function () {
+ var getAbsolutePosition = function (elm) {
+ var doc, docElem, win, clientRect;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function destroy() {
- blobCache.destroy();
- uploadStatus.destroy();
- imageScanner = uploader = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ clientRect = elm.getBoundingClientRect();
+ doc = elm.ownerDocument;
+ docElem = doc.documentElement;
+ win = doc.defaultView;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function replaceBlobUris(content) {
- return content.replace(/src="(blob:[^"]+)"/g, function(match, blobUri) {
- var resultUri = uploadStatus.getResultUri(blobUri);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ top: clientRect.top + win.pageYOffset - docElem.clientTop,
+ left: clientRect.left + win.pageXOffset - docElem.clientLeft
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (resultUri) {
- return 'src="' + resultUri + '"';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getBodyPosition = function (editor) {
+ return editor.inline ? getAbsolutePosition(editor.getBody()) : { left: 0, top: 0 };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var blobInfo = blobCache.getByUri(blobUri);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getScrollPosition = function (editor) {
+ var body = editor.getBody();
+ return editor.inline ? { left: body.scrollLeft, top: body.scrollTop } : { left: 0, top: 0 };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!blobInfo) {
- blobInfo = Arr.reduce(editor.editorManager.editors, function(result, editor) {
- return result || editor.editorUpload.blobCache.getByUri(blobUri);
- }, null);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getBodyScroll = function (editor) {
+ var body = editor.getBody(), docElm = editor.getDoc().documentElement;
+ var inlineScroll = { left: body.scrollLeft, top: body.scrollTop };
+ var iframeScroll = { left: body.scrollLeft || docElm.scrollLeft, top: body.scrollTop || docElm.scrollTop };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (blobInfo) {
- return 'src="data:' + blobInfo.blob().type + ';base64,' + blobInfo.base64() + '"';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return editor.inline ? inlineScroll : iframeScroll;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return match;
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getMousePosition = function (editor, event) {
+ if (event.target.ownerDocument !== editor.getDoc()) {
+ var iframePosition = getAbsolutePosition(editor.getContentAreaContainer());
+ var scrollPosition = getBodyScroll(editor);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('setContent', function() {
- if (editor.settings.automatic_uploads !== false) {
- uploadImagesAuto();
- } else {
- scanForImages();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ left: event.pageX - iframePosition.left + scrollPosition.left,
+ top: event.pageY - iframePosition.top + scrollPosition.top
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('RawSaveContent', function(e) {
- e.content = replaceBlobUris(e.content);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ left: event.pageX,
+ top: event.pageY
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('getContent', function(e) {
- if (e.source_view || e.format == 'raw') {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var calculatePosition = function (bodyPosition, scrollPosition, mousePosition) {
+ return {
+ pageX: (mousePosition.left - bodyPosition.left) + scrollPosition.left,
+ pageY: (mousePosition.top - bodyPosition.top) + scrollPosition.top
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- e.content = replaceBlobUris(e.content);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var calc = function (editor, event) {
+ return calculatePosition(getBodyPosition(editor), getScrollPosition(editor), getMousePosition(editor, event));
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('PostRender', function() {
- editor.parser.addNodeFilter('img', function(images) {
- Arr.each(images, function(img) {
- var src = img.attr('src');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ calc: calc
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (blobCache.getByUri(src)) {
- return;
- }
-
- var resultUri = uploadStatus.getResultUri(src);
- if (resultUri) {
- img.attr('src', resultUri);
- }
- });
- });
- });
-
- return {
- blobCache: blobCache,
- uploadImages: uploadImages,
- uploadImagesAuto: uploadImagesAuto,
- scanForImages: scanForImages,
- destroy: destroy
- };
- };
-});
-
-// Included from: js/tinymce/classes/caret/FakeCaret.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * FakeCaret.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * DragDropOverrides.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * This module contains logic for rendering a fake visual caret.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * This module contains logic overriding the drag/drop logic of the editor.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @class tinymce.caret.FakeCaret
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @class tinymce.DragDropOverrides
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/caret/FakeCaret", [
- "tinymce/caret/CaretContainer",
- "tinymce/caret/CaretPosition",
- "tinymce/dom/NodeType",
- "tinymce/dom/RangeUtils",
- "tinymce/dom/DomQuery",
- "tinymce/geom/ClientRect",
- "tinymce/util/Delay"
-], function(CaretContainer, CaretPosition, NodeType, RangeUtils, $, ClientRect, Delay) {
- var isContentEditableFalse = NodeType.isContentEditableFalse;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.DragDropOverrides',
+ [
+ "tinymce.core.dom.NodeType",
+ "tinymce.core.util.Arr",
+ "tinymce.core.util.Fun",
+ "tinymce.core.util.Delay",
+ "tinymce.core.dom.DOMUtils",
+ "tinymce.core.dom.MousePosition"
+ ],
+ function (
+ NodeType, Arr, Fun, Delay, DOMUtils, MousePosition
+ ) {
+ var isContentEditableFalse = NodeType.isContentEditableFalse,
+ isContentEditableTrue = NodeType.isContentEditableTrue;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function(rootNode, isBlock) {
- var cursorInterval, $lastVisualCaret, caretContainerNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isDraggable = function (rootElm, elm) {
+ return isContentEditableFalse(elm) && elm !== rootElm;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getAbsoluteClientRect(node, before) {
- var clientRect = ClientRect.collapse(node.getBoundingClientRect(), before),
- docElm, scrollX, scrollY, margin, rootRect;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isValidDropTarget = function (editor, targetElement, dragElement) {
+ if (targetElement === dragElement || editor.dom.isChildOf(targetElement, dragElement)) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rootNode.tagName == 'BODY') {
- docElm = rootNode.ownerDocument.documentElement;
- scrollX = rootNode.scrollLeft || docElm.scrollLeft;
- scrollY = rootNode.scrollTop || docElm.scrollTop;
- } else {
- rootRect = rootNode.getBoundingClientRect();
- scrollX = rootNode.scrollLeft - rootRect.left;
- scrollY = rootNode.scrollTop - rootRect.top;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isContentEditableFalse(targetElement)) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- clientRect.left += scrollX;
- clientRect.right += scrollX;
- clientRect.top += scrollY;
- clientRect.bottom += scrollY;
- clientRect.width = 1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- margin = node.offsetWidth - node.clientWidth;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var cloneElement = function (elm) {
+ var cloneElm = elm.cloneNode(true);
+ cloneElm.removeAttribute('data-mce-selected');
+ return cloneElm;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (margin > 0) {
- if (before) {
- margin *= -1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createGhost = function (editor, elm, width, height) {
+ var clonedElm = elm.cloneNode(true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- clientRect.left += margin;
- clientRect.right += margin;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.dom.setStyles(clonedElm, { width: width, height: height });
+ editor.dom.setAttrib(clonedElm, 'data-mce-selected', null);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return clientRect;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var ghostElm = editor.dom.create('div', {
+ 'class': 'mce-drag-container',
+ 'data-mce-bogus': 'all',
+ unselectable: 'on',
+ contenteditable: 'false'
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function trimInlineCaretContainers() {
- var contentEditableFalseNodes, node, sibling, i, data;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.dom.setStyles(ghostElm, {
+ position: 'absolute',
+ opacity: 0.5,
+ overflow: 'hidden',
+ border: 0,
+ padding: 0,
+ margin: 0,
+ width: width,
+ height: height
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- contentEditableFalseNodes = $('*[contentEditable=false]', rootNode);
- for (i = 0; i < contentEditableFalseNodes.length; i++) {
- node = contentEditableFalseNodes[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.dom.setStyles(clonedElm, {
+ margin: 0,
+ boxSizing: 'border-box'
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- sibling = node.previousSibling;
- if (CaretContainer.endsWithCaretContainer(sibling)) {
- data = sibling.data;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ghostElm.appendChild(clonedElm);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (data.length == 1) {
- sibling.parentNode.removeChild(sibling);
- } else {
- sibling.deleteData(data.length - 1, 1);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return ghostElm;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- sibling = node.nextSibling;
- if (CaretContainer.startsWithCaretContainer(sibling)) {
- data = sibling.data;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var appendGhostToBody = function (ghostElm, bodyElm) {
+ if (ghostElm.parentNode !== bodyElm) {
+ bodyElm.appendChild(ghostElm);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (data.length == 1) {
- sibling.parentNode.removeChild(sibling);
- } else {
- sibling.deleteData(0, 1);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var moveGhost = function (ghostElm, position, width, height, maxX, maxY) {
+ var overflowX = 0, overflowY = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ghostElm.style.left = position.pageX + 'px';
+ ghostElm.style.top = position.pageY + 'px';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function show(before, node) {
- var clientRect, rng;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (position.pageX + width > maxX) {
+ overflowX = (position.pageX + width) - maxX;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- hide();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (position.pageY + height > maxY) {
+ overflowY = (position.pageY + height) - maxY;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isBlock(node)) {
- caretContainerNode = CaretContainer.insertBlock('p', node, before);
- clientRect = getAbsoluteClientRect(node, before);
- $(caretContainerNode).css('top', clientRect.top);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ghostElm.style.width = (width - overflowX) + 'px';
+ ghostElm.style.height = (height - overflowY) + 'px';
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $lastVisualCaret = $('<div class="mce-visual-caret" data-mce-bogus="all"></div>').css(clientRect).appendTo(rootNode);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var removeElement = function (elm) {
+ if (elm && elm.parentNode) {
+ elm.parentNode.removeChild(elm);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (before) {
- $lastVisualCaret.addClass('mce-visual-caret-before');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isLeftMouseButtonPressed = function (e) {
+ return e.button === 0;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- startBlink();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var hasDraggableElement = function (state) {
+ return state.element;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng = node.ownerDocument.createRange();
- rng.setStart(caretContainerNode, 0);
- rng.setEnd(caretContainerNode, 0);
- } else {
- caretContainerNode = CaretContainer.insertInline(node, before);
- rng = node.ownerDocument.createRange();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var applyRelPos = function (state, position) {
+ return {
+ pageX: position.pageX - state.relX,
+ pageY: position.pageY + 5
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isContentEditableFalse(caretContainerNode.nextSibling)) {
- rng.setStart(caretContainerNode, 0);
- rng.setEnd(caretContainerNode, 0);
- } else {
- rng.setStart(caretContainerNode, 1);
- rng.setEnd(caretContainerNode, 1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var start = function (state, editor) {
+ return function (e) {
+ if (isLeftMouseButtonPressed(e)) {
+ var ceElm = Arr.find(editor.dom.getParents(e.target), Fun.or(isContentEditableFalse, isContentEditableTrue));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return rng;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isDraggable(editor.getBody(), ceElm)) {
+ var elmPos = editor.dom.getPos(ceElm);
+ var bodyElm = editor.getBody();
+ var docElm = editor.getDoc().documentElement;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return rng;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ state.element = ceElm;
+ state.screenX = e.screenX;
+ state.screenY = e.screenY;
+ state.maxX = (editor.inline ? bodyElm.scrollWidth : docElm.offsetWidth) - 2;
+ state.maxY = (editor.inline ? bodyElm.scrollHeight : docElm.offsetHeight) - 2;
+ state.relX = e.pageX - elmPos.x;
+ state.relY = e.pageY - elmPos.y;
+ state.width = ceElm.offsetWidth;
+ state.height = ceElm.offsetHeight;
+ state.ghost = createGhost(editor, ceElm, state.width, state.height);
+ }
+ }
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hide() {
- trimInlineCaretContainers();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var move = function (state, editor) {
+ // Reduces laggy drag behavior on Gecko
+ var throttledPlaceCaretAt = Delay.throttle(function (clientX, clientY) {
+ editor._selectionOverrides.hideFakeCaret();
+ editor.selection.placeCaretAt(clientX, clientY);
+ }, 0);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (caretContainerNode) {
- CaretContainer.remove(caretContainerNode);
- caretContainerNode = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function (e) {
+ var movement = Math.max(Math.abs(e.screenX - state.screenX), Math.abs(e.screenY - state.screenY));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ($lastVisualCaret) {
- $lastVisualCaret.remove();
- $lastVisualCaret = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (hasDraggableElement(state) && !state.dragging && movement > 10) {
+ var args = editor.fire('dragstart', { target: state.element });
+ if (args.isDefaultPrevented()) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- clearInterval(cursorInterval);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ state.dragging = true;
+ editor.focus();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function startBlink() {
- cursorInterval = Delay.setInterval(function() {
- $('div.mce-visual-caret', rootNode).toggleClass('mce-visual-caret-hidden');
- }, 500);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (state.dragging) {
+ var targetPos = applyRelPos(state, MousePosition.calc(editor, e));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function destroy() {
- Delay.clearInterval(cursorInterval);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ appendGhostToBody(state.ghost, editor.getBody());
+ moveGhost(state.ghost, targetPos, state.width, state.height, state.maxX, state.maxY);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getCss() {
- return (
- '.mce-visual-caret {' +
- 'position: absolute;' +
- 'background-color: black;' +
- 'background-color: currentcolor;' +
- '}' +
- '.mce-visual-caret-hidden {' +
- 'display: none;' +
- '}' +
- '*[data-mce-caret] {' +
- 'position: absolute;' +
- 'left: -1000px;' +
- 'right: auto;' +
- 'top: 0;' +
- 'margin: 0;' +
- 'padding: 0;' +
- '}'
- );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ throttledPlaceCaretAt(e.clientX, e.clientY);
+ }
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- show: show,
- hide: hide,
- getCss: getCss,
- destroy: destroy
- };
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Returns the raw element instead of the fake cE=false element
+ var getRawTarget = function (selection) {
+ var rng = selection.getSel().getRangeAt(0);
+ var startContainer = rng.startContainer;
+ return startContainer.nodeType === 3 ? startContainer.parentNode : startContainer;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/dom/Dimensions.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var drop = function (state, editor) {
+ return function (e) {
+ if (state.dragging) {
+ if (isValidDropTarget(editor, getRawTarget(editor.selection), state.element)) {
+ var targetClone = cloneElement(state.element);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Dimensions.js
- *
- * Released under LGPL License.
- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var args = editor.fire('drop', {
+ targetClone: targetClone,
+ clientX: e.clientX,
+ clientY: e.clientY
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * This module measures nodes and returns client rects. The client rects has an
- * extra node property.
- *
- * @private
- * @class tinymce.dom.Dimensions
- */
-define("tinymce/dom/Dimensions", [
- "tinymce/util/Arr",
- "tinymce/dom/NodeType",
- "tinymce/geom/ClientRect"
-], function(Arr, NodeType, ClientRect) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!args.isDefaultPrevented()) {
+ targetClone = args.targetClone;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getClientRects(node) {
- function toArrayWithNode(clientRects) {
- return Arr.map(clientRects, function(clientRect) {
- clientRect = ClientRect.clone(clientRect);
- clientRect.node = node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.undoManager.transact(function () {
+ removeElement(state.element);
+ editor.insertContent(editor.dom.getOuterHTML(targetClone));
+ editor._selectionOverrides.hideFakeCaret();
+ });
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return clientRect;
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ removeDragState(state);
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (Arr.isArray(node)) {
- return Arr.reduce(node, function(result, node) {
- return result.concat(getClientRects(node));
- }, []);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var stop = function (state, editor) {
+ return function () {
+ removeDragState(state);
+ if (state.dragging) {
+ editor.fire('dragend');
+ }
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (NodeType.isElement(node)) {
- return toArrayWithNode(node.getClientRects());
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var removeDragState = function (state) {
+ state.dragging = false;
+ state.element = null;
+ removeElement(state.ghost);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (NodeType.isText(node)) {
- var rng = node.ownerDocument.createRange();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var bindFakeDragEvents = function (editor) {
+ var state = {}, pageDom, dragStartHandler, dragHandler, dropHandler, dragEndHandler, rootDocument;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng.setStart(node, 0);
- rng.setEnd(node, node.data.length);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ pageDom = DOMUtils.DOM;
+ rootDocument = document;
+ dragStartHandler = start(state, editor);
+ dragHandler = move(state, editor);
+ dropHandler = drop(state, editor);
+ dragEndHandler = stop(state, editor);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return toArrayWithNode(rng.getClientRects());
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('mousedown', dragStartHandler);
+ editor.on('mousemove', dragHandler);
+ editor.on('mouseup', dropHandler);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- /**
- * Returns the client rects for a specific node.
- *
- * @method getClientRects
- * @param {Array/DOMNode} node Node or array of nodes to get client rects on.
- * @param {Array} Array of client rects with a extra node property.
- */
- getClientRects: getClientRects
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ pageDom.bind(rootDocument, 'mousemove', dragHandler);
+ pageDom.bind(rootDocument, 'mouseup', dragEndHandler);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/caret/LineWalker.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('remove', function () {
+ pageDom.unbind(rootDocument, 'mousemove', dragHandler);
+ pageDom.unbind(rootDocument, 'mouseup', dragEndHandler);
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var blockIeDrop = function (editor) {
+ editor.on('drop', function (e) {
+ // FF doesn't pass out clientX/clientY for drop since this is for IE we just use null instead
+ var realTarget = typeof e.clientX !== 'undefined' ? editor.getDoc().elementFromPoint(e.clientX, e.clientY) : null;
+
+ if (isContentEditableFalse(realTarget) || isContentEditableFalse(editor.dom.getContentEditableParent(realTarget))) {
+ e.preventDefault();
+ }
+ });
+ };
+
+ var init = function (editor) {
+ bindFakeDragEvents(editor);
+ blockIeDrop(editor);
+ };
+
+ return {
+ init: init
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * LineWalker.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * SelectionOverrides.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * This module lets you walk the document line by line
- * returing nodes and client rects for each line.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * This module contains logic overriding the selection with keyboard/mouse
+ * around contentEditable=false regions.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @example
+ * // Disable the default cE=false selection
+ * tinymce.activeEditor.on('ShowCaret BeforeObjectSelected', function(e) {
+ * e.preventDefault();
+ * });
+ *
</ins><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @class tinymce.caret.LineWalker
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @class tinymce.SelectionOverrides
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/caret/LineWalker", [
- "tinymce/util/Fun",
- "tinymce/util/Arr",
- "tinymce/dom/Dimensions",
- "tinymce/caret/CaretCandidate",
- "tinymce/caret/CaretUtils",
- "tinymce/caret/CaretWalker",
- "tinymce/caret/CaretPosition",
- "tinymce/geom/ClientRect"
-], function(Fun, Arr, Dimensions, CaretCandidate, CaretUtils, CaretWalker, CaretPosition, ClientRect) {
- var curry = Fun.curry;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.SelectionOverrides',
+ [
+ "tinymce.core.Env",
+ "tinymce.core.caret.CaretWalker",
+ "tinymce.core.caret.CaretPosition",
+ "tinymce.core.caret.CaretContainer",
+ "tinymce.core.caret.CaretContainerRemove",
+ "tinymce.core.caret.CaretUtils",
+ "tinymce.core.caret.FakeCaret",
+ "tinymce.core.caret.LineWalker",
+ "tinymce.core.caret.LineUtils",
+ "tinymce.core.dom.NodeType",
+ "tinymce.core.dom.RangeUtils",
+ "tinymce.core.geom.ClientRect",
+ "tinymce.core.util.VK",
+ "tinymce.core.util.Fun",
+ "tinymce.core.util.Arr",
+ "tinymce.core.util.Delay",
+ "tinymce.core.DragDropOverrides"
+ ],
+ function (
+ Env, CaretWalker, CaretPosition, CaretContainer, CaretContainerRemove, CaretUtils, FakeCaret, LineWalker,
+ LineUtils, NodeType, RangeUtils, ClientRect, VK, Fun, Arr, Delay, DragDropOverrides
+) {
+ var curry = Fun.curry,
+ isContentEditableTrue = NodeType.isContentEditableTrue,
+ isContentEditableFalse = NodeType.isContentEditableFalse,
+ isAfterContentEditableFalse = CaretUtils.isAfterContentEditableFalse,
+ isBeforeContentEditableFalse = CaretUtils.isBeforeContentEditableFalse,
+ getSelectedNode = RangeUtils.getSelectedNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function findUntil(direction, rootNode, predicateFn, node) {
- while ((node = CaretUtils.findNode(node, direction, CaretCandidate.isEditableCaretCandidate, rootNode))) {
- if (predicateFn(node)) {
- return;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getVisualCaretPosition(walkFn, caretPosition) {
+ while ((caretPosition = walkFn(caretPosition))) {
+ if (caretPosition.isVisible()) {
+ return caretPosition;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function walkUntil(direction, isAboveFn, isBeflowFn, rootNode, predicateFn, caretPosition) {
- var line = 0, node, result = [], targetClientRect;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return caretPosition;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function add(node) {
- var i, clientRect, clientRects;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function SelectionOverrides(editor) {
+ var rootNode = editor.getBody(), caretWalker = new CaretWalker(rootNode);
+ var getNextVisualCaretPosition = curry(getVisualCaretPosition, caretWalker.next);
+ var getPrevVisualCaretPosition = curry(getVisualCaretPosition, caretWalker.prev),
+ fakeCaret = new FakeCaret(editor.getBody(), isBlock),
+ realSelectionId = 'sel-' + editor.dom.uniqueId(),
+ selectedContentEditableNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- clientRects = Dimensions.getClientRects(node);
- if (direction == -1) {
- clientRects = clientRects.reverse();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isFakeSelectionElement(elm) {
+ return editor.dom.hasClass(elm, 'mce-offscreen-selection');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0; i < clientRects.length; i++) {
- clientRect = clientRects[i];
- if (isBeflowFn(clientRect, targetClientRect)) {
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getRealSelectionElement() {
+ var container = editor.dom.get(realSelectionId);
+ return container ? container.getElementsByTagName('*')[0] : container;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (result.length > 0 && isAboveFn(clientRect, Arr.last(result))) {
- line++;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isBlock(node) {
+ return editor.dom.isBlock(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- clientRect.line = line;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setRange(range) {
+ //console.log('setRange', range);
+ if (range) {
+ editor.selection.setRng(range);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (predicateFn(clientRect)) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getRange() {
+ return editor.selection.getRng();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- result.push(clientRect);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function scrollIntoView(node, alignToTop) {
+ editor.selection.scrollIntoView(node, alignToTop);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- targetClientRect = Arr.last(caretPosition.getClientRects());
- if (!targetClientRect) {
- return result;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function showCaret(direction, node, before) {
+ var e;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = caretPosition.getNode();
- add(node);
- findUntil(direction, rootNode, add, node);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ e = editor.fire('ShowCaret', {
+ target: node,
+ direction: direction,
+ before: before
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return result;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.isDefaultPrevented()) {
+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function aboveLineNumber(lineNumber, clientRect) {
- return clientRect.line > lineNumber;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ scrollIntoView(node, direction === -1);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isLine(lineNumber, clientRect) {
- return clientRect.line === lineNumber;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return fakeCaret.show(before, node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var upUntil = curry(walkUntil, -1, ClientRect.isAbove, ClientRect.isBelow);
- var downUntil = curry(walkUntil, 1, ClientRect.isBelow, ClientRect.isAbove);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function selectNode(node) {
+ var e;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function positionsUntil(direction, rootNode, predicateFn, node) {
- var caretWalker = new CaretWalker(rootNode), walkFn, isBelowFn, isAboveFn,
- caretPosition, result = [], line = 0, clientRect, targetClientRect;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ e = editor.fire('BeforeObjectSelected', { target: node });
+ if (e.isDefaultPrevented()) {
+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getClientRect(caretPosition) {
- if (direction == 1) {
- return Arr.last(caretPosition.getClientRects());
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return getNodeRange(node);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Arr.last(caretPosition.getClientRects());
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getNodeRange(node) {
+ var rng = node.ownerDocument.createRange();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (direction == 1) {
- walkFn = caretWalker.next;
- isBelowFn = ClientRect.isBelow;
- isAboveFn = ClientRect.isAbove;
- caretPosition = CaretPosition.after(node);
- } else {
- walkFn = caretWalker.prev;
- isBelowFn = ClientRect.isAbove;
- isAboveFn = ClientRect.isBelow;
- caretPosition = CaretPosition.before(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng.selectNode(node);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- targetClientRect = getClientRect(caretPosition);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return rng;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- do {
- if (!caretPosition.isVisible()) {
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isMoveInsideSameBlock(fromCaretPosition, toCaretPosition) {
+ var inSameBlock = CaretUtils.isInSameBlock(fromCaretPosition, toCaretPosition);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- clientRect = getClientRect(caretPosition);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handle bogus BR <p>abc|<br></p>
+ if (!inSameBlock && NodeType.isBr(fromCaretPosition.getNode())) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isAboveFn(clientRect, targetClientRect)) {
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return inSameBlock;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (result.length > 0 && isBelowFn(clientRect, Arr.last(result))) {
- line++;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getNormalizedRangeEndPoint(direction, range) {
+ range = CaretUtils.normalizeRange(direction, rootNode, range);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- clientRect = ClientRect.clone(clientRect);
- clientRect.position = caretPosition;
- clientRect.line = line;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (direction == -1) {
+ return CaretPosition.fromRangeStart(range);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (predicateFn(clientRect)) {
- return result;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return CaretPosition.fromRangeEnd(range);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- result.push(clientRect);
- } while ((caretPosition = walkFn(caretPosition)));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isRangeInCaretContainerBlock(range) {
+ return CaretContainer.isCaretContainerBlock(range.startContainer);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return result;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function moveToCeFalseHorizontally(direction, getNextPosFn, isBeforeContentEditableFalseFn, range) {
+ var node, caretPosition, peekCaretPosition, rangeIsInContainerBlock;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- upUntil: upUntil,
- downUntil: downUntil,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!range.collapsed) {
+ node = getSelectedNode(range);
+ if (isContentEditableFalse(node)) {
+ return showCaret(direction, node, direction == -1);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Find client rects with line and caret position until the predicate returns true.
- *
- * @method positionsUntil
- * @param {Number} direction Direction forward/backward 1/-1.
- * @param {DOMNode} rootNode Root node to walk within.
- * @param {function} predicateFn Gets the client rect as it's input.
- * @param {DOMNode} node Node to start walking from.
- * @return {Array} Array of client rects with line and position properties.
- */
- positionsUntil: positionsUntil,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rangeIsInContainerBlock = isRangeInCaretContainerBlock(range);
+ caretPosition = getNormalizedRangeEndPoint(direction, range);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- isAboveLine: curry(aboveLineNumber),
- isLine: curry(isLine)
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isBeforeContentEditableFalseFn(caretPosition)) {
+ return selectNode(caretPosition.getNode(direction == -1));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/caret/LineUtils.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ caretPosition = getNextPosFn(caretPosition);
+ if (!caretPosition) {
+ if (rangeIsInContainerBlock) {
+ return range;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * LineUtils.js
- *
- * Released under LGPL License.
- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Utility functions for working with lines.
- *
- * @private
- * @class tinymce.caret.LineUtils
- */
-define("tinymce/caret/LineUtils", [
- "tinymce/util/Fun",
- "tinymce/util/Arr",
- "tinymce/dom/NodeType",
- "tinymce/dom/Dimensions",
- "tinymce/geom/ClientRect",
- "tinymce/caret/CaretUtils",
- "tinymce/caret/CaretCandidate"
-], function(Fun, Arr, NodeType, Dimensions, ClientRect, CaretUtils, CaretCandidate) {
- var isContentEditableFalse = NodeType.isContentEditableFalse,
- findNode = CaretUtils.findNode,
- curry = Fun.curry;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isBeforeContentEditableFalseFn(caretPosition)) {
+ return showCaret(direction, caretPosition.getNode(direction == -1), direction == 1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function distanceToRectLeft(clientRect, clientX) {
- return Math.abs(clientRect.left - clientX);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Peek ahead for handling of ab|c<span cE=false> -> abc|<span cE=false>
+ peekCaretPosition = getNextPosFn(caretPosition);
+ if (isBeforeContentEditableFalseFn(peekCaretPosition)) {
+ if (isMoveInsideSameBlock(caretPosition, peekCaretPosition)) {
+ return showCaret(direction, peekCaretPosition.getNode(direction == -1), direction == 1);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function distanceToRectRight(clientRect, clientX) {
- return Math.abs(clientRect.right - clientX);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rangeIsInContainerBlock) {
+ return renderRangeCaret(caretPosition.toRange());
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function findClosestClientRect(clientRects, clientX) {
- function isInside(clientX, clientRect) {
- return clientX >= clientRect.left && clientX <= clientRect.right;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Arr.reduce(clientRects, function(oldClientRect, clientRect) {
- var oldDistance, newDistance;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function moveToCeFalseVertically(direction, walkerFn, range) {
+ var caretPosition, linePositions, nextLinePositions,
+ closestNextLineRect, caretClientRect, clientX,
+ dist1, dist2, contentEditableFalseNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- oldDistance = Math.min(distanceToRectLeft(oldClientRect, clientX), distanceToRectRight(oldClientRect, clientX));
- newDistance = Math.min(distanceToRectLeft(clientRect, clientX), distanceToRectRight(clientRect, clientX));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ contentEditableFalseNode = getSelectedNode(range);
+ caretPosition = getNormalizedRangeEndPoint(direction, range);
+ linePositions = walkerFn(rootNode, LineWalker.isAboveLine(1), caretPosition);
+ nextLinePositions = Arr.filter(linePositions, LineWalker.isLine(1));
+ caretClientRect = Arr.last(caretPosition.getClientRects());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isInside(clientX, clientRect)) {
- return clientRect;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isBeforeContentEditableFalse(caretPosition)) {
+ contentEditableFalseNode = caretPosition.getNode();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isInside(clientX, oldClientRect)) {
- return oldClientRect;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isAfterContentEditableFalse(caretPosition)) {
+ contentEditableFalseNode = caretPosition.getNode(true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // cE=false has higher priority
- if (newDistance == oldDistance && isContentEditableFalse(clientRect.node)) {
- return clientRect;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!caretClientRect) {
+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (newDistance < oldDistance) {
- return clientRect;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ clientX = caretClientRect.left;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return oldClientRect;
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ closestNextLineRect = LineUtils.findClosestClientRect(nextLinePositions, clientX);
+ if (closestNextLineRect) {
+ if (isContentEditableFalse(closestNextLineRect.node)) {
+ dist1 = Math.abs(clientX - closestNextLineRect.left);
+ dist2 = Math.abs(clientX - closestNextLineRect.right);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function walkUntil(direction, rootNode, predicateFn, node) {
- while ((node = findNode(node, direction, CaretCandidate.isEditableCaretCandidate, rootNode))) {
- if (predicateFn(node)) {
- return;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return showCaret(direction, closestNextLineRect.node, dist1 < dist2);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function findLineNodeRects(rootNode, targetNodeRect) {
- var clientRects = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (contentEditableFalseNode) {
+ var caretPositions = LineWalker.positionsUntil(direction, rootNode, LineWalker.isAboveLine(1), contentEditableFalseNode);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function collect(checkPosFn, node) {
- var lineRects;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ closestNextLineRect = LineUtils.findClosestClientRect(Arr.filter(caretPositions, LineWalker.isLine(1)), clientX);
+ if (closestNextLineRect) {
+ return renderRangeCaret(closestNextLineRect.position.toRange());
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- lineRects = Arr.filter(Dimensions.getClientRects(node), function(clientRect) {
- return !checkPosFn(clientRect, targetNodeRect);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ closestNextLineRect = Arr.last(Arr.filter(caretPositions, LineWalker.isLine(0)));
+ if (closestNextLineRect) {
+ return renderRangeCaret(closestNextLineRect.position.toRange());
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- clientRects = clientRects.concat(lineRects);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function exitPreBlock(direction, range) {
+ var pre, caretPos, newBlock;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return lineRects.length === 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function createTextBlock() {
+ var textBlock = editor.dom.create(editor.settings.forced_root_block);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- clientRects.push(targetNodeRect);
- walkUntil(-1, rootNode, curry(collect, ClientRect.isAbove), targetNodeRect.node);
- walkUntil(1, rootNode, curry(collect, ClientRect.isBelow), targetNodeRect.node);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!Env.ie || Env.ie >= 11) {
+ textBlock.innerHTML = '<br data-mce-bogus="1">';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return clientRects;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return textBlock;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getContentEditableFalseChildren(rootNode) {
- return Arr.filter(Arr.toArray(rootNode.getElementsByTagName('*')), isContentEditableFalse);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (range.collapsed && editor.settings.forced_root_block) {
+ pre = editor.dom.getParent(range.startContainer, 'PRE');
+ if (!pre) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function caretInfo(clientRect, clientX) {
- return {
- node: clientRect.node,
- before: distanceToRectLeft(clientRect, clientX) < distanceToRectRight(clientRect, clientX)
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (direction == 1) {
+ caretPos = getNextVisualCaretPosition(CaretPosition.fromRangeStart(range));
+ } else {
+ caretPos = getPrevVisualCaretPosition(CaretPosition.fromRangeStart(range));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function closestCaret(rootNode, clientX, clientY) {
- var contentEditableFalseNodeRects, closestNodeRect;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!caretPos) {
+ newBlock = createTextBlock();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- contentEditableFalseNodeRects = Dimensions.getClientRects(getContentEditableFalseChildren(rootNode));
- contentEditableFalseNodeRects = Arr.filter(contentEditableFalseNodeRects, function(clientRect) {
- return clientY >= clientRect.top && clientY <= clientRect.bottom;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (direction == 1) {
+ editor.$(pre).after(newBlock);
+ } else {
+ editor.$(pre).before(newBlock);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- closestNodeRect = findClosestClientRect(contentEditableFalseNodeRects, clientX);
- if (closestNodeRect) {
- closestNodeRect = findClosestClientRect(findLineNodeRects(rootNode, closestNodeRect), clientX);
- if (closestNodeRect && isContentEditableFalse(closestNodeRect.node)) {
- return caretInfo(closestNodeRect, clientX);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.selection.select(newBlock, true);
+ editor.selection.collapse();
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function moveH(direction, getNextPosFn, isBeforeContentEditableFalseFn, range) {
+ var newRange;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- findClosestClientRect: findClosestClientRect,
- findLineNodeRects: findLineNodeRects,
- closestCaret: closestCaret
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ newRange = moveToCeFalseHorizontally(direction, getNextPosFn, isBeforeContentEditableFalseFn, range);
+ if (newRange) {
+ return newRange;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/dom/MousePosition.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ newRange = exitPreBlock(direction, range);
+ if (newRange) {
+ return newRange;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * MousePosition.js
- *
- * Released under LGPL License.
- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * This module calculates an absolute coordinate inside the editor body for both local and global mouse events.
- *
- * @private
- * @class tinymce.dom.MousePosition
- */
-define("tinymce/dom/MousePosition", [
-], function() {
- var getAbsolutePosition = function (elm) {
- var doc, docElem, win, clientRect;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function moveV(direction, walkerFn, range) {
+ var newRange;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- clientRect = elm.getBoundingClientRect();
- doc = elm.ownerDocument;
- docElem = doc.documentElement;
- win = doc.defaultView;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ newRange = moveToCeFalseVertically(direction, walkerFn, range);
+ if (newRange) {
+ return newRange;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- top: clientRect.top + win.pageYOffset - docElem.clientTop,
- left: clientRect.left + win.pageXOffset - docElem.clientLeft
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ newRange = exitPreBlock(direction, range);
+ if (newRange) {
+ return newRange;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getBodyPosition = function (editor) {
- return editor.inline ? getAbsolutePosition(editor.getBody()) : {left: 0, top: 0};
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getScrollPosition = function (editor) {
- var body = editor.getBody();
- return editor.inline ? {left: body.scrollLeft, top: body.scrollTop} : {left: 0, top: 0};
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function showBlockCaretContainer(blockCaretContainer) {
+ if (blockCaretContainer.hasAttribute('data-mce-caret')) {
+ CaretContainer.showCaretContainerBlock(blockCaretContainer);
+ setRange(getRange()); // Removes control rect on IE
+ scrollIntoView(blockCaretContainer[0]);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getBodyScroll = function (editor) {
- var body = editor.getBody(), docElm = editor.getDoc().documentElement;
- var inlineScroll = {left: body.scrollLeft, top: body.scrollTop};
- var iframeScroll = {left: body.scrollLeft || docElm.scrollLeft, top: body.scrollTop || docElm.scrollTop};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function renderCaretAtRange(range) {
+ var caretPosition, ceRoot;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return editor.inline ? inlineScroll : iframeScroll;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ range = CaretUtils.normalizeRange(1, rootNode, range);
+ caretPosition = CaretPosition.fromRangeStart(range);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getMousePosition = function (editor, event) {
- if (event.target.ownerDocument !== editor.getDoc()) {
- var iframePosition = getAbsolutePosition(editor.getContentAreaContainer());
- var scrollPosition = getBodyScroll(editor);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isContentEditableFalse(caretPosition.getNode())) {
+ return showCaret(1, caretPosition.getNode(), !caretPosition.isAtEnd());
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- left: event.pageX - iframePosition.left + scrollPosition.left,
- top: event.pageY - iframePosition.top + scrollPosition.top
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isContentEditableFalse(caretPosition.getNode(true))) {
+ return showCaret(1, caretPosition.getNode(true), false);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- left: event.pageX,
- top: event.pageY
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // TODO: Should render caret before/after depending on where you click on the page forces after now
+ ceRoot = editor.dom.getParent(caretPosition.getNode(), Fun.or(isContentEditableFalse, isContentEditableTrue));
+ if (isContentEditableFalse(ceRoot)) {
+ return showCaret(1, ceRoot, false);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var calculatePosition = function (bodyPosition, scrollPosition, mousePosition) {
- return {
- pageX: (mousePosition.left - bodyPosition.left) + scrollPosition.left,
- pageY: (mousePosition.top - bodyPosition.top) + scrollPosition.top
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var calc = function (editor, event) {
- return calculatePosition(getBodyPosition(editor), getScrollPosition(editor), getMousePosition(editor, event));
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function renderRangeCaret(range) {
+ var caretRange;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- calc: calc
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!range || !range.collapsed) {
+ return range;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/DragDropOverrides.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ caretRange = renderCaretAtRange(range);
+ if (caretRange) {
+ return caretRange;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * DragDropOverrides.js
- *
- * Released under LGPL License.
- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return range;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * This module contains logic overriding the drag/drop logic of the editor.
- *
- * @private
- * @class tinymce.DragDropOverrides
- */
-define("tinymce/DragDropOverrides", [
- "tinymce/dom/NodeType",
- "tinymce/util/Arr",
- "tinymce/util/Fun",
- "tinymce/util/Delay",
- "tinymce/dom/DOMUtils",
- "tinymce/dom/MousePosition"
-], function(
- NodeType, Arr, Fun, Delay, DOMUtils, MousePosition
-) {
- var isContentEditableFalse = NodeType.isContentEditableFalse,
- isContentEditableTrue = NodeType.isContentEditableTrue;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function registerEvents() {
+ var right = curry(moveH, 1, getNextVisualCaretPosition, isBeforeContentEditableFalse);
+ var left = curry(moveH, -1, getPrevVisualCaretPosition, isAfterContentEditableFalse);
+ var up = curry(moveV, -1, LineWalker.upUntil);
+ var down = curry(moveV, 1, LineWalker.downUntil);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isDraggable = function (rootElm, elm) {
- return isContentEditableFalse(elm) && elm !== rootElm;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function override(evt, moveFn) {
+ if (evt.isDefaultPrevented() === false) {
+ var range = moveFn(getRange());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isValidDropTarget = function (editor, targetElement, dragElement) {
- if (targetElement === dragElement || editor.dom.isChildOf(targetElement, dragElement)) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (range) {
+ evt.preventDefault();
+ setRange(range);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isContentEditableFalse(targetElement)) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getContentEditableRoot(node) {
+ var root = editor.getBody();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (node && node != root) {
+ if (isContentEditableTrue(node) || isContentEditableFalse(node)) {
+ return node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var cloneElement = function (elm) {
- var cloneElm = elm.cloneNode(true);
- cloneElm.removeAttribute('data-mce-selected');
- return cloneElm;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var createGhost = function (editor, elm, width, height) {
- var clonedElm = elm.cloneNode(true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.dom.setStyles(clonedElm, {width: width, height: height});
- editor.dom.setAttrib(clonedElm, 'data-mce-selected', null);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isXYWithinRange(clientX, clientY, range) {
+ if (range.collapsed) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var ghostElm = editor.dom.create('div', {
- 'class': 'mce-drag-container',
- 'data-mce-bogus': 'all',
- unselectable: 'on',
- contenteditable: 'false'
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Arr.reduce(range.getClientRects(), function (state, rect) {
+ return state || ClientRect.containsXY(rect, clientX, clientY);
+ }, false);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.dom.setStyles(ghostElm, {
- position: 'absolute',
- opacity: 0.5,
- overflow: 'hidden',
- border: 0,
- padding: 0,
- margin: 0,
- width: width,
- height: height
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Some browsers (Chrome) lets you place the caret after a cE=false
+ // Make sure we render the caret container in this case
+ editor.on('mouseup', function () {
+ var range = getRange();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.dom.setStyles(clonedElm, {
- margin: 0,
- boxSizing: 'border-box'
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (range.collapsed) {
+ setRange(renderCaretAtRange(range));
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ghostElm.appendChild(clonedElm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('click', function (e) {
+ var contentEditableRoot;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return ghostElm;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ contentEditableRoot = getContentEditableRoot(e.target);
+ if (contentEditableRoot) {
+ // Prevent clicks on links in a cE=false element
+ if (isContentEditableFalse(contentEditableRoot)) {
+ e.preventDefault();
+ editor.focus();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var appendGhostToBody = function (ghostElm, bodyElm) {
- if (ghostElm.parentNode !== bodyElm) {
- bodyElm.appendChild(ghostElm);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Removes fake selection if a cE=true is clicked within a cE=false like the toc title
+ if (isContentEditableTrue(contentEditableRoot)) {
+ if (editor.dom.isChildOf(contentEditableRoot, editor.selection.getNode())) {
+ removeContentEditableSelection();
+ }
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var moveGhost = function (ghostElm, position, width, height, maxX, maxY) {
- var overflowX = 0, overflowY = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('blur NewBlock', function () {
+ removeContentEditableSelection();
+ hideFakeCaret();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ghostElm.style.left = position.pageX + 'px';
- ghostElm.style.top = position.pageY + 'px';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function handleTouchSelect(editor) {
+ var moved = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (position.pageX + width > maxX) {
- overflowX = (position.pageX + width) - maxX;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('touchstart', function () {
+ moved = false;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (position.pageY + height > maxY) {
- overflowY = (position.pageY + height) - maxY;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('touchmove', function () {
+ moved = true;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ghostElm.style.width = (width - overflowX) + 'px';
- ghostElm.style.height = (height - overflowY) + 'px';
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('touchend', function (e) {
+ var contentEditableRoot = getContentEditableRoot(e.target);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var removeElement = function (elm) {
- if (elm && elm.parentNode) {
- elm.parentNode.removeChild(elm);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isContentEditableFalse(contentEditableRoot)) {
+ if (!moved) {
+ e.preventDefault();
+ setContentEditableSelection(selectNode(contentEditableRoot));
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isLeftMouseButtonPressed = function (e) {
- return e.button === 0;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var hasNormalCaretPosition = function (elm) {
+ var caretWalker = new CaretWalker(elm);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var hasDraggableElement = function (state) {
- return state.element;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!elm.firstChild) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var applyRelPos = function (state, position) {
- return {
- pageX: position.pageX - state.relX,
- pageY: position.pageY + 5
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var startPos = CaretPosition.before(elm.firstChild);
+ var newPos = caretWalker.next(startPos);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var start = function (state, editor) {
- return function (e) {
- if (isLeftMouseButtonPressed(e)) {
- var ceElm = Arr.find(editor.dom.getParents(e.target), Fun.or(isContentEditableFalse, isContentEditableTrue));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return newPos && !isBeforeContentEditableFalse(newPos) && !isAfterContentEditableFalse(newPos);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isDraggable(editor.getBody(), ceElm)) {
- var elmPos = editor.dom.getPos(ceElm);
- var bodyElm = editor.getBody();
- var docElm = editor.getDoc().documentElement;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isInSameBlock = function (node1, node2) {
+ var block1 = editor.dom.getParent(node1, editor.dom.isBlock);
+ var block2 = editor.dom.getParent(node2, editor.dom.isBlock);
+ return block1 === block2;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- state.element = ceElm;
- state.screenX = e.screenX;
- state.screenY = e.screenY;
- state.maxX = (editor.inline ? bodyElm.scrollWidth : docElm.offsetWidth) - 2;
- state.maxY = (editor.inline ? bodyElm.scrollHeight : docElm.offsetHeight) - 2;
- state.relX = e.pageX - elmPos.x;
- state.relY = e.pageY - elmPos.y;
- state.width = ceElm.offsetWidth;
- state.height = ceElm.offsetHeight;
- state.ghost = createGhost(editor, ceElm, state.width, state.height);
- }
- }
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isContentKey = function (e) {
+ if (e.keyCode >= 112 && e.keyCode <= 123) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var move = function (state, editor) {
- // Reduces laggy drag behavior on Gecko
- var throttledPlaceCaretAt = Delay.throttle(function (clientX, clientY) {
- editor._selectionOverrides.hideFakeCaret();
- editor.selection.placeCaretAt(clientX, clientY);
- }, 0);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return function (e) {
- var movement = Math.max(Math.abs(e.screenX - state.screenX), Math.abs(e.screenY - state.screenY));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Checks if the target node is in a block and if that block has a caret position better than the
+ // suggested caretNode this is to prevent the caret from being sucked in towards a cE=false block if
+ // they are adjacent on the vertical axis
+ var hasBetterMouseTarget = function (targetNode, caretNode) {
+ var targetBlock = editor.dom.getParent(targetNode, editor.dom.isBlock);
+ var caretBlock = editor.dom.getParent(caretNode, editor.dom.isBlock);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (hasDraggableElement(state) && !state.dragging && movement > 10) {
- var args = editor.fire('dragstart', {target: state.element});
- if (args.isDefaultPrevented()) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return targetBlock && !isInSameBlock(targetBlock, caretBlock) && hasNormalCaretPosition(targetBlock);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- state.dragging = true;
- editor.focus();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ handleTouchSelect(editor);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (state.dragging) {
- var targetPos = applyRelPos(state, MousePosition.calc(editor, e));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('mousedown', function (e) {
+ var contentEditableRoot;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- appendGhostToBody(state.ghost, editor.getBody());
- moveGhost(state.ghost, targetPos, state.width, state.height, state.maxX, state.maxY);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ contentEditableRoot = getContentEditableRoot(e.target);
+ if (contentEditableRoot) {
+ if (isContentEditableFalse(contentEditableRoot)) {
+ e.preventDefault();
+ setContentEditableSelection(selectNode(contentEditableRoot));
+ } else {
+ if (!isXYWithinRange(e.clientX, e.clientY, editor.selection.getRng())) {
+ editor.selection.placeCaretAt(e.clientX, e.clientY);
+ }
+ }
+ } else {
+ // Remove needs to be called here since the mousedown might alter the selection without calling selection.setRng
+ // and therefore not fire the AfterSetSelectionRange event.
+ removeContentEditableSelection();
+ hideFakeCaret();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- throttledPlaceCaretAt(e.clientX, e.clientY);
- }
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var caretInfo = LineUtils.closestCaret(rootNode, e.clientX, e.clientY);
+ if (caretInfo) {
+ if (!hasBetterMouseTarget(e.target, caretInfo.node)) {
+ e.preventDefault();
+ editor.getBody().focus();
+ setRange(showCaret(1, caretInfo.node, caretInfo.before));
+ }
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Returns the raw element instead of the fake cE=false element
- var getRawTarget = function (selection) {
- var rng = selection.getSel().getRangeAt(0);
- var startContainer = rng.startContainer;
- return startContainer.nodeType === 3 ? startContainer.parentNode : startContainer;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('keydown', function (e) {
+ if (VK.modifierPressed(e)) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var drop = function (state, editor) {
- return function (e) {
- if (state.dragging) {
- if (isValidDropTarget(editor, getRawTarget(editor.selection), state.element)) {
- var targetClone = cloneElement(state.element);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ switch (e.keyCode) {
+ case VK.RIGHT:
+ override(e, right);
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var args = editor.fire('drop', {
- targetClone: targetClone,
- clientX: e.clientX,
- clientY: e.clientY
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case VK.DOWN:
+ override(e, down);
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!args.isDefaultPrevented()) {
- targetClone = args.targetClone;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case VK.LEFT:
+ override(e, left);
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.undoManager.transact(function() {
- removeElement(state.element);
- editor.insertContent(editor.dom.getOuterHTML(targetClone));
- editor._selectionOverrides.hideFakeCaret();
- });
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case VK.UP:
+ override(e, up);
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- removeDragState(state);
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ default:
+ if (isContentEditableFalse(editor.selection.getNode()) && isContentKey(e)) {
+ e.preventDefault();
+ }
+ break;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var stop = function (state, editor) {
- return function () {
- removeDragState(state);
- if (state.dragging) {
- editor.fire('dragend');
- }
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('getSelectionRange', function (e) {
+ var rng = e.range;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var removeDragState = function (state) {
- state.dragging = false;
- state.element = null;
- removeElement(state.ghost);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (selectedContentEditableNode) {
+ if (!selectedContentEditableNode.parentNode) {
+ selectedContentEditableNode = null;
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var bindFakeDragEvents = function (editor) {
- var state = {}, pageDom, dragStartHandler, dragHandler, dropHandler, dragEndHandler, rootDocument;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng = rng.cloneRange();
+ rng.selectNode(selectedContentEditableNode);
+ e.range = rng;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- pageDom = DOMUtils.DOM;
- rootDocument = document;
- dragStartHandler = start(state, editor);
- dragHandler = move(state, editor);
- dropHandler = drop(state, editor);
- dragEndHandler = stop(state, editor);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('setSelectionRange', function (e) {
+ var rng;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('mousedown', dragStartHandler);
- editor.on('mousemove', dragHandler);
- editor.on('mouseup', dropHandler);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng = setContentEditableSelection(e.range);
+ if (rng) {
+ e.range = rng;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- pageDom.bind(rootDocument, 'mousemove', dragHandler);
- pageDom.bind(rootDocument, 'mouseup', dragEndHandler);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('AfterSetSelectionRange', function (e) {
+ var rng = e.range;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('remove', function () {
- pageDom.unbind(rootDocument, 'mousemove', dragHandler);
- pageDom.unbind(rootDocument, 'mouseup', dragEndHandler);
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isRangeInCaretContainer(rng)) {
+ hideFakeCaret();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var blockIeDrop = function (editor) {
- editor.on('drop', function(e) {
- // FF doesn't pass out clientX/clientY for drop since this is for IE we just use null instead
- var realTarget = typeof e.clientX !== 'undefined' ? editor.getDoc().elementFromPoint(e.clientX, e.clientY) : null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isFakeSelectionElement(rng.startContainer.parentNode)) {
+ removeContentEditableSelection();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isContentEditableFalse(realTarget) || isContentEditableFalse(editor.dom.getContentEditableParent(realTarget))) {
- e.preventDefault();
- }
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('focus', function () {
+ // Make sure we have a proper fake caret on focus
+ Delay.setEditorTimeout(editor, function () {
+ editor.selection.setRng(renderRangeCaret(editor.selection.getRng()));
+ }, 0);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var init = function (editor) {
- bindFakeDragEvents(editor);
- blockIeDrop(editor);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('copy', function (e) {
+ var clipboardData = e.clipboardData;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- init: init
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Make sure we get proper html/text for the fake cE=false selection
+ // Doesn't work at all on Edge since it doesn't have proper clipboardData support
+ if (!e.isDefaultPrevented() && e.clipboardData && !Env.ie) {
+ var realSelectionElement = getRealSelectionElement();
+ if (realSelectionElement) {
+ e.preventDefault();
+ clipboardData.clearData();
+ clipboardData.setData('text/html', realSelectionElement.outerHTML);
+ clipboardData.setData('text/plain', realSelectionElement.outerText);
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/SelectionOverrides.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DragDropOverrides.init(editor);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function addCss() {
+ var styles = editor.contentStyles, rootClass = '.mce-content-body';
+
+ styles.push(fakeCaret.getCss());
+ styles.push(
+ rootClass + ' .mce-offscreen-selection {' +
+ 'position: absolute;' +
+ 'left: -9999999999px;' +
+ 'max-width: 1000000px;' +
+ '}' +
+ rootClass + ' *[contentEditable=false] {' +
+ 'cursor: default;' +
+ '}' +
+ rootClass + ' *[contentEditable=true] {' +
+ 'cursor: text;' +
+ '}'
+ );
+ }
+
+ function isWithinCaretContainer(node) {
+ return (
+ CaretContainer.isCaretContainer(node) ||
+ CaretContainer.startsWithCaretContainer(node) ||
+ CaretContainer.endsWithCaretContainer(node)
+ );
+ }
+
+ function isRangeInCaretContainer(rng) {
+ return isWithinCaretContainer(rng.startContainer) || isWithinCaretContainer(rng.endContainer);
+ }
+
+ function setContentEditableSelection(range) {
+ var node, $ = editor.$, dom = editor.dom, $realSelectionContainer, sel,
+ startContainer, startOffset, endOffset, e, caretPosition, targetClone, origTargetClone;
+
+ if (!range) {
+ return null;
+ }
+
+ if (range.collapsed) {
+ if (!isRangeInCaretContainer(range)) {
+ caretPosition = getNormalizedRangeEndPoint(1, range);
+
+ if (isContentEditableFalse(caretPosition.getNode())) {
+ return showCaret(1, caretPosition.getNode(), !caretPosition.isAtEnd());
+ }
+
+ if (isContentEditableFalse(caretPosition.getNode(true))) {
+ return showCaret(1, caretPosition.getNode(true), false);
+ }
+ }
+
+ return null;
+ }
+
+ startContainer = range.startContainer;
+ startOffset = range.startOffset;
+ endOffset = range.endOffset;
+
+ // Normalizes <span cE=false>[</span>] to [<span cE=false></span>]
+ if (startContainer.nodeType == 3 && startOffset == 0 && isContentEditableFalse(startContainer.parentNode)) {
+ startContainer = startContainer.parentNode;
+ startOffset = dom.nodeIndex(startContainer);
+ startContainer = startContainer.parentNode;
+ }
+
+ if (startContainer.nodeType != 1) {
+ return null;
+ }
+
+ if (endOffset == startOffset + 1) {
+ node = startContainer.childNodes[startOffset];
+ }
+
+ if (!isContentEditableFalse(node)) {
+ return null;
+ }
+
+ targetClone = origTargetClone = node.cloneNode(true);
+ e = editor.fire('ObjectSelected', { target: node, targetClone: targetClone });
+ if (e.isDefaultPrevented()) {
+ return null;
+ }
+
+ targetClone = e.targetClone;
+ $realSelectionContainer = $('#' + realSelectionId);
+ if ($realSelectionContainer.length === 0) {
+ $realSelectionContainer = $(
+ '<div data-mce-bogus="all" class="mce-offscreen-selection"></div>'
+ ).attr('id', realSelectionId);
+
+ $realSelectionContainer.appendTo(editor.getBody());
+ }
+
+ range = editor.dom.createRng();
+
+ // WHY is IE making things so hard! Copy on <i contentEditable="false">x</i> produces: <em>x</em>
+ // This is a ridiculous hack where we place the selection from a block over the inline element
+ // so that just the inline element is copied as is and not converted.
+ if (targetClone === origTargetClone && Env.ie) {
+ $realSelectionContainer.empty().append('<p style="font-size: 0" data-mce-bogus="all">\u00a0</p>').append(targetClone);
+ range.setStartAfter($realSelectionContainer[0].firstChild.firstChild);
+ range.setEndAfter(targetClone);
+ } else {
+ $realSelectionContainer.empty().append('\u00a0').append(targetClone).append('\u00a0');
+ range.setStart($realSelectionContainer[0].firstChild, 1);
+ range.setEnd($realSelectionContainer[0].lastChild, 0);
+ }
+
+ $realSelectionContainer.css({
+ top: dom.getPos(node, editor.getBody()).y
+ });
+
+ $realSelectionContainer[0].focus();
+ sel = editor.selection.getSel();
+ sel.removeAllRanges();
+ sel.addRange(range);
+
+ editor.$('*[data-mce-selected]').removeAttr('data-mce-selected');
+ node.setAttribute('data-mce-selected', 1);
+ selectedContentEditableNode = node;
+ hideFakeCaret();
+
+ return range;
+ }
+
+ function removeContentEditableSelection() {
+ if (selectedContentEditableNode) {
+ selectedContentEditableNode.removeAttribute('data-mce-selected');
+ editor.$('#' + realSelectionId).remove();
+ selectedContentEditableNode = null;
+ }
+ }
+
+ function destroy() {
+ fakeCaret.destroy();
+ selectedContentEditableNode = null;
+ }
+
+ function hideFakeCaret() {
+ fakeCaret.hide();
+ }
+
+ if (Env.ceFalse) {
+ registerEvents();
+ addCss();
+ }
+
+ return {
+ showBlockCaretContainer: showBlockCaretContainer,
+ hideFakeCaret: hideFakeCaret,
+ destroy: destroy
+ };
+ }
+
+ return SelectionOverrides;
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * SelectionOverrides.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * NodePath.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * This module contains logic overriding the selection with keyboard/mouse
- * around contentEditable=false regions.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Handles paths of nodes within an element.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @example
- * // Disable the default cE=false selection
- * tinymce.activeEditor.on('ShowCaret BeforeObjectSelected', function(e) {
- * e.preventDefault();
- * });
- *
</del><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @class tinymce.SelectionOverrides
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @class tinymce.dom.NodePath
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/SelectionOverrides", [
- "tinymce/Env",
- "tinymce/caret/CaretWalker",
- "tinymce/caret/CaretPosition",
- "tinymce/caret/CaretContainer",
- "tinymce/caret/CaretUtils",
- "tinymce/caret/FakeCaret",
- "tinymce/caret/LineWalker",
- "tinymce/caret/LineUtils",
- "tinymce/dom/NodeType",
- "tinymce/dom/RangeUtils",
- "tinymce/geom/ClientRect",
- "tinymce/util/VK",
- "tinymce/util/Fun",
- "tinymce/util/Arr",
- "tinymce/util/Delay",
- "tinymce/DragDropOverrides"
-], function(
- Env, CaretWalker, CaretPosition, CaretContainer, CaretUtils, FakeCaret, LineWalker,
- LineUtils, NodeType, RangeUtils, ClientRect, VK, Fun, Arr, Delay, DragDropOverrides
-) {
- var curry = Fun.curry,
- isContentEditableTrue = NodeType.isContentEditableTrue,
- isContentEditableFalse = NodeType.isContentEditableFalse,
- isElement = NodeType.isElement,
- isAfterContentEditableFalse = CaretUtils.isAfterContentEditableFalse,
- isBeforeContentEditableFalse = CaretUtils.isBeforeContentEditableFalse,
- getSelectedNode = RangeUtils.getSelectedNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.dom.NodePath',
+ [
+ "tinymce.core.dom.DOMUtils"
+ ],
+ function (DOMUtils) {
+ function create(rootNode, targetNode, normalized) {
+ var path = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getVisualCaretPosition(walkFn, caretPosition) {
- while ((caretPosition = walkFn(caretPosition))) {
- if (caretPosition.isVisible()) {
- return caretPosition;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (; targetNode && targetNode != rootNode; targetNode = targetNode.parentNode) {
+ path.push(DOMUtils.nodeIndex(targetNode, normalized));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return caretPosition;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return path;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function SelectionOverrides(editor) {
- var rootNode = editor.getBody(), caretWalker = new CaretWalker(rootNode);
- var getNextVisualCaretPosition = curry(getVisualCaretPosition, caretWalker.next);
- var getPrevVisualCaretPosition = curry(getVisualCaretPosition, caretWalker.prev),
- fakeCaret = new FakeCaret(editor.getBody(), isBlock),
- realSelectionId = 'sel-' + editor.dom.uniqueId(),
- selectedContentEditableNode, $ = editor.$;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function resolve(rootNode, path) {
+ var i, node, children;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isFakeSelectionElement(elm) {
- return editor.dom.hasClass(elm, 'mce-offscreen-selection');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (node = rootNode, i = path.length - 1; i >= 0; i--) {
+ children = node.childNodes;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getRealSelectionElement() {
- var container = editor.dom.get(realSelectionId);
- return container ? container.getElementsByTagName('*')[0] : container;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (path[i] > children.length - 1) {
+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isBlock(node) {
- return editor.dom.isBlock(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = children[path[i]];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setRange(range) {
- //console.log('setRange', range);
- if (range) {
- editor.selection.setRng(range);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return node;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getRange() {
- return editor.selection.getRng();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ create: create,
+ resolve: resolve
+ };
+ }
+);
+/**
+ * Quirks.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ *
+ * @ignore-file
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function scrollIntoView(node, alignToTop) {
- editor.selection.scrollIntoView(node, alignToTop);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * This file includes fixes for various browser quirks it's made to make it easy to add/remove browser specific fixes.
+ *
+ * @private
+ * @class tinymce.util.Quirks
+ */
+define(
+ 'tinymce.core.util.Quirks',
+ [
+ "tinymce.core.util.VK",
+ "tinymce.core.dom.RangeUtils",
+ "tinymce.core.dom.TreeWalker",
+ "tinymce.core.dom.NodePath",
+ "tinymce.core.html.Node",
+ "tinymce.core.html.Entities",
+ "tinymce.core.Env",
+ "tinymce.core.util.Tools",
+ "tinymce.core.util.Delay",
+ "tinymce.core.caret.CaretContainer",
+ "tinymce.core.caret.CaretPosition",
+ "tinymce.core.caret.CaretWalker"
+ ],
+ function (VK, RangeUtils, TreeWalker, NodePath, Node, Entities, Env, Tools, Delay, CaretContainer, CaretPosition, CaretWalker) {
+ return function (editor) {
+ var each = Tools.each;
+ var BACKSPACE = VK.BACKSPACE, DELETE = VK.DELETE, dom = editor.dom, selection = editor.selection,
+ settings = editor.settings, parser = editor.parser, serializer = editor.serializer;
+ var isGecko = Env.gecko, isIE = Env.ie, isWebKit = Env.webkit;
+ var mceInternalUrlPrefix = 'data:text/mce-internal,';
+ var mceInternalDataType = isIE ? 'Text' : 'URL';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function showCaret(direction, node, before) {
- var e;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Executes a command with a specific state this can be to enable/disable browser editing features.
+ */
+ function setEditorCommandState(cmd, state) {
+ try {
+ editor.getDoc().execCommand(cmd, false, state);
+ } catch (ex) {
+ // Ignore
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- e = editor.fire('ShowCaret', {
- target: node,
- direction: direction,
- before: before
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns current IE document mode.
+ */
+ function getDocumentMode() {
+ var documentMode = editor.getDoc().documentMode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.isDefaultPrevented()) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return documentMode ? documentMode : 6;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- scrollIntoView(node, direction === -1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the event is prevented or not.
+ *
+ * @private
+ * @param {Event} e Event object.
+ * @return {Boolean} true/false if the event is prevented or not.
+ */
+ function isDefaultPrevented(e) {
+ return e.isDefaultPrevented();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return fakeCaret.show(before, node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets Text/URL data on the event's dataTransfer object to a special data:text/mce-internal url.
+ * This is to workaround the inability to set custom contentType on IE and Safari.
+ * The editor's selected content is encoded into this url so drag and drop between editors will work.
+ *
+ * @private
+ * @param {DragEvent} e Event object
+ */
+ function setMceInternalContent(e) {
+ var selectionHtml, internalContent;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function selectNode(node) {
- var e;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.dataTransfer) {
+ if (editor.selection.isCollapsed() && e.target.tagName == 'IMG') {
+ selection.select(e.target);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- e = editor.fire('BeforeObjectSelected', {target: node});
- if (e.isDefaultPrevented()) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ selectionHtml = editor.selection.getContent();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return getNodeRange(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Safari/IE doesn't support custom dataTransfer items so we can only use URL and Text
+ if (selectionHtml.length > 0) {
+ internalContent = mceInternalUrlPrefix + escape(editor.id) + ',' + escape(selectionHtml);
+ e.dataTransfer.setData(mceInternalDataType, internalContent);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getNodeRange(node) {
- var rng = node.ownerDocument.createRange();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Gets content of special data:text/mce-internal url on the event's dataTransfer object.
+ * This is to workaround the inability to set custom contentType on IE and Safari.
+ * The editor's selected content is encoded into this url so drag and drop between editors will work.
+ *
+ * @private
+ * @param {DragEvent} e Event object
+ * @returns {String} mce-internal content
+ */
+ function getMceInternalContent(e) {
+ var internalContent;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng.selectNode(node);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.dataTransfer) {
+ internalContent = e.dataTransfer.getData(mceInternalDataType);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return rng;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (internalContent && internalContent.indexOf(mceInternalUrlPrefix) >= 0) {
+ internalContent = internalContent.substr(mceInternalUrlPrefix.length).split(',');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isMoveInsideSameBlock(fromCaretPosition, toCaretPosition) {
- var inSameBlock = CaretUtils.isInSameBlock(fromCaretPosition, toCaretPosition);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ id: unescape(internalContent[0]),
+ html: unescape(internalContent[1])
+ };
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle bogus BR <p>abc|<br></p>
- if (!inSameBlock && NodeType.isBr(fromCaretPosition.getNode())) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return inSameBlock;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Inserts contents using the paste clipboard command if it's available if it isn't it will fallback
+ * to the core command.
+ *
+ * @private
+ * @param {String} content Content to insert at selection.
+ * @param {Boolean} internal State if the paste is to be considered internal or external.
+ */
+ function insertClipboardContents(content, internal) {
+ if (editor.queryCommandSupported('mceInsertClipboardContent')) {
+ editor.execCommand('mceInsertClipboardContent', false, { content: content, internal: internal });
+ } else {
+ editor.execCommand('mceInsertContent', false, content);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getNormalizedRangeEndPoint(direction, range) {
- range = CaretUtils.normalizeRange(direction, rootNode, range);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Makes sure that the editor body becomes empty when backspace or delete is pressed in empty editors.
+ *
+ * For example:
+ * <p><b>|</b></p>
+ *
+ * Or:
+ * <h1>|</h1>
+ *
+ * Or:
+ * [<h1></h1>]
+ */
+ function emptyEditorWhenDeleting() {
+ function serializeRng(rng) {
+ var body = dom.create("body");
+ var contents = rng.cloneContents();
+ body.appendChild(contents);
+ return selection.serializer.serialize(body, { format: 'html' });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (direction == -1) {
- return CaretPosition.fromRangeStart(range);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function allContentsSelected(rng) {
+ if (!rng.setStart) {
+ if (rng.item) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return CaretPosition.fromRangeEnd(range);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var bodyRng = rng.duplicate();
+ bodyRng.moveToElementText(editor.getBody());
+ return RangeUtils.compareRanges(rng, bodyRng);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isRangeInCaretContainerBlock(range) {
- return CaretContainer.isCaretContainerBlock(range.startContainer);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var selection = serializeRng(rng);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function moveToCeFalseHorizontally(direction, getNextPosFn, isBeforeContentEditableFalseFn, range) {
- var node, caretPosition, peekCaretPosition, rangeIsInContainerBlock;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var allRng = dom.createRng();
+ allRng.selectNode(editor.getBody());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!range.collapsed) {
- node = getSelectedNode(range);
- if (isContentEditableFalse(node)) {
- return showCaret(direction, node, direction == -1);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var allSelection = serializeRng(allRng);
+ return selection === allSelection;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rangeIsInContainerBlock = isRangeInCaretContainerBlock(range);
- caretPosition = getNormalizedRangeEndPoint(direction, range);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('keydown', function (e) {
+ var keyCode = e.keyCode, isCollapsed, body;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isBeforeContentEditableFalseFn(caretPosition)) {
- return selectNode(caretPosition.getNode(direction == -1));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Empty the editor if it's needed for example backspace at <p><b>|</b></p>
+ if (!isDefaultPrevented(e) && (keyCode == DELETE || keyCode == BACKSPACE)) {
+ isCollapsed = editor.selection.isCollapsed();
+ body = editor.getBody();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- caretPosition = getNextPosFn(caretPosition);
- if (!caretPosition) {
- if (rangeIsInContainerBlock) {
- return range;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Selection is collapsed but the editor isn't empty
+ if (isCollapsed && !dom.isEmpty(body)) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Selection isn't collapsed but not all the contents is selected
+ if (!isCollapsed && !allContentsSelected(editor.selection.getRng())) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isBeforeContentEditableFalseFn(caretPosition)) {
- return showCaret(direction, caretPosition.getNode(direction == -1), direction == 1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Manually empty the editor
+ e.preventDefault();
+ editor.setContent('');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Peek ahead for handling of ab|c<span cE=false> -> abc|<span cE=false>
- peekCaretPosition = getNextPosFn(caretPosition);
- if (isBeforeContentEditableFalseFn(peekCaretPosition)) {
- if (isMoveInsideSameBlock(caretPosition, peekCaretPosition)) {
- return showCaret(direction, peekCaretPosition.getNode(direction == -1), direction == 1);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (body.firstChild && dom.isBlock(body.firstChild)) {
+ editor.selection.setCursorLocation(body.firstChild, 0);
+ } else {
+ editor.selection.setCursorLocation(body, 0);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rangeIsInContainerBlock) {
- return renderRangeCaret(caretPosition.toRange());
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.nodeChanged();
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * WebKit doesn't select all the nodes in the body when you press Ctrl+A.
+ * IE selects more than the contents <body>[<p>a</p>]</body> instead of <body><p>[a]</p]</body> see bug #6438
+ * This selects the whole body so that backspace/delete logic will delete everything
+ */
+ function selectAll() {
+ editor.shortcuts.add('meta+a', null, 'SelectAll');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function moveToCeFalseVertically(direction, walkerFn, range) {
- var caretPosition, linePositions, nextLinePositions,
- closestNextLineRect, caretClientRect, clientX,
- dist1, dist2, contentEditableFalseNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * WebKit has a weird issue where it some times fails to properly convert keypresses to input method keystrokes.
+ * The IME on Mac doesn't initialize when it doesn't fire a proper focus event.
+ *
+ * This seems to happen when the user manages to click the documentElement element then the window doesn't get proper focus until
+ * you enter a character into the editor.
+ *
+ * It also happens when the first focus in made to the body.
+ *
+ * See: https://bugs.webkit.org/show_bug.cgi?id=83566
+ */
+ function inputMethodFocus() {
+ if (!editor.settings.content_editable) {
+ // Case 1 IME doesn't initialize if you focus the document
+ // Disabled since it was interferring with the cE=false logic
+ // Also coultn't reproduce the issue on Safari 9
+ /*dom.bind(editor.getDoc(), 'focusin', function() {
+ selection.setRng(selection.getRng());
+ });*/
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- contentEditableFalseNode = getSelectedNode(range);
- caretPosition = getNormalizedRangeEndPoint(direction, range);
- linePositions = walkerFn(rootNode, LineWalker.isAboveLine(1), caretPosition);
- nextLinePositions = Arr.filter(linePositions, LineWalker.isLine(1));
- caretClientRect = Arr.last(caretPosition.getClientRects());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Case 2 IME doesn't initialize if you click the documentElement it also doesn't properly fire the focusin event
+ // Needs to be both down/up due to weird rendering bug on Chrome Windows
+ dom.bind(editor.getDoc(), 'mousedown mouseup', function (e) {
+ var rng;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isBeforeContentEditableFalse(caretPosition)) {
- contentEditableFalseNode = caretPosition.getNode();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.target == editor.getDoc().documentElement) {
+ rng = selection.getRng();
+ editor.getBody().focus();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isAfterContentEditableFalse(caretPosition)) {
- contentEditableFalseNode = caretPosition.getNode(true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.type == 'mousedown') {
+ if (CaretContainer.isCaretContainer(rng.startContainer)) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!caretClientRect) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Edge case for mousedown, drag select and mousedown again within selection on Chrome Windows to render caret
+ selection.placeCaretAt(e.clientX, e.clientY);
+ } else {
+ selection.setRng(rng);
+ }
+ }
+ });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- clientX = caretClientRect.left;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Backspacing in FireFox/IE from a paragraph into a horizontal rule results in a floating text node because the
+ * browser just deletes the paragraph - the browser fails to merge the text node with a horizontal rule so it is
+ * left there. TinyMCE sees a floating text node and wraps it in a paragraph on the key up event (ForceBlocks.js
+ * addRootBlocks), meaning the action does nothing. With this code, FireFox/IE matche the behaviour of other
+ * browsers.
+ *
+ * It also fixes a bug on Firefox where it's impossible to delete HR elements.
+ */
+ function removeHrOnBackspace() {
+ editor.on('keydown', function (e) {
+ if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {
+ // Check if there is any HR elements this is faster since getRng on IE 7 & 8 is slow
+ if (!editor.getBody().getElementsByTagName('hr').length) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- closestNextLineRect = LineUtils.findClosestClientRect(nextLinePositions, clientX);
- if (closestNextLineRect) {
- if (isContentEditableFalse(closestNextLineRect.node)) {
- dist1 = Math.abs(clientX - closestNextLineRect.left);
- dist2 = Math.abs(clientX - closestNextLineRect.right);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (selection.isCollapsed() && selection.getRng(true).startOffset === 0) {
+ var node = selection.getNode();
+ var previousSibling = node.previousSibling;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return showCaret(direction, closestNextLineRect.node, dist1 < dist2);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.nodeName == 'HR') {
+ dom.remove(node);
+ e.preventDefault();
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (contentEditableFalseNode) {
- var caretPositions = LineWalker.positionsUntil(direction, rootNode, LineWalker.isAboveLine(1), contentEditableFalseNode);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === "hr") {
+ dom.remove(previousSibling);
+ e.preventDefault();
+ }
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- closestNextLineRect = LineUtils.findClosestClientRect(Arr.filter(caretPositions, LineWalker.isLine(1)), clientX);
- if (closestNextLineRect) {
- return renderRangeCaret(closestNextLineRect.position.toRange());
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Firefox 3.x has an issue where the body element won't get proper focus if you click out
+ * side it's rectangle.
+ */
+ function focusBody() {
+ // Fix for a focus bug in FF 3.x where the body element
+ // wouldn't get proper focus if the user clicked on the HTML element
+ if (!window.Range.prototype.getClientRects) { // Detect getClientRects got introduced in FF 4
+ editor.on('mousedown', function (e) {
+ if (!isDefaultPrevented(e) && e.target.nodeName === "HTML") {
+ var body = editor.getBody();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- closestNextLineRect = Arr.last(Arr.filter(caretPositions, LineWalker.isLine(0)));
- if (closestNextLineRect) {
- return renderRangeCaret(closestNextLineRect.position.toRange());
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Blur the body it's focused but not correctly focused
+ body.blur();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function exitPreBlock(direction, range) {
- var pre, caretPos, newBlock;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Refocus the body after a little while
+ Delay.setEditorTimeout(editor, function () {
+ body.focus();
+ });
+ }
+ });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function createTextBlock() {
- var textBlock = editor.dom.create(editor.settings.forced_root_block);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * WebKit has a bug where it isn't possible to select image, hr or anchor elements
+ * by clicking on them so we need to fake that.
+ */
+ function selectControlElements() {
+ editor.on('click', function (e) {
+ var target = e.target;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!Env.ie || Env.ie >= 11) {
- textBlock.innerHTML = '<br data-mce-bogus="1">';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Workaround for bug, http://bugs.webkit.org/show_bug.cgi?id=12250
+ // WebKit can't even do simple things like selecting an image
+ // Needs to be the setBaseAndExtend or it will fail to select floated images
+ if (/^(IMG|HR)$/.test(target.nodeName) && dom.getContentEditableParent(target) !== "false") {
+ e.preventDefault();
+ editor.selection.select(target);
+ editor.nodeChanged();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return textBlock;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (target.nodeName == 'A' && dom.hasClass(target, 'mce-item-anchor')) {
+ e.preventDefault();
+ selection.select(target);
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (range.collapsed && editor.settings.forced_root_block) {
- pre = editor.dom.getParent(range.startContainer, 'PRE');
- if (!pre) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Fixes a Gecko bug where the style attribute gets added to the wrong element when deleting between two block elements.
+ *
+ * Fixes do backspace/delete on this:
+ * <p>bla[ck</p><p style="color:red">r]ed</p>
+ *
+ * Would become:
+ * <p>bla|ed</p>
+ *
+ * Instead of:
+ * <p style="color:red">bla|ed</p>
+ */
+ function removeStylesWhenDeletingAcrossBlockElements() {
+ function getAttributeApplyFunction() {
+ var template = dom.getAttribs(selection.getStart().cloneNode(false));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (direction == 1) {
- caretPos = getNextVisualCaretPosition(CaretPosition.fromRangeStart(range));
- } else {
- caretPos = getPrevVisualCaretPosition(CaretPosition.fromRangeStart(range));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return function () {
+ var target = selection.getStart();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!caretPos) {
- newBlock = createTextBlock();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (target !== editor.getBody()) {
+ dom.setAttrib(target, "style", null);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (direction == 1) {
- editor.$(pre).after(newBlock);
- } else {
- editor.$(pre).before(newBlock);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(template, function (attr) {
+ target.setAttributeNode(attr.cloneNode(true));
+ });
+ }
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.selection.select(newBlock, true);
- editor.selection.collapse();
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isSelectionAcrossElements() {
+ return !selection.isCollapsed() &&
+ dom.getParent(selection.getStart(), dom.isBlock) != dom.getParent(selection.getEnd(), dom.isBlock);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function moveH(direction, getNextPosFn, isBeforeContentEditableFalseFn, range) {
- var newRange;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('keypress', function (e) {
+ var applyAttributes;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- newRange = moveToCeFalseHorizontally(direction, getNextPosFn, isBeforeContentEditableFalseFn, range);
- if (newRange) {
- return newRange;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isDefaultPrevented(e) && (e.keyCode == 8 || e.keyCode == 46) && isSelectionAcrossElements()) {
+ applyAttributes = getAttributeApplyFunction();
+ editor.getDoc().execCommand('delete', false, null);
+ applyAttributes();
+ e.preventDefault();
+ return false;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- newRange = exitPreBlock(direction, range);
- if (newRange) {
- return newRange;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.bind(editor.getDoc(), 'cut', function (e) {
+ var applyAttributes;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isDefaultPrevented(e) && isSelectionAcrossElements()) {
+ applyAttributes = getAttributeApplyFunction();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function moveV(direction, walkerFn, range) {
- var newRange;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Delay.setEditorTimeout(editor, function () {
+ applyAttributes();
+ });
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- newRange = moveToCeFalseVertically(direction, walkerFn, range);
- if (newRange) {
- return newRange;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Screen readers on IE needs to have the role application set on the body.
+ */
+ function ensureBodyHasRoleApplication() {
+ document.body.setAttribute("role", "application");
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- newRange = exitPreBlock(direction, range);
- if (newRange) {
- return newRange;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Backspacing into a table behaves differently depending upon browser type.
+ * Therefore, disable Backspace when cursor immediately follows a table.
+ */
+ function disableBackspaceIntoATable() {
+ editor.on('keydown', function (e) {
+ if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {
+ if (selection.isCollapsed() && selection.getRng(true).startOffset === 0) {
+ var previousSibling = selection.getNode().previousSibling;
+ if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === "table") {
+ e.preventDefault();
+ return false;
+ }
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Old IE versions can't properly render BR elements in PRE tags white in contentEditable mode. So this
+ * logic adds a \n before the BR so that it will get rendered.
+ */
+ function addNewLinesBeforeBrInPre() {
+ // IE8+ rendering mode does the right thing with BR in PRE
+ if (getDocumentMode() > 7) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getBlockCaretContainer() {
- return $('*[data-mce-caret]')[0];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Enable display: none in area and add a specific class that hides all BR elements in PRE to
+ // avoid the caret from getting stuck at the BR elements while pressing the right arrow key
+ setEditorCommandState('RespectVisibilityInDesign', true);
+ editor.contentStyles.push('.mceHideBrInPre pre br {display: none}');
+ dom.addClass(editor.getBody(), 'mceHideBrInPre');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function showBlockCaretContainer(blockCaretContainer) {
- if (blockCaretContainer.hasAttribute('data-mce-caret')) {
- CaretContainer.showCaretContainerBlock(blockCaretContainer);
- setRange(getRange()); // Removes control rect on IE
- scrollIntoView(blockCaretContainer[0]);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Adds a \n before all BR elements in PRE to get them visual
+ parser.addNodeFilter('pre', function (nodes) {
+ var i = nodes.length, brNodes, j, brElm, sibling;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function renderCaretAtRange(range) {
- var caretPosition, ceRoot;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ brNodes = nodes[i].getAll('br');
+ j = brNodes.length;
+ while (j--) {
+ brElm = brNodes[j];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- range = CaretUtils.normalizeRange(1, rootNode, range);
- caretPosition = CaretPosition.fromRangeStart(range);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add \n before BR in PRE elements on older IE:s so the new lines get rendered
+ sibling = brElm.prev;
+ if (sibling && sibling.type === 3 && sibling.value.charAt(sibling.value - 1) != '\n') {
+ sibling.value += '\n';
+ } else {
+ brElm.parent.insert(new Node('#text', 3), brElm, true).value = '\n';
+ }
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isContentEditableFalse(caretPosition.getNode())) {
- return showCaret(1, caretPosition.getNode(), !caretPosition.isAtEnd());
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Removes any \n before BR elements in PRE since other browsers and in contentEditable=false mode they will be visible
+ serializer.addNodeFilter('pre', function (nodes) {
+ var i = nodes.length, brNodes, j, brElm, sibling;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isContentEditableFalse(caretPosition.getNode(true))) {
- return showCaret(1, caretPosition.getNode(true), false);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ brNodes = nodes[i].getAll('br');
+ j = brNodes.length;
+ while (j--) {
+ brElm = brNodes[j];
+ sibling = brElm.prev;
+ if (sibling && sibling.type == 3) {
+ sibling.value = sibling.value.replace(/\r?\n$/, '');
+ }
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // TODO: Should render caret before/after depending on where you click on the page forces after now
- ceRoot = editor.dom.getParent(caretPosition.getNode(), Fun.or(isContentEditableFalse, isContentEditableTrue));
- if (isContentEditableFalse(ceRoot)) {
- return showCaret(1, ceRoot, false);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Moves style width/height to attribute width/height when the user resizes an image on IE.
+ */
+ function removePreSerializedStylesWhenSelectingControls() {
+ dom.bind(editor.getBody(), 'mouseup', function () {
+ var value, node = selection.getNode();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Moved styles to attributes on IMG eements
+ if (node.nodeName == 'IMG') {
+ // Convert style width to width attribute
+ if ((value = dom.getStyle(node, 'width'))) {
+ dom.setAttrib(node, 'width', value.replace(/[^0-9%]+/g, ''));
+ dom.setStyle(node, 'width', '');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function renderRangeCaret(range) {
- var caretRange;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Convert style height to height attribute
+ if ((value = dom.getStyle(node, 'height'))) {
+ dom.setAttrib(node, 'height', value.replace(/[^0-9%]+/g, ''));
+ dom.setStyle(node, 'height', '');
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!range || !range.collapsed) {
- return range;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes a blockquote when backspace is pressed at the beginning of it.
+ *
+ * For example:
+ * <blockquote><p>|x</p></blockquote>
+ *
+ * Becomes:
+ * <p>|x</p>
+ */
+ function removeBlockQuoteOnBackSpace() {
+ // Add block quote deletion handler
+ editor.on('keydown', function (e) {
+ var rng, container, offset, root, parent;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- caretRange = renderCaretAtRange(range);
- if (caretRange) {
- return caretRange;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isDefaultPrevented(e) || e.keyCode != VK.BACKSPACE) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return range;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rng = selection.getRng();
+ container = rng.startContainer;
+ offset = rng.startOffset;
+ root = dom.getRoot();
+ parent = container;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function deleteContentEditableNode(node) {
- var nextCaretPosition, prevCaretPosition, prevCeFalseElm, nextElement;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!rng.collapsed || offset !== 0) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isContentEditableFalse(node)) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (parent && parent.parentNode && parent.parentNode.firstChild == parent && parent.parentNode != root) {
+ parent = parent.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isContentEditableFalse(node.previousSibling)) {
- prevCeFalseElm = node.previousSibling;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Is the cursor at the beginning of a blockquote?
+ if (parent.tagName === 'BLOCKQUOTE') {
+ // Remove the blockquote
+ editor.formatter.toggle('blockquote', null, parent);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- prevCaretPosition = getPrevVisualCaretPosition(CaretPosition.before(node));
- if (!prevCaretPosition) {
- nextCaretPosition = getNextVisualCaretPosition(CaretPosition.after(node));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move the caret to the beginning of container
+ rng = dom.createRng();
+ rng.setStart(container, 0);
+ rng.setEnd(container, 0);
+ selection.setRng(rng);
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (nextCaretPosition && isElement(nextCaretPosition.getNode())) {
- nextElement = nextCaretPosition.getNode();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets various Gecko editing options on mouse down and before a execCommand to disable inline table editing that is broken etc.
+ */
+ function setGeckoEditingOptions() {
+ function setOpts() {
+ refreshContentEditable();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- CaretContainer.remove(node.previousSibling);
- CaretContainer.remove(node.nextSibling);
- editor.dom.remove(node);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ setEditorCommandState("StyleWithCSS", false);
+ setEditorCommandState("enableInlineTableEditing", false);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.dom.isEmpty(editor.getBody())) {
- editor.setContent('');
- editor.focus();
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!settings.object_resizing) {
+ setEditorCommandState("enableObjectResizing", false);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (prevCeFalseElm) {
- return CaretPosition.after(prevCeFalseElm).toRange();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!settings.readonly) {
+ editor.on('BeforeExecCommand MouseDown', setOpts);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (nextElement) {
- return CaretPosition.before(nextElement).toRange();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Fixes a gecko link bug, when a link is placed at the end of block elements there is
+ * no way to move the caret behind the link. This fix adds a bogus br element after the link.
+ *
+ * For example this:
+ * <p><b><a href="#">x</a></b></p>
+ *
+ * Becomes this:
+ * <p><b><a href="#">x</a></b><br></p>
+ */
+ function addBrAfterLastLinks() {
+ function fixLinks() {
+ each(dom.select('a'), function (node) {
+ var parentNode = node.parentNode, root = dom.getRoot();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (prevCaretPosition) {
- return prevCaretPosition.toRange();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parentNode.lastChild === node) {
+ while (parentNode && !dom.isBlock(parentNode)) {
+ if (parentNode.parentNode.lastChild !== parentNode || parentNode === root) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (nextCaretPosition) {
- return nextCaretPosition.toRange();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parentNode = parentNode.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.add(parentNode, 'br', { 'data-mce-bogus': 1 });
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isTextBlock(node) {
- var textBlocks = editor.schema.getTextBlockElements();
- return node.nodeName in textBlocks;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('SetContent ExecCommand', function (e) {
+ if (e.type == "setcontent" || e.command === 'mceInsertLink') {
+ fixLinks();
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isEmpty(elm) {
- return editor.dom.isEmpty(elm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * WebKit will produce DIV elements here and there by default. But since TinyMCE uses paragraphs by
+ * default we want to change that behavior.
+ */
+ function setDefaultBlockType() {
+ if (settings.forced_root_block) {
+ editor.on('init', function () {
+ setEditorCommandState('DefaultParagraphSeparator', settings.forced_root_block);
+ });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function mergeTextBlocks(direction, fromCaretPosition, toCaretPosition) {
- var dom = editor.dom, fromBlock, toBlock, node, ceTarget;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Deletes the selected image on IE instead of navigating to previous page.
+ */
+ function deleteControlItemOnBackSpace() {
+ editor.on('keydown', function (e) {
+ var rng;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- fromBlock = dom.getParent(fromCaretPosition.getNode(), dom.isBlock);
- toBlock = dom.getParent(toCaretPosition.getNode(), dom.isBlock);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isDefaultPrevented(e) && e.keyCode == BACKSPACE) {
+ rng = editor.getDoc().selection.createRange();
+ if (rng && rng.item) {
+ e.preventDefault();
+ editor.undoManager.beforeChange();
+ dom.remove(rng.item(0));
+ editor.undoManager.add();
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (direction === -1) {
- ceTarget = toCaretPosition.getNode(true);
- if (isAfterContentEditableFalse(toCaretPosition) && isBlock(ceTarget)) {
- if (isTextBlock(fromBlock)) {
- if (isEmpty(fromBlock)) {
- dom.remove(fromBlock);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * IE10 doesn't properly render block elements with the right height until you add contents to them.
+ * This fixes that by adding a padding-right to all empty text block elements.
+ * See: https://connect.microsoft.com/IE/feedback/details/743881
+ */
+ function renderEmptyBlocksFix() {
+ var emptyBlocksCSS;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return CaretPosition.after(ceTarget).toRange();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // IE10+
+ if (getDocumentMode() >= 10) {
+ emptyBlocksCSS = '';
+ each('p div h1 h2 h3 h4 h5 h6'.split(' '), function (name, i) {
+ emptyBlocksCSS += (i > 0 ? ',' : '') + name + ':empty';
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return deleteContentEditableNode(toCaretPosition.getNode(true));
- }
- } else {
- ceTarget = fromCaretPosition.getNode();
- if (isBeforeContentEditableFalse(fromCaretPosition) && isBlock(ceTarget)) {
- if (isTextBlock(toBlock)) {
- if (isEmpty(toBlock)) {
- dom.remove(toBlock);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.contentStyles.push(emptyBlocksCSS + '{padding-right: 1px !important}');
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return CaretPosition.before(ceTarget).toRange();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Old IE versions can't retain contents within noscript elements so this logic will store the contents
+ * as a attribute and the insert that value as it's raw text when the DOM is serialized.
+ */
+ function keepNoScriptContents() {
+ if (getDocumentMode() < 9) {
+ parser.addNodeFilter('noscript', function (nodes) {
+ var i = nodes.length, node, textNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return deleteContentEditableNode(fromCaretPosition.getNode());
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i];
+ textNode = node.firstChild;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Verify that both blocks are text blocks
- if (fromBlock === toBlock || !isTextBlock(fromBlock) || !isTextBlock(toBlock)) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (textNode) {
+ node.attr('data-mce-innertext', textNode.value);
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while ((node = fromBlock.firstChild)) {
- toBlock.appendChild(node);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ serializer.addNodeFilter('noscript', function (nodes) {
+ var i = nodes.length, node, textNode, value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.dom.remove(fromBlock);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i];
+ textNode = nodes[i].firstChild;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return toCaretPosition.toRange();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (textNode) {
+ textNode.value = Entities.decode(textNode.value);
+ } else {
+ // Old IE can't retain noscript value so an attribute is used to store it
+ value = node.attributes.map['data-mce-innertext'];
+ if (value) {
+ node.attr('data-mce-innertext', null);
+ textNode = new Node('#text', 3);
+ textNode.value = value;
+ textNode.raw = true;
+ node.append(textNode);
+ }
+ }
+ }
+ });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function backspaceDelete(direction, beforeFn, afterFn, range) {
- var node, caretPosition, peekCaretPosition, newCaretPosition;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * IE has an issue where you can't select/move the caret by clicking outside the body if the document is in standards mode.
+ */
+ function fixCaretSelectionOfDocumentElementOnIe() {
+ var doc = dom.doc, body = doc.body, started, startRng, htmlElm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!range.collapsed) {
- node = getSelectedNode(range);
- if (isContentEditableFalse(node)) {
- return renderRangeCaret(deleteContentEditableNode(node));
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Return range from point or null if it failed
+ function rngFromPoint(x, y) {
+ var rng = body.createTextRange();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- caretPosition = getNormalizedRangeEndPoint(direction, range);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ try {
+ rng.moveToPoint(x, y);
+ } catch (ex) {
+ // IE sometimes throws and exception, so lets just ignore it
+ rng = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (afterFn(caretPosition) && CaretContainer.isCaretContainerBlock(range.startContainer)) {
- newCaretPosition = direction == -1 ? caretWalker.prev(caretPosition) : caretWalker.next(caretPosition);
- return newCaretPosition ? renderRangeCaret(newCaretPosition.toRange()) : range;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return rng;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (beforeFn(caretPosition)) {
- return renderRangeCaret(deleteContentEditableNode(caretPosition.getNode(direction == -1)));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Fires while the selection is changing
+ function selectionChange(e) {
+ var pointRng;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- peekCaretPosition = direction == -1 ? caretWalker.prev(caretPosition) : caretWalker.next(caretPosition);
- if (beforeFn(peekCaretPosition)) {
- if (direction === -1) {
- return mergeTextBlocks(direction, caretPosition, peekCaretPosition);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if the button is down or not
+ if (e.button) {
+ // Create range from mouse position
+ pointRng = rngFromPoint(e.x, e.y);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return mergeTextBlocks(direction, peekCaretPosition, caretPosition);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (pointRng) {
+ // Check if pointRange is before/after selection then change the endPoint
+ if (pointRng.compareEndPoints('StartToStart', startRng) > 0) {
+ pointRng.setEndPoint('StartToStart', startRng);
+ } else {
+ pointRng.setEndPoint('EndToEnd', startRng);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function registerEvents() {
- var right = curry(moveH, 1, getNextVisualCaretPosition, isBeforeContentEditableFalse);
- var left = curry(moveH, -1, getPrevVisualCaretPosition, isAfterContentEditableFalse);
- var deleteForward = curry(backspaceDelete, 1, isBeforeContentEditableFalse, isAfterContentEditableFalse);
- var backspace = curry(backspaceDelete, -1, isAfterContentEditableFalse, isBeforeContentEditableFalse);
- var up = curry(moveV, -1, LineWalker.upUntil);
- var down = curry(moveV, 1, LineWalker.downUntil);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ pointRng.select();
+ }
+ } else {
+ endSelection();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function override(evt, moveFn) {
- var range = moveFn(getRange());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Removes listeners
+ function endSelection() {
+ var rng = doc.selection.createRange();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (range && !evt.isDefaultPrevented()) {
- evt.preventDefault();
- setRange(range);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If the range is collapsed then use the last start range
+ if (startRng && !rng.item && rng.compareEndPoints('StartToEnd', rng) === 0) {
+ startRng.select();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getContentEditableRoot(node) {
- var root = editor.getBody();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.unbind(doc, 'mouseup', endSelection);
+ dom.unbind(doc, 'mousemove', selectionChange);
+ startRng = started = 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (node && node != root) {
- if (isContentEditableTrue(node) || isContentEditableFalse(node)) {
- return node;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Make HTML element unselectable since we are going to handle selection by hand
+ doc.documentElement.unselectable = true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Detect when user selects outside BODY
+ dom.bind(doc, 'mousedown contextmenu', function (e) {
+ if (e.target.nodeName === 'HTML') {
+ if (started) {
+ endSelection();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Detect vertical scrollbar, since IE will fire a mousedown on the scrollbar and have target set as HTML
+ htmlElm = doc.documentElement;
+ if (htmlElm.scrollHeight > htmlElm.clientHeight) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isXYWithinRange(clientX, clientY, range) {
- if (range.collapsed) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ started = 1;
+ // Setup start position
+ startRng = rngFromPoint(e.x, e.y);
+ if (startRng) {
+ // Listen for selection change events
+ dom.bind(doc, 'mouseup', endSelection);
+ dom.bind(doc, 'mousemove', selectionChange);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Arr.reduce(range.getClientRects(), function(state, rect) {
- return state || ClientRect.containsXY(rect, clientX, clientY);
- }, false);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.getRoot().focus();
+ startRng.select();
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Some browsers (Chrome) lets you place the caret after a cE=false
- // Make sure we render the caret container in this case
- editor.on('mouseup', function() {
- var range = getRange();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Fixes selection issues where the caret can be placed between two inline elements like <b>a</b>|<b>b</b>
+ * this fix will lean the caret right into the closest inline element.
+ */
+ function normalizeSelection() {
+ // Normalize selection for example <b>a</b><i>|a</i> becomes <b>a|</b><i>a</i> except for Ctrl+A since it selects everything
+ editor.on('keyup focusin mouseup', function (e) {
+ if (e.keyCode != 65 || !VK.metaKeyPressed(e)) {
+ selection.normalize();
+ }
+ }, true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (range.collapsed) {
- setRange(renderCaretAtRange(range));
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Forces Gecko to render a broken image icon if it fails to load an image.
+ */
+ function showBrokenImageIcon() {
+ editor.contentStyles.push(
+ 'img:-moz-broken {' +
+ '-moz-force-broken-image-icon:1;' +
+ 'min-width:24px;' +
+ 'min-height:24px' +
+ '}'
+ );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('click', function(e) {
- var contentEditableRoot;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * iOS has a bug where it's impossible to type if the document has a touchstart event
+ * bound and the user touches the document while having the on screen keyboard visible.
+ *
+ * The touch event moves the focus to the parent document while having the caret inside the iframe
+ * this fix moves the focus back into the iframe document.
+ */
+ function restoreFocusOnKeyDown() {
+ if (!editor.inline) {
+ editor.on('keydown', function () {
+ if (document.activeElement == document.body) {
+ editor.getWin().focus();
+ }
+ });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- contentEditableRoot = getContentEditableRoot(e.target);
- if (contentEditableRoot) {
- // Prevent clicks on links in a cE=false element
- if (isContentEditableFalse(contentEditableRoot)) {
- e.preventDefault();
- editor.focus();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * IE 11 has an annoying issue where you can't move focus into the editor
+ * by clicking on the white area HTML element. We used to be able to to fix this with
+ * the fixCaretSelectionOfDocumentElementOnIe fix. But since M$ removed the selection
+ * object it's not possible anymore. So we need to hack in a ungly CSS to force the
+ * body to be at least 150px. If the user clicks the HTML element out side this 150px region
+ * we simply move the focus into the first paragraph. Not ideal since you loose the
+ * positioning of the caret but goot enough for most cases.
+ */
+ function bodyHeight() {
+ if (!editor.inline) {
+ editor.contentStyles.push('body {min-height: 150px}');
+ editor.on('click', function (e) {
+ var rng;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Removes fake selection if a cE=true is clicked within a cE=false like the toc title
- if (isContentEditableTrue(contentEditableRoot)) {
- if (editor.dom.isChildOf(contentEditableRoot, editor.selection.getNode())) {
- removeContentEditableSelection();
- }
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.target.nodeName == 'HTML') {
+ // Edge seems to only need focus if we set the range
+ // the caret will become invisible and moved out of the iframe!!
+ if (Env.ie > 11) {
+ editor.getBody().focus();
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('blur NewBlock', function () {
- removeContentEditableSelection();
- hideFakeCaret();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Need to store away non collapsed ranges since the focus call will mess that up see #7382
+ rng = editor.selection.getRng();
+ editor.getBody().focus();
+ editor.selection.setRng(rng);
+ editor.selection.normalize();
+ editor.nodeChanged();
+ }
+ });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function handleTouchSelect(editor) {
- var moved = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Firefox on Mac OS will move the browser back to the previous page if you press CMD+Left arrow.
+ * You might then loose all your work so we need to block that behavior and replace it with our own.
+ */
+ function blockCmdArrowNavigation() {
+ if (Env.mac) {
+ editor.on('keydown', function (e) {
+ if (VK.metaKeyPressed(e) && !e.shiftKey && (e.keyCode == 37 || e.keyCode == 39)) {
+ e.preventDefault();
+ editor.selection.getSel().modify('move', e.keyCode == 37 ? 'backward' : 'forward', 'lineboundary');
+ }
+ });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('touchstart', function () {
- moved = false;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Disables the autolinking in IE 9+ this is then re-enabled by the autolink plugin.
+ */
+ function disableAutoUrlDetect() {
+ setEditorCommandState("AutoUrlDetect", false);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('touchmove', function () {
- moved = true;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * iOS 7.1 introduced two new bugs:
+ * 1) It's possible to open links within a contentEditable area by clicking on them.
+ * 2) If you hold down the finger it will display the link/image touch callout menu.
+ */
+ function tapLinksAndImages() {
+ editor.on('click', function (e) {
+ var elm = e.target;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('touchend', function (e) {
- var contentEditableRoot = getContentEditableRoot(e.target);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ do {
+ if (elm.tagName === 'A') {
+ e.preventDefault();
+ return;
+ }
+ } while ((elm = elm.parentNode));
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isContentEditableFalse(contentEditableRoot)) {
- if (!moved) {
- e.preventDefault();
- setContentEditableSelection(selectNode(contentEditableRoot));
- }
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.contentStyles.push('.mce-content-body {-webkit-touch-callout: none}');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var hasNormalCaretPosition = function (elm) {
- var caretWalker = new CaretWalker(elm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * iOS Safari and possible other browsers have a bug where it won't fire
+ * a click event when a contentEditable is focused. This function fakes click events
+ * by using touchstart/touchend and measuring the time and distance travelled.
+ */
+ /*
+ function touchClickEvent() {
+ editor.on('touchstart', function(e) {
+ var elm, time, startTouch, changedTouches;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!elm.firstChild) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elm = e.target;
+ time = new Date().getTime();
+ changedTouches = e.changedTouches;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var startPos = CaretPosition.before(elm.firstChild);
- var newPos = caretWalker.next(startPos);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!changedTouches || changedTouches.length > 1) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return newPos && !isBeforeContentEditableFalse(newPos) && !isAfterContentEditableFalse(newPos);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ startTouch = changedTouches[0];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isInSameBlock = function (node1, node2) {
- var block1 = editor.dom.getParent(node1, editor.dom.isBlock);
- var block2 = editor.dom.getParent(node2, editor.dom.isBlock);
- return block1 === block2;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.once('touchend', function(e) {
+ var endTouch = e.changedTouches[0], args;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isContentKey = function (e) {
- if (e.keyCode >= 112 && e.keyCode <= 123) {
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (new Date().getTime() - time > 500) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (Math.abs(startTouch.clientX - endTouch.clientX) > 5) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Checks if the target node is in a block and if that block has a caret position better than the
- // suggested caretNode this is to prevent the caret from being sucked in towards a cE=false block if
- // they are adjacent on the vertical axis
- var hasBetterMouseTarget = function (targetNode, caretNode) {
- var targetBlock = editor.dom.getParent(targetNode, editor.dom.isBlock);
- var caretBlock = editor.dom.getParent(caretNode, editor.dom.isBlock);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (Math.abs(startTouch.clientY - endTouch.clientY) > 5) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return targetBlock && !isInSameBlock(targetBlock, caretBlock) && hasNormalCaretPosition(targetBlock);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args = {
+ target: elm
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- handleTouchSelect(editor);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each('pageX pageY clientX clientY screenX screenY'.split(' '), function(key) {
+ args[key] = endTouch[key];
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('mousedown', function(e) {
- var contentEditableRoot;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args = editor.fire('click', args);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- contentEditableRoot = getContentEditableRoot(e.target);
- if (contentEditableRoot) {
- if (isContentEditableFalse(contentEditableRoot)) {
- e.preventDefault();
- setContentEditableSelection(selectNode(contentEditableRoot));
- } else {
- if (!isXYWithinRange(e.clientX, e.clientY, editor.selection.getRng())) {
- editor.selection.placeCaretAt(e.clientX, e.clientY);
- }
- }
- } else {
- // Remove needs to be called here since the mousedown might alter the selection without calling selection.setRng
- // and therefore not fire the AfterSetSelectionRange event.
- removeContentEditableSelection();
- hideFakeCaret();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!args.isDefaultPrevented()) {
+ // iOS WebKit can't place the caret properly once
+ // you bind touch events so we need to do this manually
+ // TODO: Expand to the closest word? Touble tap still works.
+ editor.selection.placeCaretAt(endTouch.clientX, endTouch.clientY);
+ editor.nodeChanged();
+ }
+ });
+ });
+ }
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var caretInfo = LineUtils.closestCaret(rootNode, e.clientX, e.clientY);
- if (caretInfo) {
- if (!hasBetterMouseTarget(e.target, caretInfo.node)) {
- e.preventDefault();
- editor.getBody().focus();
- setRange(showCaret(1, caretInfo.node, caretInfo.before));
- }
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * WebKit has a bug where it will allow forms to be submitted if they are inside a contentEditable element.
+ * For example this: <form><button></form>
+ */
+ function blockFormSubmitInsideEditor() {
+ editor.on('init', function () {
+ editor.dom.bind(editor.getBody(), 'submit', function (e) {
+ e.preventDefault();
+ });
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('keydown', function(e) {
- if (VK.modifierPressed(e)) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sometimes WebKit/Blink generates BR elements with the Apple-interchange-newline class.
+ *
+ * Scenario:
+ * 1) Create a table 2x2.
+ * 2) Select and copy cells A2-B2.
+ * 3) Paste and it will add BR element to table cell.
+ */
+ function removeAppleInterchangeBrs() {
+ parser.addNodeFilter('br', function (nodes) {
+ var i = nodes.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- switch (e.keyCode) {
- case VK.RIGHT:
- override(e, right);
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ if (nodes[i].attr('class') == 'Apple-interchange-newline') {
+ nodes[i].remove();
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case VK.DOWN:
- override(e, down);
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * IE cannot set custom contentType's on drag events, and also does not properly drag/drop between
+ * editors. This uses a special data:text/mce-internal URL to pass data when drag/drop between editors.
+ */
+ function ieInternalDragAndDrop() {
+ editor.on('dragstart', function (e) {
+ setMceInternalContent(e);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case VK.LEFT:
- override(e, left);
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('drop', function (e) {
+ if (!isDefaultPrevented(e)) {
+ var internalContent = getMceInternalContent(e);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case VK.UP:
- override(e, up);
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (internalContent && internalContent.id != editor.id) {
+ e.preventDefault();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case VK.DELETE:
- override(e, deleteForward);
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var rng = RangeUtils.getCaretRangeFromPoint(e.x, e.y, editor.getDoc());
+ selection.setRng(rng);
+ insertClipboardContents(internalContent.html, true);
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case VK.BACKSPACE:
- override(e, backspace);
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function refreshContentEditable() {
+ // No-op since Mozilla seems to have fixed the caret repaint issues
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- default:
- if (isContentEditableFalse(editor.selection.getNode()) && isContentKey(e)) {
- e.preventDefault();
- }
- break;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isHidden() {
+ var sel;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function paddEmptyContentEditableArea() {
- var br, ceRoot = getContentEditableRoot(editor.selection.getNode());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isGecko) {
+ return 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isContentEditableTrue(ceRoot) && isBlock(ceRoot) && editor.dom.isEmpty(ceRoot)) {
- br = editor.dom.create('br', {"data-mce-bogus": "1"});
- editor.$(ceRoot).empty().append(br);
- editor.selection.setRng(CaretPosition.before(br).toRange());
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Weird, wheres that cursor selection?
+ sel = editor.selection.getSel();
+ return (!sel || !sel.rangeCount || sel.rangeCount === 0);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function handleBlockContainer(e) {
- var blockCaretContainer = getBlockCaretContainer();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Properly empties the editor if all contents is selected and deleted this to
+ * prevent empty paragraphs from being produced at beginning/end of contents.
+ */
+ function emptyEditorOnDeleteEverything() {
+ function isEverythingSelected(editor) {
+ var caretWalker = new CaretWalker(editor.getBody());
+ var rng = editor.selection.getRng();
+ var startCaretPos = CaretPosition.fromRangeStart(rng);
+ var endCaretPos = CaretPosition.fromRangeEnd(rng);
+ var prev = caretWalker.prev(startCaretPos);
+ var next = caretWalker.next(endCaretPos);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!blockCaretContainer) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return !editor.selection.isCollapsed() &&
+ (!prev || (prev.isAtStart() && startCaretPos.isEqual(prev))) &&
+ (!next || (next.isAtEnd() && startCaretPos.isEqual(next)));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.type == 'compositionstart') {
- e.preventDefault();
- e.stopPropagation();
- showBlockCaretContainer(blockCaretContainer);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Type over case delete and insert this won't cover typeover with a IME but at least it covers the common case
+ editor.on('keypress', function (e) {
+ if (!isDefaultPrevented(e) && !selection.isCollapsed() && e.charCode > 31 && !VK.metaKeyPressed(e)) {
+ if (isEverythingSelected(editor)) {
+ e.preventDefault();
+ editor.setContent(String.fromCharCode(e.charCode));
+ editor.selection.select(editor.getBody(), true);
+ editor.selection.collapse(false);
+ editor.nodeChanged();
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (CaretContainer.hasContent(blockCaretContainer)) {
- showBlockCaretContainer(blockCaretContainer);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('keydown', function (e) {
+ var keyCode = e.keyCode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function handleEmptyBackspaceDelete(e) {
- var prevent;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!isDefaultPrevented(e) && (keyCode == DELETE || keyCode == BACKSPACE)) {
+ if (isEverythingSelected(editor)) {
+ e.preventDefault();
+ editor.setContent('');
+ editor.nodeChanged();
+ }
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- switch (e.keyCode) {
- case VK.DELETE:
- prevent = paddEmptyContentEditableArea();
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // All browsers
+ removeBlockQuoteOnBackSpace();
+ emptyEditorWhenDeleting();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case VK.BACKSPACE:
- prevent = paddEmptyContentEditableArea();
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Windows phone will return a range like [body, 0] on mousedown so
+ // it will always normalize to the wrong location
+ if (!Env.windowsPhone) {
+ normalizeSelection();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (prevent) {
- e.preventDefault();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // WebKit
+ if (isWebKit) {
+ emptyEditorOnDeleteEverything();
+ inputMethodFocus();
+ selectControlElements();
+ setDefaultBlockType();
+ blockFormSubmitInsideEditor();
+ disableBackspaceIntoATable();
+ removeAppleInterchangeBrs();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Must be added to "top" since undoManager needs to be executed after
- editor.on('keyup compositionstart', function(e) {
- handleBlockContainer(e);
- handleEmptyBackspaceDelete(e);
- }, true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ //touchClickEvent();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('cut', function() {
- var node = editor.selection.getNode();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // iOS
+ if (Env.iOS) {
+ restoreFocusOnKeyDown();
+ bodyHeight();
+ tapLinksAndImages();
+ } else {
+ selectAll();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isContentEditableFalse(node)) {
- Delay.setEditorTimeout(editor, function() {
- setRange(renderRangeCaret(deleteContentEditableNode(node)));
- });
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // IE
+ if (isIE && Env.ie < 11) {
+ removeHrOnBackspace();
+ ensureBodyHasRoleApplication();
+ addNewLinesBeforeBrInPre();
+ removePreSerializedStylesWhenSelectingControls();
+ deleteControlItemOnBackSpace();
+ renderEmptyBlocksFix();
+ keepNoScriptContents();
+ fixCaretSelectionOfDocumentElementOnIe();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('getSelectionRange', function(e) {
- var rng = e.range;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (Env.ie >= 11) {
+ bodyHeight();
+ disableBackspaceIntoATable();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (selectedContentEditableNode) {
- if (!selectedContentEditableNode.parentNode) {
- selectedContentEditableNode = null;
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (Env.ie) {
+ selectAll();
+ disableAutoUrlDetect();
+ ieInternalDragAndDrop();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng = rng.cloneRange();
- rng.selectNode(selectedContentEditableNode);
- e.range = rng;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Gecko
+ if (isGecko) {
+ emptyEditorOnDeleteEverything();
+ removeHrOnBackspace();
+ focusBody();
+ removeStylesWhenDeletingAcrossBlockElements();
+ setGeckoEditingOptions();
+ addBrAfterLastLinks();
+ showBrokenImageIcon();
+ blockCmdArrowNavigation();
+ disableBackspaceIntoATable();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('setSelectionRange', function(e) {
- var rng;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ refreshContentEditable: refreshContentEditable,
+ isHidden: isHidden
+ };
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rng = setContentEditableSelection(e.range);
- if (rng) {
- e.range = rng;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * InitContentBody.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('AfterSetSelectionRange', function(e) {
- var rng = e.range;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.init.InitContentBody',
+ [
+ 'global!document',
+ 'global!window',
+ 'tinymce.core.caret.CaretContainerInput',
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.core.dom.Selection',
+ 'tinymce.core.dom.Serializer',
+ 'tinymce.core.EditorUpload',
+ 'tinymce.core.ErrorReporter',
+ 'tinymce.core.ForceBlocks',
+ 'tinymce.core.Formatter',
+ 'tinymce.core.html.DomParser',
+ 'tinymce.core.html.Node',
+ 'tinymce.core.html.Schema',
+ 'tinymce.core.keyboard.KeyboardOverrides',
+ 'tinymce.core.NodeChange',
+ 'tinymce.core.SelectionOverrides',
+ 'tinymce.core.UndoManager',
+ 'tinymce.core.util.Delay',
+ 'tinymce.core.util.Quirks',
+ 'tinymce.core.util.Tools'
+ ],
+ function (
+ document, window, CaretContainerInput, DOMUtils, Selection, Serializer, EditorUpload, ErrorReporter, ForceBlocks, Formatter, DomParser, Node, Schema, KeyboardOverrides,
+ NodeChange, SelectionOverrides, UndoManager, Delay, Quirks, Tools
+ ) {
+ var DOM = DOMUtils.DOM;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isRangeInCaretContainer(rng)) {
- hideFakeCaret();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createParser = function (editor) {
+ var parser = new DomParser(editor.settings, editor.schema);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isFakeSelectionElement(rng.startContainer.parentNode)) {
- removeContentEditableSelection();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Convert src and href into data-mce-src, data-mce-href and data-mce-style
+ parser.addAttributeFilter('src,href,style,tabindex', function (nodes, name) {
+ var i = nodes.length, node, dom = editor.dom, value, internalName;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('focus', function() {
- // Make sure we have a proper fake caret on focus
- Delay.setEditorTimeout(editor, function() {
- editor.selection.setRng(renderRangeCaret(editor.selection.getRng()));
- }, 0);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i];
+ value = node.attr(name);
+ internalName = 'data-mce-' + name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('copy', function (e) {
- var clipboardData = e.clipboardData;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add internal attribute if we need to we don't on a refresh of the document
+ if (!node.attributes.map[internalName]) {
+ // Don't duplicate these since they won't get modified by any browser
+ if (value.indexOf('data:') === 0 || value.indexOf('blob:') === 0) {
+ continue;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Make sure we get proper html/text for the fake cE=false selection
- // Doesn't work at all on Edge since it doesn't have proper clipboardData support
- if (!e.isDefaultPrevented() && e.clipboardData && !Env.ie) {
- var realSelectionElement = getRealSelectionElement();
- if (realSelectionElement) {
- e.preventDefault();
- clipboardData.clearData();
- clipboardData.setData('text/html', realSelectionElement.outerHTML);
- clipboardData.setData('text/plain', realSelectionElement.outerText);
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (name === "style") {
+ value = dom.serializeStyle(dom.parseStyle(value), node.name);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DragDropOverrides.init(editor);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!value.length) {
+ value = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function addCss() {
- var styles = editor.contentStyles, rootClass = '.mce-content-body';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node.attr(internalName, value);
+ node.attr(name, value);
+ } else if (name === "tabindex") {
+ node.attr(internalName, value);
+ node.attr(name, null);
+ } else {
+ node.attr(internalName, editor.convertURL(value, name, node.name));
+ }
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- styles.push(fakeCaret.getCss());
- styles.push(
- rootClass + ' .mce-offscreen-selection {' +
- 'position: absolute;' +
- 'left: -9999999999px;' +
- 'max-width: 1000000px;' +
- '}' +
- rootClass + ' *[contentEditable=false] {' +
- 'cursor: default;' +
- '}' +
- rootClass + ' *[contentEditable=true] {' +
- 'cursor: text;' +
- '}'
- );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Keep scripts from executing
+ parser.addNodeFilter('script', function (nodes) {
+ var i = nodes.length, node, type;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isRangeInCaretContainer(rng) {
- return CaretContainer.isCaretContainer(rng.startContainer) || CaretContainer.isCaretContainer(rng.endContainer);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i];
+ type = node.attr('type') || 'no/type';
+ if (type.indexOf('mce-') !== 0) {
+ node.attr('type', 'mce-' + type);
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setContentEditableSelection(range) {
- var node, $ = editor.$, dom = editor.dom, $realSelectionContainer, sel,
- startContainer, startOffset, endOffset, e, caretPosition, targetClone, origTargetClone;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parser.addNodeFilter('#cdata', function (nodes) {
+ var i = nodes.length, node;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!range) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i];
+ node.type = 8;
+ node.name = '#comment';
+ node.value = '[CDATA[' + node.value + ']]';
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (range.collapsed) {
- if (!isRangeInCaretContainer(range)) {
- caretPosition = getNormalizedRangeEndPoint(1, range);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parser.addNodeFilter('p,h1,h2,h3,h4,h5,h6,div', function (nodes) {
+ var i = nodes.length, node, nonEmptyElements = editor.schema.getNonEmptyElements();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isContentEditableFalse(caretPosition.getNode())) {
- return showCaret(1, caretPosition.getNode(), !caretPosition.isAtEnd());
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ node = nodes[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isContentEditableFalse(caretPosition.getNode(true))) {
- return showCaret(1, caretPosition.getNode(true), false);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (node.isEmpty(nonEmptyElements) && node.getAll('br').length === 0) {
+ node.append(new Node('br', 1)).shortEnded = true;
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return parser;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- startContainer = range.startContainer;
- startOffset = range.startOffset;
- endOffset = range.endOffset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var autoFocus = function (editor) {
+ if (editor.settings.auto_focus) {
+ Delay.setEditorTimeout(editor, function () {
+ var focusEditor;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Normalizes <span cE=false>[</span>] to [<span cE=false></span>]
- if (startContainer.nodeType == 3 && startOffset == 0 && isContentEditableFalse(startContainer.parentNode)) {
- startContainer = startContainer.parentNode;
- startOffset = dom.nodeIndex(startContainer);
- startContainer = startContainer.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.settings.auto_focus === true) {
+ focusEditor = editor;
+ } else {
+ focusEditor = editor.editorManager.get(editor.settings.auto_focus);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (startContainer.nodeType != 1) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!focusEditor.destroyed) {
+ focusEditor.focus();
+ }
+ }, 100);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (endOffset == startOffset + 1) {
- node = startContainer.childNodes[startOffset];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var initEditor = function (editor) {
+ editor.bindPendingEventDelegates();
+ editor.initialized = true;
+ editor.fire('init');
+ editor.focus(true);
+ editor.nodeChanged({ initial: true });
+ editor.execCallback('init_instance_callback', editor);
+ autoFocus(editor);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!isContentEditableFalse(node)) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var initContentBody = function (editor, skipWrite) {
+ var settings = editor.settings, targetElm = editor.getElement(), doc = editor.getDoc(), body, contentCssText;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- targetClone = origTargetClone = node.cloneNode(true);
- e = editor.fire('ObjectSelected', {target: node, targetClone: targetClone});
- if (e.isDefaultPrevented()) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Restore visibility on target element
+ if (!settings.inline) {
+ editor.getElement().style.visibility = editor.orgVisibility;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- targetClone = e.targetClone;
- $realSelectionContainer = $('#' + realSelectionId);
- if ($realSelectionContainer.length === 0) {
- $realSelectionContainer = $(
- '<div data-mce-bogus="all" class="mce-offscreen-selection"></div>'
- ).attr('id', realSelectionId);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup iframe body
+ if (!skipWrite && !settings.content_editable) {
+ doc.open();
+ doc.write(editor.iframeHTML);
+ doc.close();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $realSelectionContainer.appendTo(editor.getBody());
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.content_editable) {
+ editor.on('remove', function () {
+ var bodyEl = this.getBody();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- range = editor.dom.createRng();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOM.removeClass(bodyEl, 'mce-content-body');
+ DOM.removeClass(bodyEl, 'mce-edit-focus');
+ DOM.setAttrib(bodyEl, 'contentEditable', null);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // WHY is IE making things so hard! Copy on <i contentEditable="false">x</i> produces: <em>x</em>
- // This is a ridiculous hack where we place the selection from a block over the inline element
- // so that just the inline element is copied as is and not converted.
- if (targetClone === origTargetClone && Env.ie) {
- $realSelectionContainer.empty().append('<p style="font-size: 0" data-mce-bogus="all">\u00a0</p>').append(targetClone);
- range.setStartAfter($realSelectionContainer[0].firstChild.firstChild);
- range.setEndAfter(targetClone);
- } else {
- $realSelectionContainer.empty().append('\u00a0').append(targetClone).append('\u00a0');
- range.setStart($realSelectionContainer[0].firstChild, 1);
- range.setEnd($realSelectionContainer[0].lastChild, 0);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOM.addClass(targetElm, 'mce-content-body');
+ editor.contentDocument = doc = settings.content_document || document;
+ editor.contentWindow = settings.content_window || window;
+ editor.bodyElement = targetElm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $realSelectionContainer.css({
- top: dom.getPos(node, editor.getBody()).y
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Prevent leak in IE
+ settings.content_document = settings.content_window = null;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $realSelectionContainer[0].focus();
- sel = editor.selection.getSel();
- sel.removeAllRanges();
- sel.addRange(range);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // TODO: Fix this
+ settings.root_name = targetElm.nodeName.toLowerCase();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.$('*[data-mce-selected]').removeAttr('data-mce-selected');
- node.setAttribute('data-mce-selected', 1);
- selectedContentEditableNode = node;
- hideFakeCaret();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // It will not steal focus while setting contentEditable
+ body = editor.getBody();
+ body.disabled = true;
+ editor.readonly = settings.readonly;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return range;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!editor.readonly) {
+ if (editor.inline && DOM.getStyle(body, 'position', true) === 'static') {
+ body.style.position = 'relative';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function removeContentEditableSelection() {
- if (selectedContentEditableNode) {
- selectedContentEditableNode.removeAttribute('data-mce-selected');
- editor.$('#' + realSelectionId).remove();
- selectedContentEditableNode = null;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ body.contentEditable = editor.getParam('content_editable_state', true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function destroy() {
- fakeCaret.destroy();
- selectedContentEditableNode = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ body.disabled = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hideFakeCaret() {
- fakeCaret.hide();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.editorUpload = new EditorUpload(editor);
+ editor.schema = new Schema(settings);
+ editor.dom = new DOMUtils(doc, {
+ keep_values: true,
+ url_converter: editor.convertURL,
+ url_converter_scope: editor,
+ hex_colors: settings.force_hex_style_colors,
+ class_filter: settings.class_filter,
+ update_styles: true,
+ root_element: editor.inline ? editor.getBody() : null,
+ collect: settings.content_editable,
+ schema: editor.schema,
+ onSetAttrib: function (e) {
+ editor.fire('SetAttrib', e);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (Env.ceFalse) {
- registerEvents();
- addCss();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.parser = createParser(editor);
+ editor.serializer = new Serializer(settings, editor);
+ editor.selection = new Selection(editor.dom, editor.getWin(), editor.serializer, editor);
+ editor.formatter = new Formatter(editor);
+ editor.undoManager = new UndoManager(editor);
+ editor._nodeChangeDispatcher = new NodeChange(editor);
+ editor._selectionOverrides = new SelectionOverrides(editor);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- showBlockCaretContainer: showBlockCaretContainer,
- hideFakeCaret: hideFakeCaret,
- destroy: destroy
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ CaretContainerInput.setup(editor);
+ KeyboardOverrides.setup(editor);
+ ForceBlocks.setup(editor);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return SelectionOverrides;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.fire('PreInit');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/util/Uuid.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!settings.browser_spellcheck && !settings.gecko_spellcheck) {
+ doc.body.spellcheck = false; // Gecko
+ DOM.setAttrib(body, "spellcheck", "false");
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Uuid.js
- *
- * Released under LGPL License.
- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.quirks = new Quirks(editor);
+ editor.fire('PostRender');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Generates unique ids.
- *
- * @class tinymce.util.Uuid
- * @private
- */
-define("tinymce/util/Uuid", [
-], function() {
- var count = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.directionality) {
+ body.dir = settings.directionality;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var seed = function () {
- var rnd = function () {
- return Math.round(Math.random() * 0xFFFFFFFF).toString(36);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.nowrap) {
+ body.style.whiteSpace = "nowrap";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var now = new Date().getTime();
- return 's' + now.toString(36) + rnd() + rnd() + rnd();
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.protect) {
+ editor.on('BeforeSetContent', function (e) {
+ Tools.each(settings.protect, function (pattern) {
+ e.content = e.content.replace(pattern, function (str) {
+ return '<!--mce:protected ' + escape(str) + '-->';
+ });
+ });
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var uuid = function (prefix) {
- return prefix + (count++) + seed();
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('SetContent', function () {
+ editor.addVisual(editor.getBody());
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- uuid: uuid
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove empty contents
+ if (settings.padd_empty_editor) {
+ editor.on('PostProcess', function (e) {
+ e.content = e.content.replace(/^(<p[^>]*>( | |\s|\u00a0|<br \/>|)<\/p>[\r\n]*|<br \/>[\r\n]*)$/, '');
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/Sidebar.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.load({ initial: true, format: 'html' });
+ editor.startContent = editor.getContent({ format: 'raw' });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('compositionstart compositionend', function (e) {
+ editor.composing = e.type === 'compositionstart';
+ });
+
+ // Add editor specific CSS styles
+ if (editor.contentStyles.length > 0) {
+ contentCssText = '';
+
+ Tools.each(editor.contentStyles, function (style) {
+ contentCssText += style + "\r\n";
+ });
+
+ editor.dom.addStyle(contentCssText);
+ }
+
+ editor.dom.styleSheetLoader.loadAll(
+ editor.contentCSS,
+ function (_) {
+ initEditor(editor);
+ },
+ function (urls) {
+ initEditor(editor);
+ ErrorReporter.contentCssError(editor, urls);
+ }
+ );
+ };
+
+ return {
+ initContentBody: initContentBody
+ };
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Sidebar.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * PluginManager.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * This module handle sidebar instances for the editor.
- *
- * @class tinymce.ui.Sidebar
- * @private
- */
-define("tinymce/ui/Sidebar", [
-], function(
-) {
- var add = function (editor, name, settings) {
- var sidebars = editor.sidebars ? editor.sidebars : [];
- sidebars.push({name: name, settings: settings});
- editor.sidebars = sidebars;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.PluginManager',
+ [
+ 'tinymce.core.AddOnManager'
+ ],
+ function (AddOnManager) {
+ return AddOnManager.PluginManager;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- add: add
- };
-});
-
-// Included from: js/tinymce/classes/Editor.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Editor.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * ThemeManager.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/*jshint scripturl:true */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ThemeManager',
+ [
+ 'tinymce.core.AddOnManager'
+ ],
+ function (AddOnManager) {
+ return AddOnManager.ThemeManager;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Include the base event class documentation.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Init.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @include ../../../tools/docs/tinymce.Event.js
- */
-
-/**
- * This class contains the core logic for a TinyMCE editor.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @class tinymce.Editor
- * @mixes tinymce.util.Observable
- * @example
- * // Add a class to all paragraphs in the editor.
- * tinymce.activeEditor.dom.addClass(tinymce.activeEditor.dom.select('p'), 'someclass');
- *
- * // Gets the current editors selection as text
- * tinymce.activeEditor.selection.getContent({format: 'text'});
- *
- * // Creates a new editor instance
- * var ed = new tinymce.Editor('textareaid', {
- * some_setting: 1
- * }, tinymce.EditorManager);
- *
- * // Select each item the user clicks on
- * ed.on('click', function(e) {
- * ed.selection.select(e.target);
- * });
- *
- * ed.render();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/Editor", [
- "tinymce/dom/DOMUtils",
- "tinymce/dom/DomQuery",
- "tinymce/AddOnManager",
- "tinymce/NodeChange",
- "tinymce/html/Node",
- "tinymce/dom/Serializer",
- "tinymce/html/Serializer",
- "tinymce/dom/Selection",
- "tinymce/Formatter",
- "tinymce/UndoManager",
- "tinymce/EnterKey",
- "tinymce/ForceBlocks",
- "tinymce/EditorCommands",
- "tinymce/util/URI",
- "tinymce/dom/ScriptLoader",
- "tinymce/dom/EventUtils",
- "tinymce/WindowManager",
- "tinymce/NotificationManager",
- "tinymce/html/Schema",
- "tinymce/html/DomParser",
- "tinymce/util/Quirks",
- "tinymce/Env",
- "tinymce/util/Tools",
- "tinymce/util/Delay",
- "tinymce/EditorObservable",
- "tinymce/Mode",
- "tinymce/Shortcuts",
- "tinymce/EditorUpload",
- "tinymce/SelectionOverrides",
- "tinymce/util/Uuid",
- "tinymce/ui/Sidebar",
- "tinymce/ErrorReporter"
-], function(
- DOMUtils, DomQuery, AddOnManager, NodeChange, Node, DomSerializer, Serializer,
- Selection, Formatter, UndoManager, EnterKey, ForceBlocks, EditorCommands,
- URI, ScriptLoader, EventUtils, WindowManager, NotificationManager,
- Schema, DomParser, Quirks, Env, Tools, Delay, EditorObservable, Mode, Shortcuts, EditorUpload,
- SelectionOverrides, Uuid, Sidebar, ErrorReporter
-) {
- // Shorten these names
- var DOM = DOMUtils.DOM, ThemeManager = AddOnManager.ThemeManager, PluginManager = AddOnManager.PluginManager;
- var extend = Tools.extend, each = Tools.each, explode = Tools.explode;
- var inArray = Tools.inArray, trim = Tools.trim, resolve = Tools.resolve;
- var Event = EventUtils.Event;
- var isGecko = Env.gecko, ie = Env.ie;
</del><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Include documentation for all the events.
- *
- * @include ../../../tools/docs/tinymce.Editor.js
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.init.Init',
+ [
+ 'global!document',
+ 'global!window',
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.core.Env',
+ 'tinymce.core.init.InitContentBody',
+ 'tinymce.core.PluginManager',
+ 'tinymce.core.ThemeManager',
+ 'tinymce.core.util.Tools',
+ 'tinymce.core.util.Uuid'
+ ],
+ function (document, window, DOMUtils, Env, InitContentBody, PluginManager, ThemeManager, Tools, Uuid) {
+ var DOM = DOMUtils.DOM;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a editor instance by id.
- *
- * @constructor
- * @method Editor
- * @param {String} id Unique id for the editor.
- * @param {Object} settings Settings for the editor.
- * @param {tinymce.EditorManager} editorManager EditorManager instance.
- */
- function Editor(id, settings, editorManager) {
- var self = this, documentBaseUrl, baseUri, defaultSettings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var initPlugin = function (editor, initializedPlugins, plugin) {
+ var Plugin = PluginManager.get(plugin), pluginUrl, pluginInstance;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- documentBaseUrl = self.documentBaseUrl = editorManager.documentBaseURL;
- baseUri = editorManager.baseURI;
- defaultSettings = editorManager.defaultSettings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ pluginUrl = PluginManager.urls[plugin] || editor.documentBaseUrl.replace(/\/$/, '');
+ plugin = Tools.trim(plugin);
+ if (Plugin && Tools.inArray(initializedPlugins, plugin) === -1) {
+ Tools.each(PluginManager.dependencies(plugin), function (dep) {
+ initPlugin(editor, initializedPlugins, dep);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Name/value collection with editor settings.
- *
- * @property settings
- * @type Object
- * @example
- * // Get the value of the theme setting
- * tinymce.activeEditor.windowManager.alert("You are using the " + tinymce.activeEditor.settings.theme + " theme");
- */
- settings = extend({
- id: id,
- theme: 'modern',
- delta_width: 0,
- delta_height: 0,
- popup_css: '',
- plugins: '',
- document_base_url: documentBaseUrl,
- add_form_submit_trigger: true,
- submit_patch: true,
- add_unload_trigger: true,
- convert_urls: true,
- relative_urls: true,
- remove_script_host: true,
- object_resizing: true,
- doctype: '<!DOCTYPE html>',
- visual: true,
- font_size_style_values: 'xx-small,x-small,small,medium,large,x-large,xx-large',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.plugins[plugin]) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // See: http://www.w3.org/TR/CSS2/fonts.html#propdef-font-size
- font_size_legacy_values: 'xx-small,small,medium,large,x-large,xx-large,300%',
- forced_root_block: 'p',
- hidden_input: true,
- padd_empty_editor: true,
- render_ui: true,
- indentation: '30px',
- inline_styles: true,
- convert_fonts_to_spans: true,
- indent: 'simple',
- indent_before: 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead,' +
- 'tfoot,tbody,tr,section,article,hgroup,aside,figure,figcaption,option,optgroup,datalist',
- indent_after: 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead,' +
- 'tfoot,tbody,tr,section,article,hgroup,aside,figure,figcaption,option,optgroup,datalist',
- validate: true,
- entity_encoding: 'named',
- url_converter: self.convertURL,
- url_converter_scope: self,
- ie7_compat: true
- }, defaultSettings, settings);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ pluginInstance = new Plugin(editor, pluginUrl, editor.$);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Merge external_plugins
- if (defaultSettings && defaultSettings.external_plugins && settings.external_plugins) {
- settings.external_plugins = extend({}, defaultSettings.external_plugins, settings.external_plugins);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.plugins[plugin] = pluginInstance;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.settings = settings;
- AddOnManager.language = settings.language || 'en';
- AddOnManager.languageLoad = settings.language_load;
- AddOnManager.baseURL = editorManager.baseURL;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (pluginInstance.init) {
+ pluginInstance.init(editor, pluginUrl);
+ initializedPlugins.push(plugin);
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Editor instance id, normally the same as the div/textarea that was replaced.
- *
- * @property id
- * @type String
- */
- self.id = settings.id = id;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var initPlugins = function (editor) {
+ var initializedPlugins = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * State to force the editor to return false on a isDirty call.
- *
- * @property isNotDirty
- * @type Boolean
- * @deprecated Use editor.setDirty instead.
- */
- self.setDirty(false);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(editor.settings.plugins.replace(/\-/g, '').split(/[ ,]/), function (name) {
+ initPlugin(editor, initializedPlugins, name);
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Name/Value object containing plugin instances.
- *
- * @property plugins
- * @type Object
- * @example
- * // Execute a method inside a plugin directly
- * tinymce.activeEditor.plugins.someplugin.someMethod();
- */
- self.plugins = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var initTheme = function (editor) {
+ var Theme, settings = editor.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * URI object to document configured for the TinyMCE instance.
- *
- * @property documentBaseURI
- * @type tinymce.util.URI
- * @example
- * // Get relative URL from the location of document_base_url
- * tinymce.activeEditor.documentBaseURI.toRelative('/somedir/somefile.htm');
- *
- * // Get absolute URL from the location of document_base_url
- * tinymce.activeEditor.documentBaseURI.toAbsolute('somefile.htm');
- */
- self.documentBaseURI = new URI(settings.document_base_url || documentBaseUrl, {
- base_uri: baseUri
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.theme) {
+ if (typeof settings.theme != "function") {
+ settings.theme = settings.theme.replace(/-/, '');
+ Theme = ThemeManager.get(settings.theme);
+ editor.theme = new Theme(editor, ThemeManager.urls[settings.theme]);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * URI object to current document that holds the TinyMCE editor instance.
- *
- * @property baseURI
- * @type tinymce.util.URI
- * @example
- * // Get relative URL from the location of the API
- * tinymce.activeEditor.baseURI.toRelative('/somedir/somefile.htm');
- *
- * // Get absolute URL from the location of the API
- * tinymce.activeEditor.baseURI.toAbsolute('somefile.htm');
- */
- self.baseURI = baseUri;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.theme.init) {
+ editor.theme.init(editor, ThemeManager.urls[settings.theme] || editor.documentBaseUrl.replace(/\/$/, ''), editor.$);
+ }
+ } else {
+ editor.theme = settings.theme;
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Array with CSS files to load into the iframe.
- *
- * @property contentCSS
- * @type Array
- */
- self.contentCSS = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var measueBox = function (editor) {
+ var w, h, minHeight, re, o, settings = editor.settings, elm = editor.getElement();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Array of CSS styles to add to head of document when the editor loads.
- *
- * @property contentStyles
- * @type Array
- */
- self.contentStyles = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Measure box
+ if (settings.render_ui && editor.theme) {
+ editor.orgDisplay = elm.style.display;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Creates all events like onClick, onSetContent etc see Editor.Events.js for the actual logic
- self.shortcuts = new Shortcuts(self);
- self.loadedCSS = {};
- self.editorCommands = new EditorCommands(self);
- self.suffix = editorManager.suffix;
- self.editorManager = editorManager;
- self.inline = settings.inline;
- self.settings.content_editable = self.inline;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof settings.theme != "function") {
+ w = settings.width || DOM.getStyle(elm, 'width') || '100%';
+ h = settings.height || DOM.getStyle(elm, 'height') || elm.offsetHeight;
+ minHeight = settings.min_height || 100;
+ re = /^[0-9\.]+(|px)$/i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.cache_suffix) {
- Env.cacheSuffix = settings.cache_suffix.replace(/^[\?\&]+/, '');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (re.test('' + w)) {
+ w = Math.max(parseInt(w, 10), 100);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.override_viewport === false) {
- Env.overrideViewPort = false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (re.test('' + h)) {
+ h = Math.max(parseInt(h, 10), minHeight);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Call setup
- editorManager.fire('SetupEditor', self);
- self.execCallback('setup', self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Render UI
+ o = editor.theme.renderUI({
+ targetNode: elm,
+ width: w,
+ height: h,
+ deltaWidth: settings.delta_width,
+ deltaHeight: settings.delta_height
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Dom query instance with default scope to the editor document and default element is the body of the editor.
- *
- * @property $
- * @type tinymce.dom.DomQuery
- * @example
- * tinymce.activeEditor.$('p').css('color', 'red');
- * tinymce.activeEditor.$().append('<p>new</p>');
- */
- self.$ = DomQuery.overrideDefaults(function() {
- return {
- context: self.inline ? self.getBody() : self.getDoc(),
- element: self.getBody()
- };
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Resize editor
+ if (!settings.content_editable) {
+ h = (o.iframeHeight || h) + (typeof h === 'number' ? (o.deltaHeight || 0) : '');
+ if (h < minHeight) {
+ h = minHeight;
+ }
+ }
+ } else {
+ o = settings.theme(editor, elm);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Editor.prototype = {
- /**
- * Renders the editor/adds it to the page.
- *
- * @method render
- */
- render: function() {
- var self = this, settings = self.settings, id = self.id, suffix = self.suffix;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (o.editorContainer.nodeType) {
+ o.editorContainer.id = o.editorContainer.id || editor.id + "_parent";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function readyHandler() {
- DOM.unbind(window, 'ready', readyHandler);
- self.render();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (o.iframeContainer.nodeType) {
+ o.iframeContainer.id = o.iframeContainer.id || editor.id + "_iframecontainer";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Page is not loaded yet, wait for it
- if (!Event.domLoaded) {
- DOM.bind(window, 'ready', readyHandler);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Use specified iframe height or the targets offsetHeight
+ h = o.iframeHeight || elm.offsetHeight;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Element not found, then skip initialization
- if (!self.getElement()) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.editorContainer = o.editorContainer;
+ o.height = h;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // No editable support old iOS versions etc
- if (!Env.contentEditable) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return o;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Hide target element early to prevent content flashing
- if (!settings.inline) {
- self.orgVisibility = self.getElement().style.visibility;
- self.getElement().style.visibility = 'hidden';
- } else {
- self.inline = true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createIframe = function (editor, o) {
+ var settings = editor.settings, bodyId, bodyClass, url;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var form = self.getElement().form || DOM.getParent(id, 'form');
- if (form) {
- self.formElement = form;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.iframeHTML = settings.doctype + '<html><head>';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add hidden input for non input elements inside form elements
- if (settings.hidden_input && !/TEXTAREA|INPUT/i.test(self.getElement().nodeName)) {
- DOM.insertAfter(DOM.create('input', {type: 'hidden', name: id}), id);
- self.hasHiddenInput = true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // We only need to override paths if we have to
+ // IE has a bug where it remove site absolute urls to relative ones if this is specified
+ if (settings.document_base_url != editor.documentBaseUrl) {
+ editor.iframeHTML += '<base href="' + editor.documentBaseURI.getURI() + '" />';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Pass submit/reset from form to editor instance
- self.formEventDelegate = function(e) {
- self.fire(e.type, e);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // IE8 doesn't support carets behind images setting ie7_compat would force IE8+ to run in IE7 compat mode.
+ if (!Env.caretAfter && settings.ie7_compat) {
+ editor.iframeHTML += '<meta http-equiv="X-UA-Compatible" content="IE=7" />';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DOM.bind(form, 'submit reset', self.formEventDelegate);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.iframeHTML += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Reset contents in editor when the form is reset
- self.on('reset', function() {
- self.setContent(self.startContent, {format: 'raw'});
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bodyId = settings.body_id || 'tinymce';
+ if (bodyId.indexOf('=') != -1) {
+ bodyId = editor.getParam('body_id', '', 'hash');
+ bodyId = bodyId[editor.id] || bodyId;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check page uses id="submit" or name="submit" for it's submit button
- if (settings.submit_patch && !form.submit.nodeType && !form.submit.length && !form._mceOldSubmit) {
- form._mceOldSubmit = form.submit;
- form.submit = function() {
- self.editorManager.triggerSave();
- self.setDirty(false);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bodyClass = settings.body_class || '';
+ if (bodyClass.indexOf('=') != -1) {
+ bodyClass = editor.getParam('body_class', '', 'hash');
+ bodyClass = bodyClass[editor.id] || '';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return form._mceOldSubmit(form);
- };
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.content_security_policy) {
+ editor.iframeHTML += '<meta http-equiv="Content-Security-Policy" content="' + settings.content_security_policy + '" />';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Window manager reference, use this to open new windows and dialogs.
- *
- * @property windowManager
- * @type tinymce.WindowManager
- * @example
- * // Shows an alert message
- * tinymce.activeEditor.windowManager.alert('Hello world!');
- *
- * // Opens a new dialog with the file.htm file and the size 320x240
- * // It also adds a custom parameter this can be retrieved by using tinyMCEPopup.getWindowArg inside the dialog.
- * tinymce.activeEditor.windowManager.open({
- * url: 'file.htm',
- * width: 320,
- * height: 240
- * }, {
- * custom_param: 1
- * });
- */
- self.windowManager = new WindowManager(self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.iframeHTML += '</head><body id="' + bodyId +
+ '" class="mce-content-body ' + bodyClass +
+ '" data-id="' + editor.id + '"><br></body></html>';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Notification manager reference, use this to open new windows and dialogs.
- *
- * @property notificationManager
- * @type tinymce.NotificationManager
- * @example
- * // Shows a notification info message.
- * tinymce.activeEditor.notificationManager.open({text: 'Hello world!', type: 'info'});
- */
- self.notificationManager = new NotificationManager(self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var bodyUuid = Uuid.uuid('mce');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.encoding == 'xml') {
- self.on('GetContent', function(e) {
- if (e.save) {
- e.content = DOM.encode(e.content);
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor[bodyUuid] = function () {
+ InitContentBody.initContentBody(editor);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.add_form_submit_trigger) {
- self.on('submit', function() {
- if (self.initialized) {
- self.save();
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /*eslint no-script-url:0 */
+ var domainRelaxUrl = 'javascript:(function(){' +
+ 'document.open();document.domain="' + document.domain + '";' +
+ 'var ed = window.parent.tinymce.get("' + editor.id + '");document.write(ed.iframeHTML);' +
+ 'document.close();ed.' + bodyUuid + '(true);})()';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.add_unload_trigger) {
- self._beforeUnload = function() {
- if (self.initialized && !self.destroyed && !self.isHidden()) {
- self.save({format: 'raw', no_events: true, set_dirty: false});
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Domain relaxing is required since the user has messed around with document.domain
+ if (document.domain != window.location.hostname) {
+ // Edge seems to be able to handle domain relaxing
+ if (Env.ie && Env.ie < 12) {
+ url = domainRelaxUrl;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.editorManager.on('BeforeUnload', self._beforeUnload);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Create iframe
+ // TODO: ACC add the appropriate description on this.
+ var ifr = DOM.create('iframe', {
+ id: editor.id + "_ifr",
+ //src: url || 'javascript:""', // Workaround for HTTPS warning in IE6/7
+ frameBorder: '0',
+ allowTransparency: "true",
+ title: editor.editorManager.translate(
+ "Rich Text Area. Press ALT-F9 for menu. " +
+ "Press ALT-F10 for toolbar. Press ALT-0 for help"
+ ),
+ style: {
+ width: '100%',
+ height: o.height,
+ display: 'block' // Important for Gecko to render the iframe correctly
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Load scripts
- function loadScripts() {
- var scriptLoader = ScriptLoader.ScriptLoader;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ifr.onload = function () {
+ ifr.onload = null;
+ editor.fire("load");
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.language && settings.language != 'en' && !settings.language_url) {
- settings.language_url = self.editorManager.baseURL + '/langs/' + settings.language + '.js';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOM.setAttrib(ifr, "src", url || 'javascript:""');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.language_url) {
- scriptLoader.add(settings.language_url);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.contentAreaContainer = o.iframeContainer;
+ editor.iframeElement = ifr;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.theme && typeof settings.theme != "function" &&
- settings.theme.charAt(0) != '-' && !ThemeManager.urls[settings.theme]) {
- var themeUrl = settings.theme_url;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOM.add(o.iframeContainer, ifr);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (themeUrl) {
- themeUrl = self.documentBaseURI.toAbsolute(themeUrl);
- } else {
- themeUrl = 'themes/' + settings.theme + '/theme' + suffix + '.js';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Try accessing the document this will fail on IE when document.domain is set to the same as location.hostname
+ // Then we have to force domain relaxing using the domainRelaxUrl approach very ugly!!
+ if (Env.ie) {
+ try {
+ editor.getDoc();
+ } catch (e) {
+ ifr.src = url = domainRelaxUrl;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ThemeManager.load(settings.theme, themeUrl);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return url;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (Tools.isArray(settings.plugins)) {
- settings.plugins = settings.plugins.join(' ');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var init = function (editor) {
+ var settings = editor.settings, elm = editor.getElement();
+ var boxInfo, url;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(settings.external_plugins, function(url, name) {
- PluginManager.load(name, url);
- settings.plugins += ' ' + name;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.rtl = settings.rtl_ui || editor.editorManager.i18n.rtl;
+ editor.editorManager.i18n.setCode(settings.language);
+ settings.aria_label = settings.aria_label || DOM.getAttrib(elm, 'aria-label', editor.getLang('aria.rich_text_area'));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(settings.plugins.split(/[ ,]/), function(plugin) {
- plugin = trim(plugin);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.fire('ScriptsLoaded');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (plugin && !PluginManager.urls[plugin]) {
- if (plugin.charAt(0) == '-') {
- plugin = plugin.substr(1, plugin.length);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ initTheme(editor);
+ initPlugins(editor);
+ boxInfo = measueBox(editor);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var dependencies = PluginManager.dependencies(plugin);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Load specified content CSS last
+ if (settings.content_css) {
+ Tools.each(Tools.explode(settings.content_css), function (u) {
+ editor.contentCSS.push(editor.documentBaseURI.toAbsolute(u));
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(dependencies, function(dep) {
- var defaultSettings = {
- prefix: 'plugins/',
- resource: dep,
- suffix: '/plugin' + suffix + '.js'
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Load specified content CSS last
+ if (settings.content_style) {
+ editor.contentStyles.push(settings.content_style);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dep = PluginManager.createUrl(defaultSettings, dep);
- PluginManager.load(dep.resource, dep);
- });
- } else {
- PluginManager.load(plugin, {
- prefix: 'plugins/',
- resource: plugin,
- suffix: '/plugin' + suffix + '.js'
- });
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Content editable mode ends here
+ if (settings.content_editable) {
+ return InitContentBody.initContentBody(editor);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- scriptLoader.loadQueue(function() {
- if (!self.removed) {
- self.init();
- }
- }, self, function (urls) {
- ErrorReporter.pluginLoadError(self, urls[0]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ url = createIframe(editor, boxInfo);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.removed) {
- self.init();
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (boxInfo.editorContainer) {
+ DOM.get(boxInfo.editorContainer).style.display = editor.orgDisplay;
+ editor.hidden = DOM.isHidden(boxInfo.editorContainer);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.editorManager.add(self);
- loadScripts();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.getElement().style.display = 'none';
+ DOM.setAttrib(editor.id, 'aria-hidden', true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Initializes the editor this will be called automatically when
- * all plugins/themes and language packs are loaded by the rendered method.
- * This method will setup the iframe and create the theme and plugin instances.
- *
- * @method init
- */
- init: function() {
- var self = this, settings = self.settings, elm = self.getElement();
- var w, h, minHeight, n, o, Theme, url, bodyId, bodyClass, re, i, initializedPlugins = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!url) {
+ InitContentBody.initContentBody(editor);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.rtl = settings.rtl_ui || self.editorManager.i18n.rtl;
- self.editorManager.i18n.setCode(settings.language);
- settings.aria_label = settings.aria_label || DOM.getAttrib(elm, 'aria-label', self.getLang('aria.rich_text_area'));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ init: init
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.fire('ScriptsLoaded');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Render.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Reference to the theme instance that was used to generate the UI.
- *
- * @property theme
- * @type tinymce.Theme
- * @example
- * // Executes a method on the theme directly
- * tinymce.activeEditor.theme.someMethod();
- */
- if (settings.theme) {
- if (typeof settings.theme != "function") {
- settings.theme = settings.theme.replace(/-/, '');
- Theme = ThemeManager.get(settings.theme);
- self.theme = new Theme(self, ThemeManager.urls[settings.theme]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.init.Render',
+ [
+ 'global!window',
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.core.dom.EventUtils',
+ 'tinymce.core.dom.ScriptLoader',
+ 'tinymce.core.Env',
+ 'tinymce.core.ErrorReporter',
+ 'tinymce.core.init.Init',
+ 'tinymce.core.NotificationManager',
+ 'tinymce.core.PluginManager',
+ 'tinymce.core.ThemeManager',
+ 'tinymce.core.util.Tools',
+ 'tinymce.core.WindowManager'
+ ],
+ function (window, DOMUtils, EventUtils, ScriptLoader, Env, ErrorReporter, Init, NotificationManager, PluginManager, ThemeManager, Tools, WindowManager) {
+ var DOM = DOMUtils.DOM;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.theme.init) {
- self.theme.init(self, ThemeManager.urls[settings.theme] || self.documentBaseUrl.replace(/\/$/, ''), self.$);
- }
- } else {
- self.theme = settings.theme;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var loadScripts = function (editor, suffix) {
+ var settings = editor.settings, scriptLoader = ScriptLoader.ScriptLoader;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function initPlugin(plugin) {
- var Plugin = PluginManager.get(plugin), pluginUrl, pluginInstance;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.language && settings.language != 'en' && !settings.language_url) {
+ settings.language_url = editor.editorManager.baseURL + '/langs/' + settings.language + '.js';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- pluginUrl = PluginManager.urls[plugin] || self.documentBaseUrl.replace(/\/$/, '');
- plugin = trim(plugin);
- if (Plugin && inArray(initializedPlugins, plugin) === -1) {
- each(PluginManager.dependencies(plugin), function(dep) {
- initPlugin(dep);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.language_url) {
+ scriptLoader.add(settings.language_url);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.plugins[plugin]) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.theme && typeof settings.theme != "function" &&
+ settings.theme.charAt(0) != '-' && !ThemeManager.urls[settings.theme]) {
+ var themeUrl = settings.theme_url;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- pluginInstance = new Plugin(self, pluginUrl, self.$);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (themeUrl) {
+ themeUrl = editor.documentBaseURI.toAbsolute(themeUrl);
+ } else {
+ themeUrl = 'themes/' + settings.theme + '/theme' + suffix + '.js';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.plugins[plugin] = pluginInstance;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ThemeManager.load(settings.theme, themeUrl);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (pluginInstance.init) {
- pluginInstance.init(self, pluginUrl);
- initializedPlugins.push(plugin);
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (Tools.isArray(settings.plugins)) {
+ settings.plugins = settings.plugins.join(' ');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Create all plugins
- each(settings.plugins.replace(/\-/g, '').split(/[ ,]/), initPlugin);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(settings.external_plugins, function (url, name) {
+ PluginManager.load(name, url);
+ settings.plugins += ' ' + name;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Measure box
- if (settings.render_ui && self.theme) {
- self.orgDisplay = elm.style.display;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(settings.plugins.split(/[ ,]/), function (plugin) {
+ plugin = Tools.trim(plugin);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof settings.theme != "function") {
- w = settings.width || elm.style.width || elm.offsetWidth;
- h = settings.height || elm.style.height || elm.offsetHeight;
- minHeight = settings.min_height || 100;
- re = /^[0-9\.]+(|px)$/i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (plugin && !PluginManager.urls[plugin]) {
+ if (plugin.charAt(0) === '-') {
+ plugin = plugin.substr(1, plugin.length);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (re.test('' + w)) {
- w = Math.max(parseInt(w, 10), 100);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var dependencies = PluginManager.dependencies(plugin);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (re.test('' + h)) {
- h = Math.max(parseInt(h, 10), minHeight);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(dependencies, function (dep) {
+ var defaultSettings = {
+ prefix: 'plugins/',
+ resource: dep,
+ suffix: '/plugin' + suffix + '.js'
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Render UI
- o = self.theme.renderUI({
- targetNode: elm,
- width: w,
- height: h,
- deltaWidth: settings.delta_width,
- deltaHeight: settings.delta_height
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dep = PluginManager.createUrl(defaultSettings, dep);
+ PluginManager.load(dep.resource, dep);
+ });
+ } else {
+ PluginManager.load(plugin, {
+ prefix: 'plugins/',
+ resource: plugin,
+ suffix: '/plugin' + suffix + '.js'
+ });
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Resize editor
- if (!settings.content_editable) {
- h = (o.iframeHeight || h) + (typeof h == 'number' ? (o.deltaHeight || 0) : '');
- if (h < minHeight) {
- h = minHeight;
- }
- }
- } else {
- o = settings.theme(self, elm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ scriptLoader.loadQueue(function () {
+ if (!editor.removed) {
+ Init.init(editor);
+ }
+ }, editor, function (urls) {
+ ErrorReporter.pluginLoadError(editor, urls[0]);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (o.editorContainer.nodeType) {
- o.editorContainer.id = o.editorContainer.id || self.id + "_parent";
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!editor.removed) {
+ Init.init(editor);
+ }
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (o.iframeContainer.nodeType) {
- o.iframeContainer.id = o.iframeContainer.id || self.id + "_iframecontainer";
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var render = function (editor) {
+ var settings = editor.settings, id = editor.id;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Use specified iframe height or the targets offsetHeight
- h = o.iframeHeight || elm.offsetHeight;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function readyHandler() {
+ DOM.unbind(window, 'ready', readyHandler);
+ editor.render();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.editorContainer = o.editorContainer;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Page is not loaded yet, wait for it
+ if (!EventUtils.Event.domLoaded) {
+ DOM.bind(window, 'ready', readyHandler);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Load specified content CSS last
- if (settings.content_css) {
- each(explode(settings.content_css), function(u) {
- self.contentCSS.push(self.documentBaseURI.toAbsolute(u));
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Element not found, then skip initialization
+ if (!editor.getElement()) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Load specified content CSS last
- if (settings.content_style) {
- self.contentStyles.push(settings.content_style);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // No editable support old iOS versions etc
+ if (!Env.contentEditable) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Content editable mode ends here
- if (settings.content_editable) {
- elm = n = o = null; // Fix IE leak
- return self.initContentBody();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Hide target element early to prevent content flashing
+ if (!settings.inline) {
+ editor.orgVisibility = editor.getElement().style.visibility;
+ editor.getElement().style.visibility = 'hidden';
+ } else {
+ editor.inline = true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.iframeHTML = settings.doctype + '<html><head>';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var form = editor.getElement().form || DOM.getParent(id, 'form');
+ if (form) {
+ editor.formElement = form;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // We only need to override paths if we have to
- // IE has a bug where it remove site absolute urls to relative ones if this is specified
- if (settings.document_base_url != self.documentBaseUrl) {
- self.iframeHTML += '<base href="' + self.documentBaseURI.getURI() + '" />';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add hidden input for non input elements inside form elements
+ if (settings.hidden_input && !/TEXTAREA|INPUT/i.test(editor.getElement().nodeName)) {
+ DOM.insertAfter(DOM.create('input', { type: 'hidden', name: id }), id);
+ editor.hasHiddenInput = true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // IE8 doesn't support carets behind images setting ie7_compat would force IE8+ to run in IE7 compat mode.
- if (!Env.caretAfter && settings.ie7_compat) {
- self.iframeHTML += '<meta http-equiv="X-UA-Compatible" content="IE=7" />';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Pass submit/reset from form to editor instance
+ editor.formEventDelegate = function (e) {
+ editor.fire(e.type, e);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.iframeHTML += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOM.bind(form, 'submit reset', editor.formEventDelegate);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Load the CSS by injecting them into the HTML this will reduce "flicker"
- // However we can't do that on Chrome since # will scroll to the editor for some odd reason see #2427
- if (!/#$/.test(document.location.href)) {
- for (i = 0; i < self.contentCSS.length; i++) {
- var cssUrl = self.contentCSS[i];
- self.iframeHTML += (
- '<link type="text/css" ' +
- 'rel="stylesheet" ' +
- 'href="' + Tools._addCacheSuffix(cssUrl) + '" />'
- );
- self.loadedCSS[cssUrl] = true;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Reset contents in editor when the form is reset
+ editor.on('reset', function () {
+ editor.setContent(editor.startContent, { format: 'raw' });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bodyId = settings.body_id || 'tinymce';
- if (bodyId.indexOf('=') != -1) {
- bodyId = self.getParam('body_id', '', 'hash');
- bodyId = bodyId[self.id] || bodyId;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check page uses id="submit" or name="submit" for it's submit button
+ if (settings.submit_patch && !form.submit.nodeType && !form.submit.length && !form._mceOldSubmit) {
+ form._mceOldSubmit = form.submit;
+ form.submit = function () {
+ editor.editorManager.triggerSave();
+ editor.setDirty(false);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bodyClass = settings.body_class || '';
- if (bodyClass.indexOf('=') != -1) {
- bodyClass = self.getParam('body_class', '', 'hash');
- bodyClass = bodyClass[self.id] || '';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return form._mceOldSubmit(form);
+ };
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.content_security_policy) {
- self.iframeHTML += '<meta http-equiv="Content-Security-Policy" content="' + settings.content_security_policy + '" />';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.windowManager = new WindowManager(editor);
+ editor.notificationManager = new NotificationManager(editor);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.iframeHTML += '</head><body id="' + bodyId +
- '" class="mce-content-body ' + bodyClass +
- '" data-id="' + self.id + '"><br></body></html>';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.encoding === 'xml') {
+ editor.on('GetContent', function (e) {
+ if (e.save) {
+ e.content = DOM.encode(e.content);
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /*eslint no-script-url:0 */
- var domainRelaxUrl = 'javascript:(function(){' +
- 'document.open();document.domain="' + document.domain + '";' +
- 'var ed = window.parent.tinymce.get("' + self.id + '");document.write(ed.iframeHTML);' +
- 'document.close();ed.initContentBody(true);})()';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.add_form_submit_trigger) {
+ editor.on('submit', function () {
+ if (editor.initialized) {
+ editor.save();
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Domain relaxing is required since the user has messed around with document.domain
- if (document.domain != location.hostname) {
- // Edge seems to be able to handle domain relaxing
- if (Env.ie && Env.ie < 12) {
- url = domainRelaxUrl;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.add_unload_trigger) {
+ editor._beforeUnload = function () {
+ if (editor.initialized && !editor.destroyed && !editor.isHidden()) {
+ editor.save({ format: 'raw', no_events: true, set_dirty: false });
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Create iframe
- // TODO: ACC add the appropriate description on this.
- var ifr = DOM.create('iframe', {
- id: self.id + "_ifr",
- //src: url || 'javascript:""', // Workaround for HTTPS warning in IE6/7
- frameBorder: '0',
- allowTransparency: "true",
- title: self.editorManager.translate(
- "Rich Text Area. Press ALT-F9 for menu. " +
- "Press ALT-F10 for toolbar. Press ALT-0 for help"
- ),
- style: {
- width: '100%',
- height: h,
- display: 'block' // Important for Gecko to render the iframe correctly
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.editorManager.on('BeforeUnload', editor._beforeUnload);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ifr.onload = function() {
- ifr.onload = null;
- self.fire("load");
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.editorManager.add(editor);
+ loadScripts(editor, editor.suffix);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DOM.setAttrib(ifr, "src", url || 'javascript:""');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ render: render
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.contentAreaContainer = o.iframeContainer;
- self.iframeElement = ifr;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Mode.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- n = DOM.add(o.iframeContainer, ifr);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Mode switcher logic.
+ *
+ * @private
+ * @class tinymce.Mode
+ */
+define(
+ 'tinymce.core.Mode',
+ [
+ ],
+ function () {
+ function setEditorCommandState(editor, cmd, state) {
+ try {
+ editor.getDoc().execCommand(cmd, false, state);
+ } catch (ex) {
+ // Ignore
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Try accessing the document this will fail on IE when document.domain is set to the same as location.hostname
- // Then we have to force domain relaxing using the domainRelaxUrl approach very ugly!!
- if (ie) {
- try {
- self.getDoc();
- } catch (e) {
- n.src = url = domainRelaxUrl;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function clickBlocker(editor) {
+ var target, handler;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (o.editorContainer) {
- DOM.get(o.editorContainer).style.display = self.orgDisplay;
- self.hidden = DOM.isHidden(o.editorContainer);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ target = editor.getBody();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.getElement().style.display = 'none';
- DOM.setAttrib(self.id, 'aria-hidden', true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ handler = function (e) {
+ if (editor.dom.getParents(e.target, 'a').length > 0) {
+ e.preventDefault();
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!url) {
- self.initContentBody();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.dom.bind(target, 'click', handler);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elm = n = o = null; // Cleanup
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ unbind: function () {
+ editor.dom.unbind(target, 'click', handler);
+ }
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * This method get called by the init method once the iframe is loaded.
- * It will fill the iframe with contents, sets up DOM and selection objects for the iframe.
- *
- * @method initContentBody
- * @private
- */
- initContentBody: function(skipWrite) {
- var self = this, settings = self.settings, targetElm = self.getElement(), doc = self.getDoc(), body, contentCssText;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function toggleReadOnly(editor, state) {
+ if (editor._clickBlocker) {
+ editor._clickBlocker.unbind();
+ editor._clickBlocker = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Restore visibility on target element
- if (!settings.inline) {
- self.getElement().style.visibility = self.orgVisibility;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (state) {
+ editor._clickBlocker = clickBlocker(editor);
+ editor.selection.controlSelection.hideResizeRect();
+ editor.readonly = true;
+ editor.getBody().contentEditable = false;
+ } else {
+ editor.readonly = false;
+ editor.getBody().contentEditable = true;
+ setEditorCommandState(editor, "StyleWithCSS", false);
+ setEditorCommandState(editor, "enableInlineTableEditing", false);
+ setEditorCommandState(editor, "enableObjectResizing", false);
+ editor.focus();
+ editor.nodeChanged();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup iframe body
- if (!skipWrite && !settings.content_editable) {
- doc.open();
- doc.write(self.iframeHTML);
- doc.close();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setMode(editor, mode) {
+ var currentMode = editor.readonly ? 'readonly' : 'design';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.content_editable) {
- self.on('remove', function() {
- var bodyEl = this.getBody();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (mode == currentMode) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DOM.removeClass(bodyEl, 'mce-content-body');
- DOM.removeClass(bodyEl, 'mce-edit-focus');
- DOM.setAttrib(bodyEl, 'contentEditable', null);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.initialized) {
+ toggleReadOnly(editor, mode == 'readonly');
+ } else {
+ editor.on('init', function () {
+ toggleReadOnly(editor, mode == 'readonly');
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DOM.addClass(targetElm, 'mce-content-body');
- self.contentDocument = doc = settings.content_document || document;
- self.contentWindow = settings.content_window || window;
- self.bodyElement = targetElm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Event is NOT preventable
+ editor.fire('SwitchMode', { mode: mode });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Prevent leak in IE
- settings.content_document = settings.content_window = null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ setMode: setMode
+ };
+ }
+);
+/**
+ * Sidebar.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // TODO: Fix this
- settings.root_name = targetElm.nodeName.toLowerCase();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * This module handle sidebar instances for the editor.
+ *
+ * @class tinymce.ui.Sidebar
+ * @private
+ */
+define(
+ 'tinymce.core.ui.Sidebar',
+ [
+ ],
+ function (
+ ) {
+ var add = function (editor, name, settings) {
+ var sidebars = editor.sidebars ? editor.sidebars : [];
+ sidebars.push({ name: name, settings: settings });
+ editor.sidebars = sidebars;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // It will not steal focus while setting contentEditable
- body = self.getBody();
- body.disabled = true;
- self.readonly = settings.readonly;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ add: add
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.readonly) {
- if (self.inline && DOM.getStyle(body, 'position', true) == 'static') {
- body.style.position = 'relative';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Editor.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- body.contentEditable = self.getParam('content_editable_state', true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/*jshint scripturl:true */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- body.disabled = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Include the base event class documentation.
+ *
+ * @include ../../../../../tools/docs/tinymce.Event.js
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.editorUpload = new EditorUpload(self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * This class contains the core logic for a TinyMCE editor.
+ *
+ * @class tinymce.Editor
+ * @mixes tinymce.util.Observable
+ * @example
+ * // Add a class to all paragraphs in the editor.
+ * tinymce.activeEditor.dom.addClass(tinymce.activeEditor.dom.select('p'), 'someclass');
+ *
+ * // Gets the current editors selection as text
+ * tinymce.activeEditor.selection.getContent({format: 'text'});
+ *
+ * // Creates a new editor instance
+ * var ed = new tinymce.Editor('textareaid', {
+ * some_setting: 1
+ * }, tinymce.EditorManager);
+ *
+ * ed.render();
+ */
+define(
+ 'tinymce.core.Editor',
+ [
+ 'tinymce.core.AddOnManager',
+ 'tinymce.core.dom.DomQuery',
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.core.EditorCommands',
+ 'tinymce.core.EditorObservable',
+ 'tinymce.core.Env',
+ 'tinymce.core.html.Serializer',
+ 'tinymce.core.init.Render',
+ 'tinymce.core.Mode',
+ 'tinymce.core.Shortcuts',
+ 'tinymce.core.ui.Sidebar',
+ 'tinymce.core.util.Tools',
+ 'tinymce.core.util.URI',
+ 'tinymce.core.util.Uuid'
+ ],
+ function (
+ AddOnManager, DomQuery, DOMUtils, EditorCommands, EditorObservable, Env, Serializer, Render, Mode,
+ Shortcuts, Sidebar, Tools, URI, Uuid
+ ) {
+ // Shorten these names
+ var DOM = DOMUtils.DOM;
+ var extend = Tools.extend, each = Tools.each;
+ var trim = Tools.trim, resolve = Tools.resolve;
+ var isGecko = Env.gecko, ie = Env.ie;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Schema instance, enables you to validate elements and its children.
- *
- * @property schema
- * @type tinymce.html.Schema
- */
- self.schema = new Schema(settings);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Include Editor API docs.
+ *
+ * @include ../../../../../tools/docs/tinymce.Editor.js
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * DOM instance for the editor.
- *
- * @property dom
- * @type tinymce.dom.DOMUtils
- * @example
- * // Adds a class to all paragraphs within the editor
- * tinymce.activeEditor.dom.addClass(tinymce.activeEditor.dom.select('p'), 'someclass');
- */
- self.dom = new DOMUtils(doc, {
- keep_values: true,
- url_converter: self.convertURL,
- url_converter_scope: self,
- hex_colors: settings.force_hex_style_colors,
- class_filter: settings.class_filter,
- update_styles: true,
- root_element: self.inline ? self.getBody() : null,
- collect: settings.content_editable,
- schema: self.schema,
- onSetAttrib: function(e) {
- self.fire('SetAttrib', e);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a editor instance by id.
+ *
+ * @constructor
+ * @method Editor
+ * @param {String} id Unique id for the editor.
+ * @param {Object} settings Settings for the editor.
+ * @param {tinymce.EditorManager} editorManager EditorManager instance.
+ */
+ function Editor(id, settings, editorManager) {
+ var self = this, documentBaseUrl, baseUri, defaultSettings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * HTML parser will be used when contents is inserted into the editor.
- *
- * @property parser
- * @type tinymce.html.DomParser
- */
- self.parser = new DomParser(settings, self.schema);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ documentBaseUrl = self.documentBaseUrl = editorManager.documentBaseURL;
+ baseUri = editorManager.baseURI;
+ defaultSettings = editorManager.defaultSettings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Convert src and href into data-mce-src, data-mce-href and data-mce-style
- self.parser.addAttributeFilter('src,href,style,tabindex', function(nodes, name) {
- var i = nodes.length, node, dom = self.dom, value, internalName;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Name/value collection with editor settings.
+ *
+ * @property settings
+ * @type Object
+ * @example
+ * // Get the value of the theme setting
+ * tinymce.activeEditor.windowManager.alert("You are using the " + tinymce.activeEditor.settings.theme + " theme");
+ */
+ settings = extend({
+ id: id,
+ theme: 'modern',
+ delta_width: 0,
+ delta_height: 0,
+ popup_css: '',
+ plugins: '',
+ document_base_url: documentBaseUrl,
+ add_form_submit_trigger: true,
+ submit_patch: true,
+ add_unload_trigger: true,
+ convert_urls: true,
+ relative_urls: true,
+ remove_script_host: true,
+ object_resizing: true,
+ doctype: '<!DOCTYPE html>',
+ visual: true,
+ font_size_style_values: 'xx-small,x-small,small,medium,large,x-large,xx-large',
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i];
- value = node.attr(name);
- internalName = 'data-mce-' + name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // See: http://www.w3.org/TR/CSS2/fonts.html#propdef-font-size
+ font_size_legacy_values: 'xx-small,small,medium,large,x-large,xx-large,300%',
+ forced_root_block: 'p',
+ hidden_input: true,
+ padd_empty_editor: true,
+ render_ui: true,
+ indentation: '30px',
+ inline_styles: true,
+ convert_fonts_to_spans: true,
+ indent: 'simple',
+ indent_before: 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead,' +
+ 'tfoot,tbody,tr,section,article,hgroup,aside,figure,figcaption,option,optgroup,datalist',
+ indent_after: 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead,' +
+ 'tfoot,tbody,tr,section,article,hgroup,aside,figure,figcaption,option,optgroup,datalist',
+ validate: true,
+ entity_encoding: 'named',
+ url_converter: self.convertURL,
+ url_converter_scope: self,
+ ie7_compat: true
+ }, defaultSettings, settings);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add internal attribute if we need to we don't on a refresh of the document
- if (!node.attributes.map[internalName]) {
- // Don't duplicate these since they won't get modified by any browser
- if (value.indexOf('data:') === 0 || value.indexOf('blob:') === 0) {
- continue;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Merge external_plugins
+ if (defaultSettings && defaultSettings.external_plugins && settings.external_plugins) {
+ settings.external_plugins = extend({}, defaultSettings.external_plugins, settings.external_plugins);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (name === "style") {
- value = dom.serializeStyle(dom.parseStyle(value), node.name);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.settings = settings;
+ AddOnManager.language = settings.language || 'en';
+ AddOnManager.languageLoad = settings.language_load;
+ AddOnManager.baseURL = editorManager.baseURL;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!value.length) {
- value = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Editor instance id, normally the same as the div/textarea that was replaced.
+ *
+ * @property id
+ * @type String
+ */
+ self.id = settings.id = id;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node.attr(internalName, value);
- node.attr(name, value);
- } else if (name === "tabindex") {
- node.attr(internalName, value);
- node.attr(name, null);
- } else {
- node.attr(internalName, self.convertURL(value, name, node.name));
- }
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * State to force the editor to return false on a isDirty call.
+ *
+ * @property isNotDirty
+ * @type Boolean
+ * @deprecated Use editor.setDirty instead.
+ */
+ self.setDirty(false);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Keep scripts from executing
- self.parser.addNodeFilter('script', function(nodes) {
- var i = nodes.length, node, type;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Name/Value object containing plugin instances.
+ *
+ * @property plugins
+ * @type Object
+ * @example
+ * // Execute a method inside a plugin directly
+ * tinymce.activeEditor.plugins.someplugin.someMethod();
+ */
+ self.plugins = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i];
- type = node.attr('type') || 'no/type';
- if (type.indexOf('mce-') !== 0) {
- node.attr('type', 'mce-' + type);
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * URI object to document configured for the TinyMCE instance.
+ *
+ * @property documentBaseURI
+ * @type tinymce.util.URI
+ * @example
+ * // Get relative URL from the location of document_base_url
+ * tinymce.activeEditor.documentBaseURI.toRelative('/somedir/somefile.htm');
+ *
+ * // Get absolute URL from the location of document_base_url
+ * tinymce.activeEditor.documentBaseURI.toAbsolute('somefile.htm');
+ */
+ self.documentBaseURI = new URI(settings.document_base_url || documentBaseUrl, {
+ base_uri: baseUri
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.parser.addNodeFilter('#cdata', function(nodes) {
- var i = nodes.length, node;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * URI object to current document that holds the TinyMCE editor instance.
+ *
+ * @property baseURI
+ * @type tinymce.util.URI
+ * @example
+ * // Get relative URL from the location of the API
+ * tinymce.activeEditor.baseURI.toRelative('/somedir/somefile.htm');
+ *
+ * // Get absolute URL from the location of the API
+ * tinymce.activeEditor.baseURI.toAbsolute('somefile.htm');
+ */
+ self.baseURI = baseUri;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i];
- node.type = 8;
- node.name = '#comment';
- node.value = '[CDATA[' + node.value + ']]';
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Array with CSS files to load into the iframe.
+ *
+ * @property contentCSS
+ * @type Array
+ */
+ self.contentCSS = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.parser.addNodeFilter('p,h1,h2,h3,h4,h5,h6,div', function(nodes) {
- var i = nodes.length, node, nonEmptyElements = self.schema.getNonEmptyElements();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Array of CSS styles to add to head of document when the editor loads.
+ *
+ * @property contentStyles
+ * @type Array
+ */
+ self.contentStyles = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- node = nodes[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Creates all events like onClick, onSetContent etc see Editor.Events.js for the actual logic
+ self.shortcuts = new Shortcuts(self);
+ self.loadedCSS = {};
+ self.editorCommands = new EditorCommands(self);
+ self.suffix = editorManager.suffix;
+ self.editorManager = editorManager;
+ self.inline = settings.inline;
+ self.settings.content_editable = self.inline;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (node.isEmpty(nonEmptyElements) && node.getAll('br').length === 0) {
- node.append(new Node('br', 1)).shortEnded = true;
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.cache_suffix) {
+ Env.cacheSuffix = settings.cache_suffix.replace(/^[\?\&]+/, '');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * DOM serializer for the editor. Will be used when contents is extracted from the editor.
- *
- * @property serializer
- * @type tinymce.dom.Serializer
- * @example
- * // Serializes the first paragraph in the editor into a string
- * tinymce.activeEditor.serializer.serialize(tinymce.activeEditor.dom.select('p')[0]);
- */
- self.serializer = new DomSerializer(settings, self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.override_viewport === false) {
+ Env.overrideViewPort = false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Selection instance for the editor.
- *
- * @property selection
- * @type tinymce.dom.Selection
- * @example
- * // Sets some contents to the current selection in the editor
- * tinymce.activeEditor.selection.setContent('Some contents');
- *
- * // Gets the current selection
- * alert(tinymce.activeEditor.selection.getContent());
- *
- * // Selects the first paragraph found
- * tinymce.activeEditor.selection.select(tinymce.activeEditor.dom.select('p')[0]);
- */
- self.selection = new Selection(self.dom, self.getWin(), self.serializer, self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Call setup
+ editorManager.fire('SetupEditor', self);
+ self.execCallback('setup', self);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Formatter instance.
- *
- * @property formatter
- * @type tinymce.Formatter
- */
- self.formatter = new Formatter(self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Dom query instance with default scope to the editor document and default element is the body of the editor.
+ *
+ * @property $
+ * @type tinymce.dom.DomQuery
+ * @example
+ * tinymce.activeEditor.$('p').css('color', 'red');
+ * tinymce.activeEditor.$().append('<p>new</p>');
+ */
+ self.$ = DomQuery.overrideDefaults(function () {
+ return {
+ context: self.inline ? self.getBody() : self.getDoc(),
+ element: self.getBody()
+ };
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Undo manager instance, responsible for handling undo levels.
- *
- * @property undoManager
- * @type tinymce.UndoManager
- * @example
- * // Undoes the last modification to the editor
- * tinymce.activeEditor.undoManager.undo();
- */
- self.undoManager = new UndoManager(self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Editor.prototype = {
+ /**
+ * Renders the editor/adds it to the page.
+ *
+ * @method render
+ */
+ render: function () {
+ Render.render(this);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.forceBlocks = new ForceBlocks(self);
- self.enterKey = new EnterKey(self);
- self._nodeChangeDispatcher = new NodeChange(self);
- self._selectionOverrides = new SelectionOverrides(self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Focuses/activates the editor. This will set this editor as the activeEditor in the tinymce collection
+ * it will also place DOM focus inside the editor.
+ *
+ * @method focus
+ * @param {Boolean} skipFocus Skip DOM focus. Just set is as the active editor.
+ */
+ focus: function (skipFocus) {
+ var self = this, selection = self.selection, contentEditable = self.settings.content_editable, rng;
+ var controlElm, doc = self.getDoc(), body = self.getBody(), contentEditableHost;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.fire('PreInit');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getContentEditableHost(node) {
+ return self.dom.getParent(node, function (node) {
+ return self.dom.getContentEditable(node) === "true";
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!settings.browser_spellcheck && !settings.gecko_spellcheck) {
- doc.body.spellcheck = false; // Gecko
- DOM.setAttrib(body, "spellcheck", "false");
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!skipFocus) {
+ // Get selected control element
+ rng = selection.getRng();
+ if (rng.item) {
+ controlElm = rng.item(0);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.quirks = new Quirks(self);
- self.fire('PostRender');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.quirks.refreshContentEditable();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.directionality) {
- body.dir = settings.directionality;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move focus to contentEditable=true child if needed
+ contentEditableHost = getContentEditableHost(selection.getNode());
+ if (self.$.contains(body, contentEditableHost)) {
+ contentEditableHost.focus();
+ selection.normalize();
+ self.editorManager.setActive(self);
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.nowrap) {
- body.style.whiteSpace = "nowrap";
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Focus the window iframe
+ if (!contentEditable) {
+ // WebKit needs this call to fire focusin event properly see #5948
+ // But Opera pre Blink engine will produce an empty selection so skip Opera
+ if (!Env.opera) {
+ self.getBody().focus();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.protect) {
- self.on('BeforeSetContent', function(e) {
- each(settings.protect, function(pattern) {
- e.content = e.content.replace(pattern, function(str) {
- return '<!--mce:protected ' + escape(str) + '-->';
- });
- });
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.getWin().focus();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('SetContent', function() {
- self.addVisual(self.getBody());
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Focus the body as well since it's contentEditable
+ if (isGecko || contentEditable) {
+ // Check for setActive since it doesn't scroll to the element
+ if (body.setActive) {
+ // IE 11 sometimes throws "Invalid function" then fallback to focus
+ try {
+ body.setActive();
+ } catch (ex) {
+ body.focus();
+ }
+ } else {
+ body.focus();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove empty contents
- if (settings.padd_empty_editor) {
- self.on('PostProcess', function(e) {
- e.content = e.content.replace(/^(<p[^>]*>( | |\s|\u00a0|<br \/>|)<\/p>[\r\n]*|<br \/>[\r\n]*)$/, '');
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (contentEditable) {
+ selection.normalize();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.load({initial: true, format: 'html'});
- self.startContent = self.getContent({format: 'raw'});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Restore selected control element
+ // This is needed when for example an image is selected within a
+ // layer a call to focus will then remove the control selection
+ if (controlElm && controlElm.ownerDocument == doc) {
+ rng = doc.body.createControlRange();
+ rng.addElement(controlElm);
+ rng.select();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Is set to true after the editor instance has been initialized
- *
- * @property initialized
- * @type Boolean
- * @example
- * function isEditorInitialized(editor) {
- * return editor && editor.initialized;
- * }
- */
- self.initialized = true;
- self.bindPendingEventDelegates();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.editorManager.setActive(self);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.fire('init');
- self.focus(true);
- self.nodeChanged({initial: true});
- self.execCallback('init_instance_callback', self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Executes a legacy callback. This method is useful to call old 2.x option callbacks.
+ * There new event model is a better way to add callback so this method might be removed in the future.
+ *
+ * @method execCallback
+ * @param {String} name Name of the callback to execute.
+ * @return {Object} Return value passed from callback function.
+ */
+ execCallback: function (name) {
+ var self = this, callback = self.settings[name], scope;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('compositionstart compositionend', function(e) {
- self.composing = e.type === 'compositionstart';
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!callback) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add editor specific CSS styles
- if (self.contentStyles.length > 0) {
- contentCssText = '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Look through lookup
+ if (self.callbackLookup && (scope = self.callbackLookup[name])) {
+ callback = scope.func;
+ scope = scope.scope;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(self.contentStyles, function(style) {
- contentCssText += style + "\r\n";
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof callback === 'string') {
+ scope = callback.replace(/\.\w+$/, '');
+ scope = scope ? resolve(scope) : 0;
+ callback = resolve(callback);
+ self.callbackLookup = self.callbackLookup || {};
+ self.callbackLookup[name] = { func: callback, scope: scope };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.dom.addStyle(contentCssText);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return callback.apply(scope || self, Array.prototype.slice.call(arguments, 1));
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Load specified content CSS last
- each(self.contentCSS, function(cssUrl) {
- if (!self.loadedCSS[cssUrl]) {
- self.dom.loadCSS(cssUrl);
- self.loadedCSS[cssUrl] = true;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Translates the specified string by replacing variables with language pack items it will also check if there is
+ * a key matching the input.
+ *
+ * @method translate
+ * @param {String} text String to translate by the language pack data.
+ * @return {String} Translated string.
+ */
+ translate: function (text) {
+ var lang = this.settings.language || 'en', i18n = this.editorManager.i18n;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle auto focus
- if (settings.auto_focus) {
- Delay.setEditorTimeout(self, function() {
- var editor;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!text) {
+ return '';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.auto_focus === true) {
- editor = self;
- } else {
- editor = self.editorManager.get(settings.auto_focus);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ text = i18n.data[lang + '.' + text] || text.replace(/\{\#([^\}]+)\}/g, function (a, b) {
+ return i18n.data[lang + '.' + b] || '{#' + b + '}';
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!editor.destroyed) {
- editor.focus();
- }
- }, 100);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this.editorManager.translate(text);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Clean up references for IE
- targetElm = doc = body = null;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a language pack item by name/key.
+ *
+ * @method getLang
+ * @param {String} name Name/key to get from the language pack.
+ * @param {String} defaultVal Optional default value to retrieve.
+ */
+ getLang: function (name, defaultVal) {
+ return (
+ this.editorManager.i18n.data[(this.settings.language || 'en') + '.' + name] ||
+ (defaultVal !== undefined ? defaultVal : '{#' + name + '}')
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Focuses/activates the editor. This will set this editor as the activeEditor in the tinymce collection
- * it will also place DOM focus inside the editor.
- *
- * @method focus
- * @param {Boolean} skipFocus Skip DOM focus. Just set is as the active editor.
- */
- focus: function(skipFocus) {
- var self = this, selection = self.selection, contentEditable = self.settings.content_editable, rng;
- var controlElm, doc = self.getDoc(), body = self.getBody(), contentEditableHost;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a configuration parameter by name.
+ *
+ * @method getParam
+ * @param {String} name Configruation parameter to retrieve.
+ * @param {String} defaultVal Optional default value to return.
+ * @param {String} type Optional type parameter.
+ * @return {String} Configuration parameter value or default value.
+ * @example
+ * // Returns a specific config value from the currently active editor
+ * var someval = tinymce.activeEditor.getParam('myvalue');
+ *
+ * // Returns a specific config value from a specific editor instance by id
+ * var someval2 = tinymce.get('my_editor').getParam('myvalue');
+ */
+ getParam: function (name, defaultVal, type) {
+ var value = name in this.settings ? this.settings[name] : defaultVal, output;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getContentEditableHost(node) {
- return self.dom.getParent(node, function(node) {
- return self.dom.getContentEditable(node) === "true";
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (type === 'hash') {
+ output = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!skipFocus) {
- // Get selected control element
- rng = selection.getRng();
- if (rng.item) {
- controlElm = rng.item(0);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof value === 'string') {
+ each(value.indexOf('=') > 0 ? value.split(/[;,](?![^=;,]*(?:[;,]|$))/) : value.split(','), function (value) {
+ value = value.split('=');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.quirks.refreshContentEditable();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value.length > 1) {
+ output[trim(value[0])] = trim(value[1]);
+ } else {
+ output[trim(value[0])] = trim(value);
+ }
+ });
+ } else {
+ output = value;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move focus to contentEditable=true child if needed
- contentEditableHost = getContentEditableHost(selection.getNode());
- if (self.$.contains(body, contentEditableHost)) {
- contentEditableHost.focus();
- selection.normalize();
- self.editorManager.setActive(self);
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return output;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Focus the window iframe
- if (!contentEditable) {
- // WebKit needs this call to fire focusin event properly see #5948
- // But Opera pre Blink engine will produce an empty selection so skip Opera
- if (!Env.opera) {
- self.getBody().focus();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return value;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.getWin().focus();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Dispatches out a onNodeChange event to all observers. This method should be called when you
+ * need to update the UI states or element path etc.
+ *
+ * @method nodeChanged
+ * @param {Object} args Optional args to pass to NodeChange event handlers.
+ */
+ nodeChanged: function (args) {
+ this._nodeChangeDispatcher.nodeChanged(args);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Focus the body as well since it's contentEditable
- if (isGecko || contentEditable) {
- // Check for setActive since it doesn't scroll to the element
- if (body.setActive) {
- // IE 11 sometimes throws "Invalid function" then fallback to focus
- try {
- body.setActive();
- } catch (ex) {
- body.focus();
- }
- } else {
- body.focus();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds a button that later gets created by the theme in the editors toolbars.
+ *
+ * @method addButton
+ * @param {String} name Button name to add.
+ * @param {Object} settings Settings object with title, cmd etc.
+ * @example
+ * // Adds a custom button to the editor that inserts contents when clicked
+ * tinymce.init({
+ * ...
+ *
+ * toolbar: 'example'
+ *
+ * setup: function(ed) {
+ * ed.addButton('example', {
+ * title: 'My title',
+ * image: '../js/tinymce/plugins/example/img/example.gif',
+ * onclick: function() {
+ * ed.insertContent('Hello world!!');
+ * }
+ * });
+ * }
+ * });
+ */
+ addButton: function (name, settings) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (contentEditable) {
- selection.normalize();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.cmd) {
+ settings.onclick = function () {
+ self.execCommand(settings.cmd);
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Restore selected control element
- // This is needed when for example an image is selected within a
- // layer a call to focus will then remove the control selection
- if (controlElm && controlElm.ownerDocument == doc) {
- rng = doc.body.createControlRange();
- rng.addElement(controlElm);
- rng.select();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!settings.text && !settings.icon) {
+ settings.icon = name;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.editorManager.setActive(self);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.buttons = self.buttons || {};
+ settings.tooltip = settings.tooltip || settings.title;
+ self.buttons[name] = settings;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Executes a legacy callback. This method is useful to call old 2.x option callbacks.
- * There new event model is a better way to add callback so this method might be removed in the future.
- *
- * @method execCallback
- * @param {String} name Name of the callback to execute.
- * @return {Object} Return value passed from callback function.
- */
- execCallback: function(name) {
- var self = this, callback = self.settings[name], scope;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds a sidebar for the editor instance.
+ *
+ * @method addSidebar
+ * @param {String} name Sidebar name to add.
+ * @param {Object} settings Settings object with icon, onshow etc.
+ * @example
+ * // Adds a custom sidebar that when clicked logs the panel element
+ * tinymce.init({
+ * ...
+ * setup: function(ed) {
+ * ed.addSidebar('example', {
+ * tooltip: 'My sidebar',
+ * icon: 'my-side-bar',
+ * onshow: function(api) {
+ * console.log(api.element());
+ * }
+ * });
+ * }
+ * });
+ */
+ addSidebar: function (name, settings) {
+ return Sidebar.add(this, name, settings);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!callback) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds a menu item to be used in the menus of the theme. There might be multiple instances
+ * of this menu item for example it might be used in the main menus of the theme but also in
+ * the context menu so make sure that it's self contained and supports multiple instances.
+ *
+ * @method addMenuItem
+ * @param {String} name Menu item name to add.
+ * @param {Object} settings Settings object with title, cmd etc.
+ * @example
+ * // Adds a custom menu item to the editor that inserts contents when clicked
+ * // The context option allows you to add the menu item to an existing default menu
+ * tinymce.init({
+ * ...
+ *
+ * setup: function(ed) {
+ * ed.addMenuItem('example', {
+ * text: 'My menu item',
+ * context: 'tools',
+ * onclick: function() {
+ * ed.insertContent('Hello world!!');
+ * }
+ * });
+ * }
+ * });
+ */
+ addMenuItem: function (name, settings) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Look through lookup
- if (self.callbackLookup && (scope = self.callbackLookup[name])) {
- callback = scope.func;
- scope = scope.scope;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.cmd) {
+ settings.onclick = function () {
+ self.execCommand(settings.cmd);
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof callback === 'string') {
- scope = callback.replace(/\.\w+$/, '');
- scope = scope ? resolve(scope) : 0;
- callback = resolve(callback);
- self.callbackLookup = self.callbackLookup || {};
- self.callbackLookup[name] = {func: callback, scope: scope};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.menuItems = self.menuItems || {};
+ self.menuItems[name] = settings;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return callback.apply(scope || self, Array.prototype.slice.call(arguments, 1));
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds a contextual toolbar to be rendered when the selector matches.
+ *
+ * @method addContextToolbar
+ * @param {function/string} predicate Predicate that needs to return true if provided strings get converted into CSS predicates.
+ * @param {String/Array} items String or array with items to add to the context toolbar.
+ */
+ addContextToolbar: function (predicate, items) {
+ var self = this, selector;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Translates the specified string by replacing variables with language pack items it will also check if there is
- * a key matching the input.
- *
- * @method translate
- * @param {String} text String to translate by the language pack data.
- * @return {String} Translated string.
- */
- translate: function(text) {
- var lang = this.settings.language || 'en', i18n = this.editorManager.i18n;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.contextToolbars = self.contextToolbars || [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!text) {
- return '';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Convert selector to predicate
+ if (typeof predicate == "string") {
+ selector = predicate;
+ predicate = function (elm) {
+ return self.dom.is(elm, selector);
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- text = i18n.data[lang + '.' + text] || text.replace(/\{\#([^\}]+)\}/g, function(a, b) {
- return i18n.data[lang + '.' + b] || '{#' + b + '}';
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.contextToolbars.push({
+ id: Uuid.uuid('mcet'),
+ predicate: predicate,
+ items: items
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this.editorManager.translate(text);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds a custom command to the editor, you can also override existing commands with this method.
+ * The command that you add can be executed with execCommand.
+ *
+ * @method addCommand
+ * @param {String} name Command name to add/override.
+ * @param {addCommandCallback} callback Function to execute when the command occurs.
+ * @param {Object} scope Optional scope to execute the function in.
+ * @example
+ * // Adds a custom command that later can be executed using execCommand
+ * tinymce.init({
+ * ...
+ *
+ * setup: function(ed) {
+ * // Register example command
+ * ed.addCommand('mycommand', function(ui, v) {
+ * ed.windowManager.alert('Hello world!! Selection: ' + ed.selection.getContent({format: 'text'}));
+ * });
+ * }
+ * });
+ */
+ addCommand: function (name, callback, scope) {
+ /**
+ * Callback function that gets called when a command is executed.
+ *
+ * @callback addCommandCallback
+ * @param {Boolean} ui Display UI state true/false.
+ * @param {Object} value Optional value for command.
+ * @return {Boolean} True/false state if the command was handled or not.
+ */
+ this.editorCommands.addCommand(name, callback, scope);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a language pack item by name/key.
- *
- * @method getLang
- * @param {String} name Name/key to get from the language pack.
- * @param {String} defaultVal Optional default value to retrieve.
- */
- getLang: function(name, defaultVal) {
- return (
- this.editorManager.i18n.data[(this.settings.language || 'en') + '.' + name] ||
- (defaultVal !== undefined ? defaultVal : '{#' + name + '}')
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds a custom query state command to the editor, you can also override existing commands with this method.
+ * The command that you add can be executed with queryCommandState function.
+ *
+ * @method addQueryStateHandler
+ * @param {String} name Command name to add/override.
+ * @param {addQueryStateHandlerCallback} callback Function to execute when the command state retrieval occurs.
+ * @param {Object} scope Optional scope to execute the function in.
+ */
+ addQueryStateHandler: function (name, callback, scope) {
+ /**
+ * Callback function that gets called when a queryCommandState is executed.
+ *
+ * @callback addQueryStateHandlerCallback
+ * @return {Boolean} True/false state if the command is enabled or not like is it bold.
+ */
+ this.editorCommands.addQueryStateHandler(name, callback, scope);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a configuration parameter by name.
- *
- * @method getParam
- * @param {String} name Configruation parameter to retrieve.
- * @param {String} defaultVal Optional default value to return.
- * @param {String} type Optional type parameter.
- * @return {String} Configuration parameter value or default value.
- * @example
- * // Returns a specific config value from the currently active editor
- * var someval = tinymce.activeEditor.getParam('myvalue');
- *
- * // Returns a specific config value from a specific editor instance by id
- * var someval2 = tinymce.get('my_editor').getParam('myvalue');
- */
- getParam: function(name, defaultVal, type) {
- var value = name in this.settings ? this.settings[name] : defaultVal, output;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds a custom query value command to the editor, you can also override existing commands with this method.
+ * The command that you add can be executed with queryCommandValue function.
+ *
+ * @method addQueryValueHandler
+ * @param {String} name Command name to add/override.
+ * @param {addQueryValueHandlerCallback} callback Function to execute when the command value retrieval occurs.
+ * @param {Object} scope Optional scope to execute the function in.
+ */
+ addQueryValueHandler: function (name, callback, scope) {
+ /**
+ * Callback function that gets called when a queryCommandValue is executed.
+ *
+ * @callback addQueryValueHandlerCallback
+ * @return {Object} Value of the command or undefined.
+ */
+ this.editorCommands.addQueryValueHandler(name, callback, scope);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (type === 'hash') {
- output = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds a keyboard shortcut for some command or function.
+ *
+ * @method addShortcut
+ * @param {String} pattern Shortcut pattern. Like for example: ctrl+alt+o.
+ * @param {String} desc Text description for the command.
+ * @param {String/Function} cmdFunc Command name string or function to execute when the key is pressed.
+ * @param {Object} sc Optional scope to execute the function in.
+ * @return {Boolean} true/false state if the shortcut was added or not.
+ */
+ addShortcut: function (pattern, desc, cmdFunc, scope) {
+ this.shortcuts.add(pattern, desc, cmdFunc, scope);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof value === 'string') {
- each(value.indexOf('=') > 0 ? value.split(/[;,](?![^=;,]*(?:[;,]|$))/) : value.split(','), function(value) {
- value = value.split('=');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Executes a command on the current instance. These commands can be TinyMCE internal commands prefixed with "mce" or
+ * they can be build in browser commands such as "Bold". A compleate list of browser commands is available on MSDN or Mozilla.org.
+ * This function will dispatch the execCommand function on each plugin, theme or the execcommand_callback option if none of these
+ * return true it will handle the command as a internal browser command.
+ *
+ * @method execCommand
+ * @param {String} cmd Command name to execute, for example mceLink or Bold.
+ * @param {Boolean} ui True/false state if a UI (dialog) should be presented or not.
+ * @param {mixed} value Optional command value, this can be anything.
+ * @param {Object} args Optional arguments object.
+ */
+ execCommand: function (cmd, ui, value, args) {
+ return this.editorCommands.execCommand(cmd, ui, value, args);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value.length > 1) {
- output[trim(value[0])] = trim(value[1]);
- } else {
- output[trim(value[0])] = trim(value);
- }
- });
- } else {
- output = value;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a command specific state, for example if bold is enabled or not.
+ *
+ * @method queryCommandState
+ * @param {string} cmd Command to query state from.
+ * @return {Boolean} Command specific state, for example if bold is enabled or not.
+ */
+ queryCommandState: function (cmd) {
+ return this.editorCommands.queryCommandState(cmd);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return output;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a command specific value, for example the current font size.
+ *
+ * @method queryCommandValue
+ * @param {string} cmd Command to query value from.
+ * @return {Object} Command specific value, for example the current font size.
+ */
+ queryCommandValue: function (cmd) {
+ return this.editorCommands.queryCommandValue(cmd);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return value;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the command is supported or not.
+ *
+ * @method queryCommandSupported
+ * @param {String} cmd Command that we check support for.
+ * @return {Boolean} true/false if the command is supported or not.
+ */
+ queryCommandSupported: function (cmd) {
+ return this.editorCommands.queryCommandSupported(cmd);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Dispatches out a onNodeChange event to all observers. This method should be called when you
- * need to update the UI states or element path etc.
- *
- * @method nodeChanged
- * @param {Object} args Optional args to pass to NodeChange event handlers.
- */
- nodeChanged: function(args) {
- this._nodeChangeDispatcher.nodeChanged(args);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Shows the editor and hides any textarea/div that the editor is supposed to replace.
+ *
+ * @method show
+ */
+ show: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds a button that later gets created by the theme in the editors toolbars.
- *
- * @method addButton
- * @param {String} name Button name to add.
- * @param {Object} settings Settings object with title, cmd etc.
- * @example
- * // Adds a custom button to the editor that inserts contents when clicked
- * tinymce.init({
- * ...
- *
- * toolbar: 'example'
- *
- * setup: function(ed) {
- * ed.addButton('example', {
- * title: 'My title',
- * image: '../js/tinymce/plugins/example/img/example.gif',
- * onclick: function() {
- * ed.insertContent('Hello world!!');
- * }
- * });
- * }
- * });
- */
- addButton: function(name, settings) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.hidden) {
+ self.hidden = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.cmd) {
- settings.onclick = function() {
- self.execCommand(settings.cmd);
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.inline) {
+ self.getBody().contentEditable = true;
+ } else {
+ DOM.show(self.getContainer());
+ DOM.hide(self.id);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!settings.text && !settings.icon) {
- settings.icon = name;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.load();
+ self.fire('show');
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.buttons = self.buttons || {};
- settings.tooltip = settings.tooltip || settings.title;
- self.buttons[name] = settings;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Hides the editor and shows any textarea/div that the editor is supposed to replace.
+ *
+ * @method hide
+ */
+ hide: function () {
+ var self = this, doc = self.getDoc();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds a sidebar for the editor instance.
- *
- * @method addSidebar
- * @param {String} name Sidebar name to add.
- * @param {Object} settings Settings object with icon, onshow etc.
- * @example
- * // Adds a custom sidebar that when clicked logs the panel element
- * tinymce.init({
- * ...
- * setup: function(ed) {
- * ed.addSidebar('example', {
- * tooltip: 'My sidebar',
- * icon: 'my-side-bar',
- * onshow: function(api) {
- * console.log(api.element());
- * }
- * });
- * }
- * });
- */
- addSidebar: function (name, settings) {
- return Sidebar.add(this, name, settings);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.hidden) {
+ // Fixed bug where IE has a blinking cursor left from the editor
+ if (ie && doc && !self.inline) {
+ doc.execCommand('SelectAll');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds a menu item to be used in the menus of the theme. There might be multiple instances
- * of this menu item for example it might be used in the main menus of the theme but also in
- * the context menu so make sure that it's self contained and supports multiple instances.
- *
- * @method addMenuItem
- * @param {String} name Menu item name to add.
- * @param {Object} settings Settings object with title, cmd etc.
- * @example
- * // Adds a custom menu item to the editor that inserts contents when clicked
- * // The context option allows you to add the menu item to an existing default menu
- * tinymce.init({
- * ...
- *
- * setup: function(ed) {
- * ed.addMenuItem('example', {
- * text: 'My menu item',
- * context: 'tools',
- * onclick: function() {
- * ed.insertContent('Hello world!!');
- * }
- * });
- * }
- * });
- */
- addMenuItem: function(name, settings) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // We must save before we hide so Safari doesn't crash
+ self.save();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.cmd) {
- settings.onclick = function() {
- self.execCommand(settings.cmd);
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.inline) {
+ self.getBody().contentEditable = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.menuItems = self.menuItems || {};
- self.menuItems[name] = settings;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Make sure the editor gets blurred
+ if (self == self.editorManager.focusedEditor) {
+ self.editorManager.focusedEditor = null;
+ }
+ } else {
+ DOM.hide(self.getContainer());
+ DOM.setStyle(self.id, 'display', self.orgDisplay);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds a contextual toolbar to be rendered when the selector matches.
- *
- * @method addContextToolbar
- * @param {function/string} predicate Predicate that needs to return true if provided strings get converted into CSS predicates.
- * @param {String/Array} items String or array with items to add to the context toolbar.
- */
- addContextToolbar: function(predicate, items) {
- var self = this, selector;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.hidden = true;
+ self.fire('hide');
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.contextToolbars = self.contextToolbars || [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the editor is hidden or not.
+ *
+ * @method isHidden
+ * @return {Boolean} True/false if the editor is hidden or not.
+ */
+ isHidden: function () {
+ return !!this.hidden;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Convert selector to predicate
- if (typeof predicate == "string") {
- selector = predicate;
- predicate = function(elm) {
- return self.dom.is(elm, selector);
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets the progress state, this will display a throbber/progess for the editor.
+ * This is ideal for asynchronous operations like an AJAX save call.
+ *
+ * @method setProgressState
+ * @param {Boolean} state Boolean state if the progress should be shown or hidden.
+ * @param {Number} time Optional time to wait before the progress gets shown.
+ * @return {Boolean} Same as the input state.
+ * @example
+ * // Show progress for the active editor
+ * tinymce.activeEditor.setProgressState(true);
+ *
+ * // Hide progress for the active editor
+ * tinymce.activeEditor.setProgressState(false);
+ *
+ * // Show progress after 3 seconds
+ * tinymce.activeEditor.setProgressState(true, 3000);
+ */
+ setProgressState: function (state, time) {
+ this.fire('ProgressState', { state: state, time: time });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.contextToolbars.push({
- id: Uuid.uuid('mcet'),
- predicate: predicate,
- items: items
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Loads contents from the textarea or div element that got converted into an editor instance.
+ * This method will move the contents from that textarea or div into the editor by using setContent
+ * so all events etc that method has will get dispatched as well.
+ *
+ * @method load
+ * @param {Object} args Optional content object, this gets passed around through the whole load process.
+ * @return {String} HTML string that got set into the editor.
+ */
+ load: function (args) {
+ var self = this, elm = self.getElement(), html;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds a custom command to the editor, you can also override existing commands with this method.
- * The command that you add can be executed with execCommand.
- *
- * @method addCommand
- * @param {String} name Command name to add/override.
- * @param {addCommandCallback} callback Function to execute when the command occurs.
- * @param {Object} scope Optional scope to execute the function in.
- * @example
- * // Adds a custom command that later can be executed using execCommand
- * tinymce.init({
- * ...
- *
- * setup: function(ed) {
- * // Register example command
- * ed.addCommand('mycommand', function(ui, v) {
- * ed.windowManager.alert('Hello world!! Selection: ' + ed.selection.getContent({format: 'text'}));
- * });
- * }
- * });
- */
- addCommand: function(name, callback, scope) {
- /**
- * Callback function that gets called when a command is executed.
- *
- * @callback addCommandCallback
- * @param {Boolean} ui Display UI state true/false.
- * @param {Object} value Optional value for command.
- * @return {Boolean} True/false state if the command was handled or not.
- */
- this.editorCommands.addCommand(name, callback, scope);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (elm) {
+ args = args || {};
+ args.load = true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds a custom query state command to the editor, you can also override existing commands with this method.
- * The command that you add can be executed with queryCommandState function.
- *
- * @method addQueryStateHandler
- * @param {String} name Command name to add/override.
- * @param {addQueryStateHandlerCallback} callback Function to execute when the command state retrieval occurs.
- * @param {Object} scope Optional scope to execute the function in.
- */
- addQueryStateHandler: function(name, callback, scope) {
- /**
- * Callback function that gets called when a queryCommandState is executed.
- *
- * @callback addQueryStateHandlerCallback
- * @return {Boolean} True/false state if the command is enabled or not like is it bold.
- */
- this.editorCommands.addQueryStateHandler(name, callback, scope);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ html = self.setContent(elm.value !== undefined ? elm.value : elm.innerHTML, args);
+ args.element = elm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds a custom query value command to the editor, you can also override existing commands with this method.
- * The command that you add can be executed with queryCommandValue function.
- *
- * @method addQueryValueHandler
- * @param {String} name Command name to add/override.
- * @param {addQueryValueHandlerCallback} callback Function to execute when the command value retrieval occurs.
- * @param {Object} scope Optional scope to execute the function in.
- */
- addQueryValueHandler: function(name, callback, scope) {
- /**
- * Callback function that gets called when a queryCommandValue is executed.
- *
- * @callback addQueryValueHandlerCallback
- * @return {Object} Value of the command or undefined.
- */
- this.editorCommands.addQueryValueHandler(name, callback, scope);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!args.no_events) {
+ self.fire('LoadContent', args);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds a keyboard shortcut for some command or function.
- *
- * @method addShortcut
- * @param {String} pattern Shortcut pattern. Like for example: ctrl+alt+o.
- * @param {String} desc Text description for the command.
- * @param {String/Function} cmdFunc Command name string or function to execute when the key is pressed.
- * @param {Object} sc Optional scope to execute the function in.
- * @return {Boolean} true/false state if the shortcut was added or not.
- */
- addShortcut: function(pattern, desc, cmdFunc, scope) {
- this.shortcuts.add(pattern, desc, cmdFunc, scope);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args.element = elm = null;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Executes a command on the current instance. These commands can be TinyMCE internal commands prefixed with "mce" or
- * they can be build in browser commands such as "Bold". A compleate list of browser commands is available on MSDN or Mozilla.org.
- * This function will dispatch the execCommand function on each plugin, theme or the execcommand_callback option if none of these
- * return true it will handle the command as a internal browser command.
- *
- * @method execCommand
- * @param {String} cmd Command name to execute, for example mceLink or Bold.
- * @param {Boolean} ui True/false state if a UI (dialog) should be presented or not.
- * @param {mixed} value Optional command value, this can be anything.
- * @param {Object} args Optional arguments object.
- */
- execCommand: function(cmd, ui, value, args) {
- return this.editorCommands.execCommand(cmd, ui, value, args);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return html;
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a command specific state, for example if bold is enabled or not.
- *
- * @method queryCommandState
- * @param {string} cmd Command to query state from.
- * @return {Boolean} Command specific state, for example if bold is enabled or not.
- */
- queryCommandState: function(cmd) {
- return this.editorCommands.queryCommandState(cmd);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Saves the contents from a editor out to the textarea or div element that got converted into an editor instance.
+ * This method will move the HTML contents from the editor into that textarea or div by getContent
+ * so all events etc that method has will get dispatched as well.
+ *
+ * @method save
+ * @param {Object} args Optional content object, this gets passed around through the whole save process.
+ * @return {String} HTML string that got set into the textarea/div.
+ */
+ save: function (args) {
+ var self = this, elm = self.getElement(), html, form;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a command specific value, for example the current font size.
- *
- * @method queryCommandValue
- * @param {string} cmd Command to query value from.
- * @return {Object} Command specific value, for example the current font size.
- */
- queryCommandValue: function(cmd) {
- return this.editorCommands.queryCommandValue(cmd);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!elm || !self.initialized) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the command is supported or not.
- *
- * @method queryCommandSupported
- * @param {String} cmd Command that we check support for.
- * @return {Boolean} true/false if the command is supported or not.
- */
- queryCommandSupported: function(cmd) {
- return this.editorCommands.queryCommandSupported(cmd);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args = args || {};
+ args.save = true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Shows the editor and hides any textarea/div that the editor is supposed to replace.
- *
- * @method show
- */
- show: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args.element = elm;
+ html = args.content = self.getContent(args);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.hidden) {
- self.hidden = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!args.no_events) {
+ self.fire('SaveContent', args);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.inline) {
- self.getBody().contentEditable = true;
- } else {
- DOM.show(self.getContainer());
- DOM.hide(self.id);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Always run this internal event
+ if (args.format == 'raw') {
+ self.fire('RawSaveContent', args);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.load();
- self.fire('show');
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ html = args.content;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Hides the editor and shows any textarea/div that the editor is supposed to replace.
- *
- * @method hide
- */
- hide: function() {
- var self = this, doc = self.getDoc();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!/TEXTAREA|INPUT/i.test(elm.nodeName)) {
+ // Update DIV element when not in inline mode
+ if (!self.inline) {
+ elm.innerHTML = html;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.hidden) {
- // Fixed bug where IE has a blinking cursor left from the editor
- if (ie && doc && !self.inline) {
- doc.execCommand('SelectAll');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Update hidden form element
+ if ((form = DOM.getParent(self.id, 'form'))) {
+ each(form.elements, function (elm) {
+ if (elm.name == self.id) {
+ elm.value = html;
+ return false;
+ }
+ });
+ }
+ } else {
+ elm.value = html;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // We must save before we hide so Safari doesn't crash
- self.save();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args.element = elm = null;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.inline) {
- self.getBody().contentEditable = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (args.set_dirty !== false) {
+ self.setDirty(false);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Make sure the editor gets blurred
- if (self == self.editorManager.focusedEditor) {
- self.editorManager.focusedEditor = null;
- }
- } else {
- DOM.hide(self.getContainer());
- DOM.setStyle(self.id, 'display', self.orgDisplay);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return html;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.hidden = true;
- self.fire('hide');
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets the specified content to the editor instance, this will cleanup the content before it gets set using
+ * the different cleanup rules options.
+ *
+ * @method setContent
+ * @param {String} content Content to set to editor, normally HTML contents but can be other formats as well.
+ * @param {Object} args Optional content object, this gets passed around through the whole set process.
+ * @return {String} HTML string that got set into the editor.
+ * @example
+ * // Sets the HTML contents of the activeEditor editor
+ * tinymce.activeEditor.setContent('<span>some</span> html');
+ *
+ * // Sets the raw contents of the activeEditor editor
+ * tinymce.activeEditor.setContent('<span>some</span> html', {format: 'raw'});
+ *
+ * // Sets the content of a specific editor (my_editor in this example)
+ * tinymce.get('my_editor').setContent(data);
+ *
+ * // Sets the bbcode contents of the activeEditor editor if the bbcode plugin was added
+ * tinymce.activeEditor.setContent('[b]some[/b] html', {format: 'bbcode'});
+ */
+ setContent: function (content, args) {
+ var self = this, body = self.getBody(), forcedRootBlockName, padd;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the editor is hidden or not.
- *
- * @method isHidden
- * @return {Boolean} True/false if the editor is hidden or not.
- */
- isHidden: function() {
- return !!this.hidden;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup args object
+ args = args || {};
+ args.format = args.format || 'html';
+ args.set = true;
+ args.content = content;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets the progress state, this will display a throbber/progess for the editor.
- * This is ideal for asynchronous operations like an AJAX save call.
- *
- * @method setProgressState
- * @param {Boolean} state Boolean state if the progress should be shown or hidden.
- * @param {Number} time Optional time to wait before the progress gets shown.
- * @return {Boolean} Same as the input state.
- * @example
- * // Show progress for the active editor
- * tinymce.activeEditor.setProgressState(true);
- *
- * // Hide progress for the active editor
- * tinymce.activeEditor.setProgressState(false);
- *
- * // Show progress after 3 seconds
- * tinymce.activeEditor.setProgressState(true, 3000);
- */
- setProgressState: function(state, time) {
- this.fire('ProgressState', {state: state, time: time});
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Do preprocessing
+ if (!args.no_events) {
+ self.fire('BeforeSetContent', args);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Loads contents from the textarea or div element that got converted into an editor instance.
- * This method will move the contents from that textarea or div into the editor by using setContent
- * so all events etc that method has will get dispatched as well.
- *
- * @method load
- * @param {Object} args Optional content object, this gets passed around through the whole load process.
- * @return {String} HTML string that got set into the editor.
- */
- load: function(args) {
- var self = this, elm = self.getElement(), html;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ content = args.content;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elm) {
- args = args || {};
- args.load = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Padd empty content in Gecko and Safari. Commands will otherwise fail on the content
+ // It will also be impossible to place the caret in the editor unless there is a BR element present
+ if (content.length === 0 || /^\s+$/.test(content)) {
+ padd = ie && ie < 11 ? '' : '<br data-mce-bogus="1">';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- html = self.setContent(elm.value !== undefined ? elm.value : elm.innerHTML, args);
- args.element = elm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Todo: There is a lot more root elements that need special padding
+ // so separate this and add all of them at some point.
+ if (body.nodeName == 'TABLE') {
+ content = '<tr><td>' + padd + '</td></tr>';
+ } else if (/^(UL|OL)$/.test(body.nodeName)) {
+ content = '<li>' + padd + '</li>';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!args.no_events) {
- self.fire('LoadContent', args);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ forcedRootBlockName = self.settings.forced_root_block;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args.element = elm = null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if forcedRootBlock is configured and that the block is a valid child of the body
+ if (forcedRootBlockName && self.schema.isValidChild(body.nodeName.toLowerCase(), forcedRootBlockName.toLowerCase())) {
+ // Padd with bogus BR elements on modern browsers and IE 7 and 8 since they don't render empty P tags properly
+ content = padd;
+ content = self.dom.createHTML(forcedRootBlockName, self.settings.forced_root_block_attrs, content);
+ } else if (!ie && !content) {
+ // We need to add a BR when forced_root_block is disabled on non IE browsers to place the caret
+ content = '<br data-mce-bogus="1">';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return html;
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.dom.setHTML(body, content);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Saves the contents from a editor out to the textarea or div element that got converted into an editor instance.
- * This method will move the HTML contents from the editor into that textarea or div by getContent
- * so all events etc that method has will get dispatched as well.
- *
- * @method save
- * @param {Object} args Optional content object, this gets passed around through the whole save process.
- * @return {String} HTML string that got set into the textarea/div.
- */
- save: function(args) {
- var self = this, elm = self.getElement(), html, form;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.fire('SetContent', args);
+ } else {
+ // Parse and serialize the html
+ if (args.format !== 'raw') {
+ content = new Serializer({
+ validate: self.validate
+ }, self.schema).serialize(
+ self.parser.parse(content, { isRootContent: true })
+ );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!elm || !self.initialized) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Set the new cleaned contents to the editor
+ args.content = trim(content);
+ self.dom.setHTML(body, args.content);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args = args || {};
- args.save = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Do post processing
+ if (!args.no_events) {
+ self.fire('SetContent', args);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args.element = elm;
- html = args.content = self.getContent(args);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't normalize selection if the focused element isn't the body in
+ // content editable mode since it will steal focus otherwise
+ /*if (!self.settings.content_editable || document.activeElement === self.getBody()) {
+ self.selection.normalize();
+ }*/
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!args.no_events) {
- self.fire('SaveContent', args);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return args.content;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Always run this internal event
- if (args.format == 'raw') {
- self.fire('RawSaveContent', args);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Gets the content from the editor instance, this will cleanup the content before it gets returned using
+ * the different cleanup rules options.
+ *
+ * @method getContent
+ * @param {Object} args Optional content object, this gets passed around through the whole get process.
+ * @return {String} Cleaned content string, normally HTML contents.
+ * @example
+ * // Get the HTML contents of the currently active editor
+ * console.debug(tinymce.activeEditor.getContent());
+ *
+ * // Get the raw contents of the currently active editor
+ * tinymce.activeEditor.getContent({format: 'raw'});
+ *
+ * // Get content of a specific editor:
+ * tinymce.get('content id').getContent()
+ */
+ getContent: function (args) {
+ var self = this, content, body = self.getBody();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- html = args.content;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup args object
+ args = args || {};
+ args.format = args.format || 'html';
+ args.get = true;
+ args.getInner = true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!/TEXTAREA|INPUT/i.test(elm.nodeName)) {
- // Update DIV element when not in inline mode
- if (!self.inline) {
- elm.innerHTML = html;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Do preprocessing
+ if (!args.no_events) {
+ self.fire('BeforeGetContent', args);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Update hidden form element
- if ((form = DOM.getParent(self.id, 'form'))) {
- each(form.elements, function(elm) {
- if (elm.name == self.id) {
- elm.value = html;
- return false;
- }
- });
- }
- } else {
- elm.value = html;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get raw contents or by default the cleaned contents
+ if (args.format == 'raw') {
+ content = Tools.trim(self.serializer.getTrimmedContent());
+ } else if (args.format == 'text') {
+ content = body.innerText || body.textContent;
+ } else {
+ content = self.serializer.serialize(body, args);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args.element = elm = null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Trim whitespace in beginning/end of HTML
+ if (args.format != 'text') {
+ args.content = trim(content);
+ } else {
+ args.content = content;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (args.set_dirty !== false) {
- self.setDirty(false);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Do post processing
+ if (!args.no_events) {
+ self.fire('GetContent', args);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return html;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return args.content;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets the specified content to the editor instance, this will cleanup the content before it gets set using
- * the different cleanup rules options.
- *
- * @method setContent
- * @param {String} content Content to set to editor, normally HTML contents but can be other formats as well.
- * @param {Object} args Optional content object, this gets passed around through the whole set process.
- * @return {String} HTML string that got set into the editor.
- * @example
- * // Sets the HTML contents of the activeEditor editor
- * tinymce.activeEditor.setContent('<span>some</span> html');
- *
- * // Sets the raw contents of the activeEditor editor
- * tinymce.activeEditor.setContent('<span>some</span> html', {format: 'raw'});
- *
- * // Sets the content of a specific editor (my_editor in this example)
- * tinymce.get('my_editor').setContent(data);
- *
- * // Sets the bbcode contents of the activeEditor editor if the bbcode plugin was added
- * tinymce.activeEditor.setContent('[b]some[/b] html', {format: 'bbcode'});
- */
- setContent: function(content, args) {
- var self = this, body = self.getBody(), forcedRootBlockName, padd;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Inserts content at caret position.
+ *
+ * @method insertContent
+ * @param {String} content Content to insert.
+ * @param {Object} args Optional args to pass to insert call.
+ */
+ insertContent: function (content, args) {
+ if (args) {
+ content = extend({ content: content }, args);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup args object
- args = args || {};
- args.format = args.format || 'html';
- args.set = true;
- args.content = content;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.execCommand('mceInsertContent', false, content);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Do preprocessing
- if (!args.no_events) {
- self.fire('BeforeSetContent', args);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the editor is dirty or not. It will get dirty if the user has made modifications to the contents.
+ *
+ * The dirty state is automatically set to true if you do modifications to the content in other
+ * words when new undo levels is created or if you undo/redo to update the contents of the editor. It will also be set
+ * to false if you call editor.save().
+ *
+ * @method isDirty
+ * @return {Boolean} True/false if the editor is dirty or not. It will get dirty if the user has made modifications to the contents.
+ * @example
+ * if (tinymce.activeEditor.isDirty())
+ * alert("You must save your contents.");
+ */
+ isDirty: function () {
+ return !this.isNotDirty;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- content = args.content;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Explicitly sets the dirty state. This will fire the dirty event if the editor dirty state is changed from false to true
+ * by invoking this method.
+ *
+ * @method setDirty
+ * @param {Boolean} state True/false if the editor is considered dirty.
+ * @example
+ * function ajaxSave() {
+ * var editor = tinymce.get('elm1');
+ *
+ * // Save contents using some XHR call
+ * alert(editor.getContent());
+ *
+ * editor.setDirty(false); // Force not dirty state
+ * }
+ */
+ setDirty: function (state) {
+ var oldState = !this.isNotDirty;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Padd empty content in Gecko and Safari. Commands will otherwise fail on the content
- // It will also be impossible to place the caret in the editor unless there is a BR element present
- if (content.length === 0 || /^\s+$/.test(content)) {
- padd = ie && ie < 11 ? '' : '<br data-mce-bogus="1">';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.isNotDirty = !state;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Todo: There is a lot more root elements that need special padding
- // so separate this and add all of them at some point.
- if (body.nodeName == 'TABLE') {
- content = '<tr><td>' + padd + '</td></tr>';
- } else if (/^(UL|OL)$/.test(body.nodeName)) {
- content = '<li>' + padd + '</li>';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (state && state != oldState) {
+ this.fire('dirty');
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- forcedRootBlockName = self.settings.forced_root_block;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets the editor mode. Mode can be for example "design", "code" or "readonly".
+ *
+ * @method setMode
+ * @param {String} mode Mode to set the editor in.
+ */
+ setMode: function (mode) {
+ Mode.setMode(this, mode);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if forcedRootBlock is configured and that the block is a valid child of the body
- if (forcedRootBlockName && self.schema.isValidChild(body.nodeName.toLowerCase(), forcedRootBlockName.toLowerCase())) {
- // Padd with bogus BR elements on modern browsers and IE 7 and 8 since they don't render empty P tags properly
- content = padd;
- content = self.dom.createHTML(forcedRootBlockName, self.settings.forced_root_block_attrs, content);
- } else if (!ie && !content) {
- // We need to add a BR when forced_root_block is disabled on non IE browsers to place the caret
- content = '<br data-mce-bogus="1">';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the editors container element. The container element wrappes in
+ * all the elements added to the page for the editor. Such as UI, iframe etc.
+ *
+ * @method getContainer
+ * @return {Element} HTML DOM element for the editor container.
+ */
+ getContainer: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.dom.setHTML(body, content);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.container) {
+ self.container = DOM.get(self.editorContainer || self.id + '_parent');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.fire('SetContent', args);
- } else {
- // Parse and serialize the html
- if (args.format !== 'raw') {
- content = new Serializer({
- validate: self.validate
- }, self.schema).serialize(
- self.parser.parse(content, {isRootContent: true})
- );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self.container;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Set the new cleaned contents to the editor
- args.content = trim(content);
- self.dom.setHTML(body, args.content);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the editors content area container element. The this element is the one who
+ * holds the iframe or the editable element.
+ *
+ * @method getContentAreaContainer
+ * @return {Element} HTML DOM element for the editor area container.
+ */
+ getContentAreaContainer: function () {
+ return this.contentAreaContainer;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Do post processing
- if (!args.no_events) {
- self.fire('SetContent', args);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the target element/textarea that got replaced with a TinyMCE editor instance.
+ *
+ * @method getElement
+ * @return {Element} HTML DOM element for the replaced element.
+ */
+ getElement: function () {
+ if (!this.targetElm) {
+ this.targetElm = DOM.get(this.id);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Don't normalize selection if the focused element isn't the body in
- // content editable mode since it will steal focus otherwise
- /*if (!self.settings.content_editable || document.activeElement === self.getBody()) {
- self.selection.normalize();
- }*/
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this.targetElm;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return args.content;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the iframes window object.
+ *
+ * @method getWin
+ * @return {Window} Iframe DOM window object.
+ */
+ getWin: function () {
+ var self = this, elm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Gets the content from the editor instance, this will cleanup the content before it gets returned using
- * the different cleanup rules options.
- *
- * @method getContent
- * @param {Object} args Optional content object, this gets passed around through the whole get process.
- * @return {String} Cleaned content string, normally HTML contents.
- * @example
- * // Get the HTML contents of the currently active editor
- * console.debug(tinymce.activeEditor.getContent());
- *
- * // Get the raw contents of the currently active editor
- * tinymce.activeEditor.getContent({format: 'raw'});
- *
- * // Get content of a specific editor:
- * tinymce.get('content id').getContent()
- */
- getContent: function(args) {
- var self = this, content, body = self.getBody();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.contentWindow) {
+ elm = self.iframeElement;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup args object
- args = args || {};
- args.format = args.format || 'html';
- args.get = true;
- args.getInner = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (elm) {
+ self.contentWindow = elm.contentWindow;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Do preprocessing
- if (!args.no_events) {
- self.fire('BeforeGetContent', args);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self.contentWindow;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Get raw contents or by default the cleaned contents
- if (args.format == 'raw') {
- content = Tools.trim(self.serializer.getTrimmedContent());
- } else if (args.format == 'text') {
- content = body.innerText || body.textContent;
- } else {
- content = self.serializer.serialize(body, args);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the iframes document object.
+ *
+ * @method getDoc
+ * @return {Document} Iframe DOM document object.
+ */
+ getDoc: function () {
+ var self = this, win;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Trim whitespace in beginning/end of HTML
- if (args.format != 'text') {
- args.content = trim(content);
- } else {
- args.content = content;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.contentDocument) {
+ win = self.getWin();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Do post processing
- if (!args.no_events) {
- self.fire('GetContent', args);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (win) {
+ self.contentDocument = win.document;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return args.content;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self.contentDocument;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Inserts content at caret position.
- *
- * @method insertContent
- * @param {String} content Content to insert.
- * @param {Object} args Optional args to pass to insert call.
- */
- insertContent: function(content, args) {
- if (args) {
- content = extend({content: content}, args);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the root element of the editable area.
+ * For a non-inline iframe-based editor, returns the iframe's body element.
+ *
+ * @method getBody
+ * @return {Element} The root element of the editable area.
+ */
+ getBody: function () {
+ var doc = this.getDoc();
+ return this.bodyElement || (doc ? doc.body : null);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.execCommand('mceInsertContent', false, content);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * URL converter function this gets executed each time a user adds an img, a or
+ * any other element that has a URL in it. This will be called both by the DOM and HTML
+ * manipulation functions.
+ *
+ * @method convertURL
+ * @param {string} url URL to convert.
+ * @param {string} name Attribute name src, href etc.
+ * @param {string/HTMLElement} elm Tag name or HTML DOM element depending on HTML or DOM insert.
+ * @return {string} Converted URL string.
+ */
+ convertURL: function (url, name, elm) {
+ var self = this, settings = self.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the editor is dirty or not. It will get dirty if the user has made modifications to the contents.
- *
- * The dirty state is automatically set to true if you do modifications to the content in other
- * words when new undo levels is created or if you undo/redo to update the contents of the editor. It will also be set
- * to false if you call editor.save().
- *
- * @method isDirty
- * @return {Boolean} True/false if the editor is dirty or not. It will get dirty if the user has made modifications to the contents.
- * @example
- * if (tinymce.activeEditor.isDirty())
- * alert("You must save your contents.");
- */
- isDirty: function() {
- return !this.isNotDirty;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Use callback instead
+ if (settings.urlconverter_callback) {
+ return self.execCallback('urlconverter_callback', url, elm, true, name);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Explicitly sets the dirty state. This will fire the dirty event if the editor dirty state is changed from false to true
- * by invoking this method.
- *
- * @method setDirty
- * @param {Boolean} state True/false if the editor is considered dirty.
- * @example
- * function ajaxSave() {
- * var editor = tinymce.get('elm1');
- *
- * // Save contents using some XHR call
- * alert(editor.getContent());
- *
- * editor.setDirty(false); // Force not dirty state
- * }
- */
- setDirty: function(state) {
- var oldState = !this.isNotDirty;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't convert link href since thats the CSS files that gets loaded into the editor also skip local file URLs
+ if (!settings.convert_urls || (elm && elm.nodeName == 'LINK') || url.indexOf('file:') === 0 || url.length === 0) {
+ return url;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.isNotDirty = !state;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Convert to relative
+ if (settings.relative_urls) {
+ return self.documentBaseURI.toRelative(url);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (state && state != oldState) {
- this.fire('dirty');
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Convert to absolute
+ url = self.documentBaseURI.toAbsolute(url, settings.remove_script_host);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets the editor mode. Mode can be for example "design", "code" or "readonly".
- *
- * @method setMode
- * @param {String} mode Mode to set the editor in.
- */
- setMode: function(mode) {
- Mode.setMode(this, mode);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return url;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the editors container element. The container element wrappes in
- * all the elements added to the page for the editor. Such as UI, iframe etc.
- *
- * @method getContainer
- * @return {Element} HTML DOM element for the editor container.
- */
- getContainer: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds visual aid for tables, anchors etc so they can be more easily edited inside the editor.
+ *
+ * @method addVisual
+ * @param {Element} elm Optional root element to loop though to find tables etc that needs the visual aid.
+ */
+ addVisual: function (elm) {
+ var self = this, settings = self.settings, dom = self.dom, cls;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.container) {
- self.container = DOM.get(self.editorContainer || self.id + '_parent');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elm = elm || self.getBody();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self.container;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.hasVisual === undefined) {
+ self.hasVisual = settings.visual;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the editors content area container element. The this element is the one who
- * holds the iframe or the editable element.
- *
- * @method getContentAreaContainer
- * @return {Element} HTML DOM element for the editor area container.
- */
- getContentAreaContainer: function() {
- return this.contentAreaContainer;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(dom.select('table,a', elm), function (elm) {
+ var value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the target element/textarea that got replaced with a TinyMCE editor instance.
- *
- * @method getElement
- * @return {Element} HTML DOM element for the replaced element.
- */
- getElement: function() {
- if (!this.targetElm) {
- this.targetElm = DOM.get(this.id);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ switch (elm.nodeName) {
+ case 'TABLE':
+ cls = settings.visual_table_class || 'mce-item-table';
+ value = dom.getAttrib(elm, 'border');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this.targetElm;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((!value || value == '0') && self.hasVisual) {
+ dom.addClass(elm, cls);
+ } else {
+ dom.removeClass(elm, cls);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the iframes window object.
- *
- * @method getWin
- * @return {Window} Iframe DOM window object.
- */
- getWin: function() {
- var self = this, elm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.contentWindow) {
- elm = self.iframeElement;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case 'A':
+ if (!dom.getAttrib(elm, 'href', false)) {
+ value = dom.getAttrib(elm, 'name') || elm.id;
+ cls = settings.visual_anchor_class || 'mce-item-anchor';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elm) {
- self.contentWindow = elm.contentWindow;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value && self.hasVisual) {
+ dom.addClass(elm, cls);
+ } else {
+ dom.removeClass(elm, cls);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self.contentWindow;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the iframes document object.
- *
- * @method getDoc
- * @return {Document} Iframe DOM document object.
- */
- getDoc: function() {
- var self = this, win;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.fire('VisualAid', { element: elm, hasVisual: self.hasVisual });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.contentDocument) {
- win = self.getWin();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes the editor from the dom and tinymce collection.
+ *
+ * @method remove
+ */
+ remove: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (win) {
- self.contentDocument = win.document;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.removed) {
+ self.save();
+ self.removed = 1;
+ self.unbindAllNativeEvents();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self.contentDocument;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove any hidden input
+ if (self.hasHiddenInput) {
+ DOM.remove(self.getElement().nextSibling);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the root element of the editable area.
- * For a non-inline iframe-based editor, returns the iframe's body element.
- *
- * @method getBody
- * @return {Element} The root element of the editable area.
- */
- getBody: function() {
- var doc = this.getDoc();
- return this.bodyElement || (doc ? doc.body : null);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.inline) {
+ // IE 9 has a bug where the selection stops working if you place the
+ // caret inside the editor then remove the iframe
+ if (ie && ie < 10) {
+ self.getDoc().execCommand('SelectAll', false, null);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * URL converter function this gets executed each time a user adds an img, a or
- * any other element that has a URL in it. This will be called both by the DOM and HTML
- * manipulation functions.
- *
- * @method convertURL
- * @param {string} url URL to convert.
- * @param {string} name Attribute name src, href etc.
- * @param {string/HTMLElement} elm Tag name or HTML DOM element depending on HTML or DOM insert.
- * @return {string} Converted URL string.
- */
- convertURL: function(url, name, elm) {
- var self = this, settings = self.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOM.setStyle(self.id, 'display', self.orgDisplay);
+ self.getBody().onload = null; // Prevent #6816
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Use callback instead
- if (settings.urlconverter_callback) {
- return self.execCallback('urlconverter_callback', url, elm, true, name);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.fire('remove');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Don't convert link href since thats the CSS files that gets loaded into the editor also skip local file URLs
- if (!settings.convert_urls || (elm && elm.nodeName == 'LINK') || url.indexOf('file:') === 0 || url.length === 0) {
- return url;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.editorManager.remove(self);
+ DOM.remove(self.getContainer());
+ self._selectionOverrides.destroy();
+ self.editorUpload.destroy();
+ self.destroy();
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Convert to relative
- if (settings.relative_urls) {
- return self.documentBaseURI.toRelative(url);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Destroys the editor instance by removing all events, element references or other resources
+ * that could leak memory. This method will be called automatically when the page is unloaded
+ * but you can also call it directly if you know what you are doing.
+ *
+ * @method destroy
+ * @param {Boolean} automatic Optional state if the destroy is an automatic destroy or user called one.
+ */
+ destroy: function (automatic) {
+ var self = this, form;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Convert to absolute
- url = self.documentBaseURI.toAbsolute(url, settings.remove_script_host);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // One time is enough
+ if (self.destroyed) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return url;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If user manually calls destroy and not remove
+ // Users seems to have logic that calls destroy instead of remove
+ if (!automatic && !self.removed) {
+ self.remove();
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds visual aid for tables, anchors etc so they can be more easily edited inside the editor.
- *
- * @method addVisual
- * @param {Element} elm Optional root element to loop though to find tables etc that needs the visual aid.
- */
- addVisual: function(elm) {
- var self = this, settings = self.settings, dom = self.dom, cls;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!automatic) {
+ self.editorManager.off('beforeunload', self._beforeUnload);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elm = elm || self.getBody();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Manual destroy
+ if (self.theme && self.theme.destroy) {
+ self.theme.destroy();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.hasVisual === undefined) {
- self.hasVisual = settings.visual;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Destroy controls, selection and dom
+ self.selection.destroy();
+ self.dom.destroy();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(dom.select('table,a', elm), function(elm) {
- var value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ form = self.formElement;
+ if (form) {
+ if (form._mceOldSubmit) {
+ form.submit = form._mceOldSubmit;
+ form._mceOldSubmit = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- switch (elm.nodeName) {
- case 'TABLE':
- cls = settings.visual_table_class || 'mce-item-table';
- value = dom.getAttrib(elm, 'border');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOM.unbind(form, 'submit reset', self.formEventDelegate);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ((!value || value == '0') && self.hasVisual) {
- dom.addClass(elm, cls);
- } else {
- dom.removeClass(elm, cls);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.contentAreaContainer = self.formElement = self.container = self.editorContainer = null;
+ self.bodyElement = self.contentDocument = self.contentWindow = null;
+ self.iframeElement = self.targetElm = null;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.selection) {
+ self.selection = self.selection.win = self.selection.dom = self.selection.dom.doc = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case 'A':
- if (!dom.getAttrib(elm, 'href', false)) {
- value = dom.getAttrib(elm, 'name') || elm.id;
- cls = settings.visual_anchor_class || 'mce-item-anchor';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.destroyed = 1;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value && self.hasVisual) {
- dom.addClass(elm, cls);
- } else {
- dom.removeClass(elm, cls);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Uploads all data uri/blob uri images in the editor contents to server.
+ *
+ * @method uploadImages
+ * @param {function} callback Optional callback with images and status for each image.
+ * @return {tinymce.util.Promise} Promise instance.
+ */
+ uploadImages: function (callback) {
+ return this.editorUpload.uploadImages(callback);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Internal functions
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.fire('VisualAid', {element: elm, hasVisual: self.hasVisual});
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ _scanForImages: function () {
+ return this.editorUpload.scanForImages();
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes the editor from the dom and tinymce collection.
- *
- * @method remove
- */
- remove: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ extend(Editor.prototype, EditorObservable);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.removed) {
- self.save();
- self.removed = 1;
- self.unbindAllNativeEvents();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Editor;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove any hidden input
- if (self.hasHiddenInput) {
- DOM.remove(self.getElement().nextSibling);
- }
-
- if (!self.inline) {
- // IE 9 has a bug where the selection stops working if you place the
- // caret inside the editor then remove the iframe
- if (ie && ie < 10) {
- self.getDoc().execCommand('SelectAll', false, null);
- }
-
- DOM.setStyle(self.id, 'display', self.orgDisplay);
- self.getBody().onload = null; // Prevent #6816
- }
-
- self.fire('remove');
-
- self.editorManager.remove(self);
- DOM.remove(self.getContainer());
- self._selectionOverrides.destroy();
- self.editorUpload.destroy();
- self.destroy();
- }
- },
-
- /**
- * Destroys the editor instance by removing all events, element references or other resources
- * that could leak memory. This method will be called automatically when the page is unloaded
- * but you can also call it directly if you know what you are doing.
- *
- * @method destroy
- * @param {Boolean} automatic Optional state if the destroy is an automatic destroy or user called one.
- */
- destroy: function(automatic) {
- var self = this, form;
-
- // One time is enough
- if (self.destroyed) {
- return;
- }
-
- // If user manually calls destroy and not remove
- // Users seems to have logic that calls destroy instead of remove
- if (!automatic && !self.removed) {
- self.remove();
- return;
- }
-
- if (!automatic) {
- self.editorManager.off('beforeunload', self._beforeUnload);
-
- // Manual destroy
- if (self.theme && self.theme.destroy) {
- self.theme.destroy();
- }
-
- // Destroy controls, selection and dom
- self.selection.destroy();
- self.dom.destroy();
- }
-
- form = self.formElement;
- if (form) {
- if (form._mceOldSubmit) {
- form.submit = form._mceOldSubmit;
- form._mceOldSubmit = null;
- }
-
- DOM.unbind(form, 'submit reset', self.formEventDelegate);
- }
-
- self.contentAreaContainer = self.formElement = self.container = self.editorContainer = null;
- self.bodyElement = self.contentDocument = self.contentWindow = null;
- self.iframeElement = self.targetElm = null;
-
- if (self.selection) {
- self.selection = self.selection.win = self.selection.dom = self.selection.dom.doc = null;
- }
-
- self.destroyed = 1;
- },
-
- /**
- * Uploads all data uri/blob uri images in the editor contents to server.
- *
- * @method uploadImages
- * @param {function} callback Optional callback with images and status for each image.
- * @return {tinymce.util.Promise} Promise instance.
- */
- uploadImages: function(callback) {
- return this.editorUpload.uploadImages(callback);
- },
-
- // Internal functions
-
- _scanForImages: function() {
- return this.editorUpload.scanForImages();
- }
- };
-
- extend(Editor.prototype, EditorObservable);
-
- return Editor;
-});
-
-// Included from: js/tinymce/classes/util/I18n.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * I18n.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -40456,138 +45332,139 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.util.I18n
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/util/I18n", [
- "tinymce/util/Tools"
-], function(Tools) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.I18n',
+ [
+ "tinymce.core.util.Tools"
+ ],
+ function (Tools) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var data = {}, code = "en";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var data = {}, code = "en";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- /**
- * Sets the current language code.
- *
- * @method setCode
- * @param {String} newCode Current language code.
- */
- setCode: function(newCode) {
- if (newCode) {
- code = newCode;
- this.rtl = this.data[newCode] ? this.data[newCode]._dir === 'rtl' : false;
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ /**
+ * Sets the current language code.
+ *
+ * @method setCode
+ * @param {String} newCode Current language code.
+ */
+ setCode: function (newCode) {
+ if (newCode) {
+ code = newCode;
+ this.rtl = this.data[newCode] ? this.data[newCode]._dir === 'rtl' : false;
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the current language code.
- *
- * @method getCode
- * @return {String} Current language code.
- */
- getCode: function() {
- return code;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the current language code.
+ *
+ * @method getCode
+ * @return {String} Current language code.
+ */
+ getCode: function () {
+ return code;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Property gets set to true if a RTL language pack was loaded.
- *
- * @property rtl
- * @type Boolean
- */
- rtl: false,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Property gets set to true if a RTL language pack was loaded.
+ *
+ * @property rtl
+ * @type Boolean
+ */
+ rtl: false,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds translations for a specific language code.
- *
- * @method add
- * @param {String} code Language code like sv_SE.
- * @param {Array} items Name/value array with English en_US to sv_SE.
- */
- add: function(code, items) {
- var langData = data[code];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds translations for a specific language code.
+ *
+ * @method add
+ * @param {String} code Language code like sv_SE.
+ * @param {Array} items Name/value array with English en_US to sv_SE.
+ */
+ add: function (code, items) {
+ var langData = data[code];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!langData) {
- data[code] = langData = {};
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!langData) {
+ data[code] = langData = {};
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var name in items) {
- langData[name] = items[name];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (var name in items) {
+ langData[name] = items[name];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.setCode(code);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.setCode(code);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Translates the specified text.
- *
- * It has a few formats:
- * I18n.translate("Text");
- * I18n.translate(["Text {0}/{1}", 0, 1]);
- * I18n.translate({raw: "Raw string"});
- *
- * @method translate
- * @param {String/Object/Array} text Text to translate.
- * @return {String} String that got translated.
- */
- translate: function(text) {
- var langData = data[code] || {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Translates the specified text.
+ *
+ * It has a few formats:
+ * I18n.translate("Text");
+ * I18n.translate(["Text {0}/{1}", 0, 1]);
+ * I18n.translate({raw: "Raw string"});
+ *
+ * @method translate
+ * @param {String/Object/Array} text Text to translate.
+ * @return {String} String that got translated.
+ */
+ translate: function (text) {
+ var langData = data[code] || {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * number - string
- * null, undefined and empty string - empty string
- * array - comma-delimited string
- * object - in [object Object]
- * function - in [object Function]
- *
- * @param obj
- * @returns {string}
- */
- function toString(obj) {
- if (Tools.is(obj, 'function')) {
- return Object.prototype.toString.call(obj);
- }
- return !isEmpty(obj) ? '' + obj : '';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * number - string
+ * null, undefined and empty string - empty string
+ * array - comma-delimited string
+ * object - in [object Object]
+ * function - in [object Function]
+ *
+ * @param obj
+ * @returns {string}
+ */
+ function toString(obj) {
+ if (Tools.is(obj, 'function')) {
+ return Object.prototype.toString.call(obj);
+ }
+ return !isEmpty(obj) ? '' + obj : '';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isEmpty(text) {
- return text === '' || text === null || Tools.is(text, 'undefined');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isEmpty(text) {
+ return text === '' || text === null || Tools.is(text, 'undefined');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getLangData(text) {
- // make sure we work on a string and return a string
- text = toString(text);
- return Tools.hasOwn(langData, text) ? toString(langData[text]) : text;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getLangData(text) {
+ // make sure we work on a string and return a string
+ text = toString(text);
+ return Tools.hasOwn(langData, text) ? toString(langData[text]) : text;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isEmpty(text)) {
- return '';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isEmpty(text)) {
+ return '';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (Tools.is(text, 'object') && Tools.hasOwn(text, 'raw')) {
- return toString(text.raw);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (Tools.is(text, 'object') && Tools.hasOwn(text, 'raw')) {
+ return toString(text.raw);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (Tools.is(text, 'array')) {
- var values = text.slice(1);
- text = getLangData(text[0]).replace(/\{([0-9]+)\}/g, function($1, $2) {
- return Tools.hasOwn(values, $2) ? toString(values[$2]) : $1;
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (Tools.is(text, 'array')) {
+ var values = text.slice(1);
+ text = getLangData(text[0]).replace(/\{([0-9]+)\}/g, function ($1, $2) {
+ return Tools.hasOwn(values, $2) ? toString(values[$2]) : $1;
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return getLangData(text).replace(/{context:\w+}$/, '');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return getLangData(text).replace(/{context:\w+}$/, '');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- data: data
- };
-});
-
-// Included from: js/tinymce/classes/FocusManager.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ data: data
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * FocusManager.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -40602,1101 +45479,1124 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.FocusManager
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/FocusManager", [
- "tinymce/dom/DOMUtils",
- "tinymce/util/Delay",
- "tinymce/Env"
-], function(DOMUtils, Delay, Env) {
- var selectionChangeHandler, documentFocusInHandler, documentMouseUpHandler, DOM = DOMUtils.DOM;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.FocusManager',
+ [
+ "tinymce.core.dom.DOMUtils",
+ "tinymce.core.util.Delay",
+ "tinymce.core.Env"
+ ],
+ function (DOMUtils, Delay, Env) {
+ var selectionChangeHandler, documentFocusInHandler, documentMouseUpHandler, DOM = DOMUtils.DOM;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isUIElement = function (editor, elm) {
- var customSelector = editor ? editor.settings.custom_ui_selector : '';
- var parent = DOM.getParent(elm, function (elm) {
- return (
- FocusManager.isEditorUIElement(elm) ||
- (customSelector ? editor.dom.is(elm, customSelector) : false)
- );
- });
- return parent !== null;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isUIElement = function (editor, elm) {
+ var customSelector = editor ? editor.settings.custom_ui_selector : '';
+ var parent = DOM.getParent(elm, function (elm) {
+ return (
+ FocusManager.isEditorUIElement(elm) ||
+ (customSelector ? editor.dom.is(elm, customSelector) : false)
+ );
+ });
+ return parent !== null;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a new focus manager instance.
- *
- * @constructor FocusManager
- * @param {tinymce.EditorManager} editorManager Editor manager instance to handle focus for.
- */
- function FocusManager(editorManager) {
- function getActiveElement() {
- try {
- return document.activeElement;
- } catch (ex) {
- // IE sometimes fails to get the activeElement when resizing table
- // TODO: Investigate this
- return document.body;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isInlineEditor = function (editor) {
+ return editor.inline === true;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // We can't store a real range on IE 11 since it gets mutated so we need to use a bookmark object
- // TODO: Move this to a separate range utils class since it's it's logic is present in Selection as well.
- function createBookmark(dom, rng) {
- if (rng && rng.startContainer) {
- // Verify that the range is within the root of the editor
- if (!dom.isChildOf(rng.startContainer, dom.getRoot()) || !dom.isChildOf(rng.endContainer, dom.getRoot())) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isElementOursideInlineEditor = function (editor, target) {
+ return isInlineEditor(editor) === false || editor.dom.isChildOf(target, editor.getBody()) === false;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- startContainer: rng.startContainer,
- startOffset: rng.startOffset,
- endContainer: rng.endContainer,
- endOffset: rng.endOffset
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a new focus manager instance.
+ *
+ * @constructor FocusManager
+ * @param {tinymce.EditorManager} editorManager Editor manager instance to handle focus for.
+ */
+ function FocusManager(editorManager) {
+ function getActiveElement() {
+ try {
+ return document.activeElement;
+ } catch (ex) {
+ // IE sometimes fails to get the activeElement when resizing table
+ // TODO: Investigate this
+ return document.body;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return rng;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // We can't store a real range on IE 11 since it gets mutated so we need to use a bookmark object
+ // TODO: Move this to a separate range utils class since it's it's logic is present in Selection as well.
+ function createBookmark(dom, rng) {
+ if (rng && rng.startContainer) {
+ // Verify that the range is within the root of the editor
+ if (!dom.isChildOf(rng.startContainer, dom.getRoot()) || !dom.isChildOf(rng.endContainer, dom.getRoot())) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function bookmarkToRng(editor, bookmark) {
- var rng;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ startContainer: rng.startContainer,
+ startOffset: rng.startOffset,
+ endContainer: rng.endContainer,
+ endOffset: rng.endOffset
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (bookmark.startContainer) {
- rng = editor.getDoc().createRange();
- rng.setStart(bookmark.startContainer, bookmark.startOffset);
- rng.setEnd(bookmark.endContainer, bookmark.endOffset);
- } else {
- rng = bookmark;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return rng;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return rng;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function bookmarkToRng(editor, bookmark) {
+ var rng;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function registerEvents(e) {
- var editor = e.editor;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (bookmark.startContainer) {
+ rng = editor.getDoc().createRange();
+ rng.setStart(bookmark.startContainer, bookmark.startOffset);
+ rng.setEnd(bookmark.endContainer, bookmark.endOffset);
+ } else {
+ rng = bookmark;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('init', function() {
- // Gecko/WebKit has ghost selections in iframes and IE only has one selection per browser tab
- if (editor.inline || Env.ie) {
- // Use the onbeforedeactivate event when available since it works better see #7023
- if ("onbeforedeactivate" in document && Env.ie < 9) {
- editor.dom.bind(editor.getBody(), 'beforedeactivate', function(e) {
- if (e.target != editor.getBody()) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return rng;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- try {
- editor.lastRng = editor.selection.getRng();
- } catch (ex) {
- // IE throws "Unexcpected call to method or property access" some times so lets ignore it
- }
- });
- } else {
- // On other browsers take snapshot on nodechange in inline mode since they have Ghost selections for iframes
- editor.on('nodechange mouseup keyup', function(e) {
- var node = getActiveElement();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function registerEvents(e) {
+ var editor = e.editor;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Only act on manual nodechanges
- if (e.type == 'nodechange' && e.selectionChange) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('init', function () {
+ // Gecko/WebKit has ghost selections in iframes and IE only has one selection per browser tab
+ if (editor.inline || Env.ie) {
+ // Use the onbeforedeactivate event when available since it works better see #7023
+ if ("onbeforedeactivate" in document && Env.ie < 9) {
+ editor.dom.bind(editor.getBody(), 'beforedeactivate', function (e) {
+ if (e.target != editor.getBody()) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // IE 11 reports active element as iframe not body of iframe
- if (node && node.id == editor.id + '_ifr') {
- node = editor.getBody();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ try {
+ editor.lastRng = editor.selection.getRng();
+ } catch (ex) {
+ // IE throws "Unexcpected call to method or property access" some times so lets ignore it
+ }
+ });
+ } else {
+ // On other browsers take snapshot on nodechange in inline mode since they have Ghost selections for iframes
+ editor.on('nodechange mouseup keyup', function (e) {
+ var node = getActiveElement();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.dom.isChildOf(node, editor.getBody())) {
- editor.lastRng = editor.selection.getRng();
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Only act on manual nodechanges
+ if (e.type == 'nodechange' && e.selectionChange) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handles the issue with WebKit not retaining selection within inline document
- // If the user releases the mouse out side the body since a mouse up event wont occur on the body
- if (Env.webkit && !selectionChangeHandler) {
- selectionChangeHandler = function() {
- var activeEditor = editorManager.activeEditor;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // IE 11 reports active element as iframe not body of iframe
+ if (node && node.id == editor.id + '_ifr') {
+ node = editor.getBody();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (activeEditor && activeEditor.selection) {
- var rng = activeEditor.selection.getRng();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.dom.isChildOf(node, editor.getBody())) {
+ editor.lastRng = editor.selection.getRng();
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Store when it's non collapsed
- if (rng && !rng.collapsed) {
- editor.lastRng = rng;
- }
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handles the issue with WebKit not retaining selection within inline document
+ // If the user releases the mouse out side the body since a mouse up event wont occur on the body
+ if (Env.webkit && !selectionChangeHandler) {
+ selectionChangeHandler = function () {
+ var activeEditor = editorManager.activeEditor;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DOM.bind(document, 'selectionchange', selectionChangeHandler);
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (activeEditor && activeEditor.selection) {
+ var rng = activeEditor.selection.getRng();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('setcontent', function() {
- editor.lastRng = null;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Store when it's non collapsed
+ if (rng && !rng.collapsed) {
+ editor.lastRng = rng;
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove last selection bookmark on mousedown see #6305
- editor.on('mousedown', function() {
- editor.selection.lastFocusBookmark = null;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOM.bind(document, 'selectionchange', selectionChangeHandler);
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('focusin', function() {
- var focusedEditor = editorManager.focusedEditor, lastRng;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('setcontent', function () {
+ editor.lastRng = null;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.selection.lastFocusBookmark) {
- lastRng = bookmarkToRng(editor, editor.selection.lastFocusBookmark);
- editor.selection.lastFocusBookmark = null;
- editor.selection.setRng(lastRng);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove last selection bookmark on mousedown see #6305
+ editor.on('mousedown', function () {
+ editor.selection.lastFocusBookmark = null;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (focusedEditor != editor) {
- if (focusedEditor) {
- focusedEditor.fire('blur', {focusedEditor: editor});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('focusin', function () {
+ var focusedEditor = editorManager.focusedEditor, lastRng;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editorManager.setActive(editor);
- editorManager.focusedEditor = editor;
- editor.fire('focus', {blurredEditor: focusedEditor});
- editor.focus(true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.selection.lastFocusBookmark) {
+ lastRng = bookmarkToRng(editor, editor.selection.lastFocusBookmark);
+ editor.selection.lastFocusBookmark = null;
+ editor.selection.setRng(lastRng);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.lastRng = null;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (focusedEditor != editor) {
+ if (focusedEditor) {
+ focusedEditor.fire('blur', { focusedEditor: editor });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('focusout', function() {
- Delay.setEditorTimeout(editor, function() {
- var focusedEditor = editorManager.focusedEditor;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editorManager.setActive(editor);
+ editorManager.focusedEditor = editor;
+ editor.fire('focus', { blurredEditor: focusedEditor });
+ editor.focus(true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Still the same editor the blur was outside any editor UI
- if (!isUIElement(editor, getActiveElement()) && focusedEditor == editor) {
- editor.fire('blur', {focusedEditor: null});
- editorManager.focusedEditor = null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.lastRng = null;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Make sure selection is valid could be invalid if the editor is blured and removed before the timeout occurs
- if (editor.selection) {
- editor.selection.lastFocusBookmark = null;
- }
- }
- });
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('focusout', function () {
+ Delay.setEditorTimeout(editor, function () {
+ var focusedEditor = editorManager.focusedEditor;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if focus is moved to an element outside the active editor by checking if the target node
- // isn't within the body of the activeEditor nor a UI element such as a dialog child control
- if (!documentFocusInHandler) {
- documentFocusInHandler = function(e) {
- var activeEditor = editorManager.activeEditor, target;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Still the same editor the blur was outside any editor UI
+ if (!isUIElement(editor, getActiveElement()) && focusedEditor == editor) {
+ editor.fire('blur', { focusedEditor: null });
+ editorManager.focusedEditor = null;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- target = e.target;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Make sure selection is valid could be invalid if the editor is blured and removed before the timeout occurs
+ if (editor.selection) {
+ editor.selection.lastFocusBookmark = null;
+ }
+ }
+ });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (activeEditor && target.ownerDocument == document) {
- // Check to make sure we have a valid selection don't update the bookmark if it's
- // a focusin to the body of the editor see #7025
- if (activeEditor.selection && target != activeEditor.getBody()) {
- activeEditor.selection.lastFocusBookmark = createBookmark(activeEditor.dom, activeEditor.lastRng);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if focus is moved to an element outside the active editor by checking if the target node
+ // isn't within the body of the activeEditor nor a UI element such as a dialog child control
+ if (!documentFocusInHandler) {
+ documentFocusInHandler = function (e) {
+ var activeEditor = editorManager.activeEditor, target;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Fire a blur event if the element isn't a UI element
- if (target != document.body && !isUIElement(activeEditor, target) && editorManager.focusedEditor == activeEditor) {
- activeEditor.fire('blur', {focusedEditor: null});
- editorManager.focusedEditor = null;
- }
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ target = e.target;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DOM.bind(document, 'focusin', documentFocusInHandler);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (activeEditor && target.ownerDocument === document) {
+ // Check to make sure we have a valid selection don't update the bookmark if it's
+ // a focusin to the body of the editor see #7025
+ if (activeEditor.selection && target !== activeEditor.getBody() && isElementOursideInlineEditor(editor, target)) {
+ activeEditor.selection.lastFocusBookmark = createBookmark(activeEditor.dom, activeEditor.lastRng);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle edge case when user starts the selection inside the editor and releases
- // the mouse outside the editor producing a new selection. This weird workaround is needed since
- // Gecko doesn't have the "selectionchange" event we need to do this. Fixes: #6843
- if (editor.inline && !documentMouseUpHandler) {
- documentMouseUpHandler = function(e) {
- var activeEditor = editorManager.activeEditor, dom = activeEditor.dom;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Fire a blur event if the element isn't a UI element
+ if (target !== document.body && !isUIElement(activeEditor, target) && editorManager.focusedEditor === activeEditor) {
+ activeEditor.fire('blur', { focusedEditor: null });
+ editorManager.focusedEditor = null;
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (activeEditor.inline && dom && !dom.isChildOf(e.target, activeEditor.getBody())) {
- var rng = activeEditor.selection.getRng();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOM.bind(document, 'focusin', documentFocusInHandler);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!rng.collapsed) {
- activeEditor.lastRng = rng;
- }
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handle edge case when user starts the selection inside the editor and releases
+ // the mouse outside the editor producing a new selection. This weird workaround is needed since
+ // Gecko doesn't have the "selectionchange" event we need to do this. Fixes: #6843
+ if (editor.inline && !documentMouseUpHandler) {
+ documentMouseUpHandler = function (e) {
+ var activeEditor = editorManager.activeEditor, dom = activeEditor.dom;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DOM.bind(document, 'mouseup', documentMouseUpHandler);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (activeEditor.inline && dom && !dom.isChildOf(e.target, activeEditor.getBody())) {
+ var rng = activeEditor.selection.getRng();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function unregisterDocumentEvents(e) {
- if (editorManager.focusedEditor == e.editor) {
- editorManager.focusedEditor = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!rng.collapsed) {
+ activeEditor.lastRng = rng;
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!editorManager.activeEditor) {
- DOM.unbind(document, 'selectionchange', selectionChangeHandler);
- DOM.unbind(document, 'focusin', documentFocusInHandler);
- DOM.unbind(document, 'mouseup', documentMouseUpHandler);
- selectionChangeHandler = documentFocusInHandler = documentMouseUpHandler = null;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOM.bind(document, 'mouseup', documentMouseUpHandler);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editorManager.on('AddEditor', registerEvents);
- editorManager.on('RemoveEditor', unregisterDocumentEvents);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function unregisterDocumentEvents(e) {
+ if (editorManager.focusedEditor == e.editor) {
+ editorManager.focusedEditor = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true if the specified element is part of the UI for example an button or text input.
- *
- * @method isEditorUIElement
- * @param {Element} elm Element to check if it's part of the UI or not.
- * @return {Boolean} True/false state if the element is part of the UI or not.
- */
- FocusManager.isEditorUIElement = function(elm) {
- // Needs to be converted to string since svg can have focus: #6776
- return elm.className.toString().indexOf('mce-') !== -1;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!editorManager.activeEditor) {
+ DOM.unbind(document, 'selectionchange', selectionChangeHandler);
+ DOM.unbind(document, 'focusin', documentFocusInHandler);
+ DOM.unbind(document, 'mouseup', documentMouseUpHandler);
+ selectionChangeHandler = documentFocusInHandler = documentMouseUpHandler = null;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- FocusManager._isUIElement = isUIElement;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editorManager.on('AddEditor', registerEvents);
+ editorManager.on('RemoveEditor', unregisterDocumentEvents);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return FocusManager;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true if the specified element is part of the UI for example an button or text input.
+ *
+ * @method isEditorUIElement
+ * @param {Element} elm Element to check if it's part of the UI or not.
+ * @return {Boolean} True/false state if the element is part of the UI or not.
+ */
+ FocusManager.isEditorUIElement = function (elm) {
+ // Needs to be converted to string since svg can have focus: #6776
+ return elm.className.toString().indexOf('mce-') !== -1;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/EditorManager.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ FocusManager._isUIElement = isUIElement;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return FocusManager;
+ }
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * EditorManager.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * LegacyInput.js
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * This class used as a factory for manager for tinymce.Editor instances.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Converts legacy input to modern HTML.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @example
- * tinymce.EditorManager.init({});
- *
- * @class tinymce.EditorManager
- * @mixes tinymce.util.Observable
- * @static
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @class tinymce.LegacyInput
+ * @private
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/EditorManager", [
- "tinymce/Editor",
- "tinymce/dom/DomQuery",
- "tinymce/dom/DOMUtils",
- "tinymce/util/URI",
- "tinymce/Env",
- "tinymce/util/Tools",
- "tinymce/util/Promise",
- "tinymce/util/Observable",
- "tinymce/util/I18n",
- "tinymce/FocusManager",
- "tinymce/AddOnManager"
-], function(Editor, $, DOMUtils, URI, Env, Tools, Promise, Observable, I18n, FocusManager, AddOnManager) {
- var DOM = DOMUtils.DOM;
- var explode = Tools.explode, each = Tools.each, extend = Tools.extend;
- var instanceCounter = 0, beforeUnloadDelegate, EditorManager, boundGlobalEvents = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.LegacyInput',
+ [
+ "tinymce.core.util.Tools"
+ ],
+ function (Tools) {
+ var each = Tools.each, explode = Tools.explode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function globalEventDelegate(e) {
- each(EditorManager.editors, function(editor) {
- if (e.type === 'scroll') {
- editor.fire('ScrollWindow', e);
- } else {
- editor.fire('ResizeWindow', e);
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var register = function (EditorManager) {
+ EditorManager.on('AddEditor', function (e) {
+ var editor = e.editor;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function toggleGlobalEvents(editors, state) {
- if (state !== boundGlobalEvents) {
- if (state) {
- $(window).on('resize scroll', globalEventDelegate);
- } else {
- $(window).off('resize scroll', globalEventDelegate);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('preInit', function () {
+ var filters, fontSizes, dom, settings = editor.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- boundGlobalEvents = state;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function replaceWithSpan(node, styles) {
+ each(styles, function (value, name) {
+ if (value) {
+ dom.setStyle(node, name, value);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function removeEditorFromList(editor) {
- var editors = EditorManager.editors, removedFromList;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.rename(node, 'span');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- delete editors[editor.id];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function convert(e) {
+ dom = editor.dom;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var i = 0; i < editors.length; i++) {
- if (editors[i] == editor) {
- editors.splice(i, 1);
- removedFromList = true;
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.convert_fonts_to_spans) {
+ each(dom.select('font,u,strike', e.node), function (node) {
+ filters[node.nodeName.toLowerCase()](dom, node);
+ });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Select another editor since the active one was removed
- if (EditorManager.activeEditor == editor) {
- EditorManager.activeEditor = editors[0];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.inline_styles) {
+ fontSizes = explode(settings.font_size_legacy_values);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Clear focusedEditor if necessary, so that we don't try to blur the destroyed editor
- if (EditorManager.focusedEditor == editor) {
- EditorManager.focusedEditor = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ filters = {
+ font: function (dom, node) {
+ replaceWithSpan(node, {
+ backgroundColor: node.style.backgroundColor,
+ color: node.color,
+ fontFamily: node.face,
+ fontSize: fontSizes[parseInt(node.size, 10) - 1]
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return removedFromList;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ u: function (dom, node) {
+ // HTML5 allows U element
+ if (editor.settings.schema === "html4") {
+ replaceWithSpan(node, {
+ textDecoration: 'underline'
+ });
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function purgeDestroyedEditor(editor) {
- // User has manually destroyed the editor lets clean up the mess
- if (editor && editor.initialized && !(editor.getContainer() || editor.getBody()).parentNode) {
- removeEditorFromList(editor);
- editor.unbindAllNativeEvents();
- editor.destroy(true);
- editor.removed = true;
- editor = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ strike: function (dom, node) {
+ replaceWithSpan(node, {
+ textDecoration: 'line-through'
+ });
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return editor;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('PreProcess SetContent', convert);
+ }
+ });
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- EditorManager = {
- /**
- * Dom query instance.
- *
- * @property $
- * @type tinymce.dom.DomQuery
- */
- $: $,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ register: register
+ };
+ }
+);
+/**
+ * EditorManager.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Major version of TinyMCE build.
- *
- * @property majorVersion
- * @type String
- */
- majorVersion: '4',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * This class used as a factory for manager for tinymce.Editor instances.
+ *
+ * @example
+ * tinymce.EditorManager.init({});
+ *
+ * @class tinymce.EditorManager
+ * @mixes tinymce.util.Observable
+ * @static
+ */
+define(
+ 'tinymce.core.EditorManager',
+ [
+ 'tinymce.core.AddOnManager',
+ 'tinymce.core.dom.DomQuery',
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.core.Editor',
+ 'tinymce.core.Env',
+ 'tinymce.core.ErrorReporter',
+ 'tinymce.core.FocusManager',
+ 'tinymce.core.LegacyInput',
+ 'tinymce.core.util.I18n',
+ 'tinymce.core.util.Observable',
+ 'tinymce.core.util.Promise',
+ 'tinymce.core.util.Tools',
+ 'tinymce.core.util.URI'
+ ],
+ function (AddOnManager, DomQuery, DOMUtils, Editor, Env, ErrorReporter, FocusManager, LegacyInput, I18n, Observable, Promise, Tools, URI) {
+ var DOM = DOMUtils.DOM;
+ var explode = Tools.explode, each = Tools.each, extend = Tools.extend;
+ var instanceCounter = 0, beforeUnloadDelegate, EditorManager, boundGlobalEvents = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Minor version of TinyMCE build.
- *
- * @property minorVersion
- * @type String
- */
- minorVersion: '5.6',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function globalEventDelegate(e) {
+ each(EditorManager.editors, function (editor) {
+ if (e.type === 'scroll') {
+ editor.fire('ScrollWindow', e);
+ } else {
+ editor.fire('ResizeWindow', e);
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Release date of TinyMCE build.
- *
- * @property releaseDate
- * @type String
- */
- releaseDate: '2017-03-30',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function toggleGlobalEvents(editors, state) {
+ if (state !== boundGlobalEvents) {
+ if (state) {
+ DomQuery(window).on('resize scroll', globalEventDelegate);
+ } else {
+ DomQuery(window).off('resize scroll', globalEventDelegate);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Collection of editor instances.
- *
- * @property editors
- * @type Object
- * @example
- * for (edId in tinymce.editors)
- * tinymce.editors[edId].save();
- */
- editors: [],
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ boundGlobalEvents = state;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Collection of language pack data.
- *
- * @property i18n
- * @type Object
- */
- i18n: I18n,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function removeEditorFromList(editor) {
+ var editors = EditorManager.editors, removedFromList;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Currently active editor instance.
- *
- * @property activeEditor
- * @type tinymce.Editor
- * @example
- * tinyMCE.activeEditor.selection.getContent();
- * tinymce.EditorManager.activeEditor.selection.getContent();
- */
- activeEditor: null,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ delete editors[editor.id];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- setup: function() {
- var self = this, baseURL, documentBaseURL, suffix = "", preInit, src;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (var i = 0; i < editors.length; i++) {
+ if (editors[i] == editor) {
+ editors.splice(i, 1);
+ removedFromList = true;
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Get base URL for the current document
- documentBaseURL = URI.getDocumentBaseUrl(document.location);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Select another editor since the active one was removed
+ if (EditorManager.activeEditor == editor) {
+ EditorManager.activeEditor = editors[0];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if the URL is a document based format like: http://site/dir/file and file:///
- // leave other formats like applewebdata://... intact
- if (/^[^:]+:\/\/\/?[^\/]+\//.test(documentBaseURL)) {
- documentBaseURL = documentBaseURL.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Clear focusedEditor if necessary, so that we don't try to blur the destroyed editor
+ if (EditorManager.focusedEditor == editor) {
+ EditorManager.focusedEditor = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!/[\/\\]$/.test(documentBaseURL)) {
- documentBaseURL += '/';
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return removedFromList;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If tinymce is defined and has a base use that or use the old tinyMCEPreInit
- preInit = window.tinymce || window.tinyMCEPreInit;
- if (preInit) {
- baseURL = preInit.base || preInit.baseURL;
- suffix = preInit.suffix;
- } else {
- // Get base where the tinymce script is located
- var scripts = document.getElementsByTagName('script');
- for (var i = 0; i < scripts.length; i++) {
- src = scripts[i].src;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function purgeDestroyedEditor(editor) {
+ // User has manually destroyed the editor lets clean up the mess
+ if (editor && editor.initialized && !(editor.getContainer() || editor.getBody()).parentNode) {
+ removeEditorFromList(editor);
+ editor.unbindAllNativeEvents();
+ editor.destroy(true);
+ editor.removed = true;
+ editor = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Script types supported:
- // tinymce.js tinymce.min.js tinymce.dev.js
- // tinymce.jquery.js tinymce.jquery.min.js tinymce.jquery.dev.js
- // tinymce.full.js tinymce.full.min.js tinymce.full.dev.js
- var srcScript = src.substring(src.lastIndexOf('/'));
- if (/tinymce(\.full|\.jquery|)(\.min|\.dev|)\.js/.test(src)) {
- if (srcScript.indexOf('.min') != -1) {
- suffix = '.min';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return editor;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- baseURL = src.substring(0, src.lastIndexOf('/'));
- break;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ EditorManager = {
+ /**
+ * Dom query instance.
+ *
+ * @property $
+ * @type tinymce.dom.DomQuery
+ */
+ $: DomQuery,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // We didn't find any baseURL by looking at the script elements
- // Try to use the document.currentScript as a fallback
- if (!baseURL && document.currentScript) {
- src = document.currentScript.src;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Major version of TinyMCE build.
+ *
+ * @property majorVersion
+ * @type String
+ */
+ majorVersion: '4',
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (src.indexOf('.min') != -1) {
- suffix = '.min';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Minor version of TinyMCE build.
+ *
+ * @property minorVersion
+ * @type String
+ */
+ minorVersion: '6.0',
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- baseURL = src.substring(0, src.lastIndexOf('/'));
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Release date of TinyMCE build.
+ *
+ * @property releaseDate
+ * @type String
+ */
+ releaseDate: '2017-05-04',
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Base URL where the root directory if TinyMCE is located.
- *
- * @property baseURL
- * @type String
- */
- self.baseURL = new URI(documentBaseURL).toAbsolute(baseURL);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Collection of editor instances.
+ *
+ * @property editors
+ * @type Object
+ * @example
+ * for (edId in tinymce.editors)
+ * tinymce.editors[edId].save();
+ */
+ editors: [],
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Document base URL where the current document is located.
- *
- * @property documentBaseURL
- * @type String
- */
- self.documentBaseURL = documentBaseURL;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Collection of language pack data.
+ *
+ * @property i18n
+ * @type Object
+ */
+ i18n: I18n,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Absolute baseURI for the installation path of TinyMCE.
- *
- * @property baseURI
- * @type tinymce.util.URI
- */
- self.baseURI = new URI(self.baseURL);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Currently active editor instance.
+ *
+ * @property activeEditor
+ * @type tinymce.Editor
+ * @example
+ * tinyMCE.activeEditor.selection.getContent();
+ * tinymce.EditorManager.activeEditor.selection.getContent();
+ */
+ activeEditor: null,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Current suffix to add to each plugin/theme that gets loaded for example ".min".
- *
- * @property suffix
- * @type String
- */
- self.suffix = suffix;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ setup: function () {
+ var self = this, baseURL, documentBaseURL, suffix = "", preInit, src;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.focusManager = new FocusManager(self);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get base URL for the current document
+ documentBaseURL = URI.getDocumentBaseUrl(document.location);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Overrides the default settings for editor instances.
- *
- * @method overrideDefaults
- * @param {Object} defaultSettings Defaults settings object.
- */
- overrideDefaults: function(defaultSettings) {
- var baseUrl, suffix;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if the URL is a document based format like: http://site/dir/file and file:///
+ // leave other formats like applewebdata://... intact
+ if (/^[^:]+:\/\/\/?[^\/]+\//.test(documentBaseURL)) {
+ documentBaseURL = documentBaseURL.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- baseUrl = defaultSettings.base_url;
- if (baseUrl) {
- this.baseURL = new URI(this.documentBaseURL).toAbsolute(baseUrl.replace(/\/+$/, ''));
- this.baseURI = new URI(this.baseURL);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!/[\/\\]$/.test(documentBaseURL)) {
+ documentBaseURL += '/';
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- suffix = defaultSettings.suffix;
- if (defaultSettings.suffix) {
- this.suffix = suffix;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If tinymce is defined and has a base use that or use the old tinyMCEPreInit
+ preInit = window.tinymce || window.tinyMCEPreInit;
+ if (preInit) {
+ baseURL = preInit.base || preInit.baseURL;
+ suffix = preInit.suffix;
+ } else {
+ // Get base where the tinymce script is located
+ var scripts = document.getElementsByTagName('script');
+ for (var i = 0; i < scripts.length; i++) {
+ src = scripts[i].src;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.defaultSettings = defaultSettings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Script types supported:
+ // tinymce.js tinymce.min.js tinymce.dev.js
+ // tinymce.jquery.js tinymce.jquery.min.js tinymce.jquery.dev.js
+ // tinymce.full.js tinymce.full.min.js tinymce.full.dev.js
+ var srcScript = src.substring(src.lastIndexOf('/'));
+ if (/tinymce(\.full|\.jquery|)(\.min|\.dev|)\.js/.test(src)) {
+ if (srcScript.indexOf('.min') != -1) {
+ suffix = '.min';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var pluginBaseUrls = defaultSettings.plugin_base_urls;
- for (var name in pluginBaseUrls) {
- AddOnManager.PluginManager.urls[name] = pluginBaseUrls[name];
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ baseURL = src.substring(0, src.lastIndexOf('/'));
+ break;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Initializes a set of editors. This method will create editors based on various settings.
- *
- * @method init
- * @param {Object} settings Settings object to be passed to each editor instance.
- * @return {tinymce.util.Promise} Promise that gets resolved with an array of editors when all editor instances are initialized.
- * @example
- * // Initializes a editor using the longer method
- * tinymce.EditorManager.init({
- * some_settings : 'some value'
- * });
- *
- * // Initializes a editor instance using the shorter version and with a promise
- * tinymce.init({
- * some_settings : 'some value'
- * }).then(function(editors) {
- * ...
- * });
- */
- init: function(settings) {
- var self = this, result, invalidInlineTargets;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // We didn't find any baseURL by looking at the script elements
+ // Try to use the document.currentScript as a fallback
+ if (!baseURL && document.currentScript) {
+ src = document.currentScript.src;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- invalidInlineTargets = Tools.makeMap(
- 'area base basefont br col frame hr img input isindex link meta param embed source wbr track ' +
- 'colgroup option tbody tfoot thead tr script noscript style textarea video audio iframe object menu',
- ' '
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (src.indexOf('.min') != -1) {
+ suffix = '.min';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isInvalidInlineTarget(settings, elm) {
- return settings.inline && elm.tagName.toLowerCase() in invalidInlineTargets;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ baseURL = src.substring(0, src.lastIndexOf('/'));
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function report(msg, elm) {
- // Log in a non test environment
- if (window.console && !window.test) {
- window.console.log(msg, elm);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Base URL where the root directory if TinyMCE is located.
+ *
+ * @property baseURL
+ * @type String
+ */
+ self.baseURL = new URI(documentBaseURL).toAbsolute(baseURL);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function createId(elm) {
- var id = elm.id;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Document base URL where the current document is located.
+ *
+ * @property documentBaseURL
+ * @type String
+ */
+ self.documentBaseURL = documentBaseURL;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Use element id, or unique name or generate a unique id
- if (!id) {
- id = elm.name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Absolute baseURI for the installation path of TinyMCE.
+ *
+ * @property baseURI
+ * @type tinymce.util.URI
+ */
+ self.baseURI = new URI(self.baseURL);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (id && !DOM.get(id)) {
- id = elm.name;
- } else {
- // Generate unique name
- id = DOM.uniqueId();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Current suffix to add to each plugin/theme that gets loaded for example ".min".
+ *
+ * @property suffix
+ * @type String
+ */
+ self.suffix = suffix;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elm.setAttribute('id', id);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.focusManager = new FocusManager(self);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return id;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Overrides the default settings for editor instances.
+ *
+ * @method overrideDefaults
+ * @param {Object} defaultSettings Defaults settings object.
+ */
+ overrideDefaults: function (defaultSettings) {
+ var baseUrl, suffix;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function execCallback(name) {
- var callback = settings[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ baseUrl = defaultSettings.base_url;
+ if (baseUrl) {
+ this.baseURL = new URI(this.documentBaseURL).toAbsolute(baseUrl.replace(/\/+$/, ''));
+ this.baseURI = new URI(this.baseURL);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!callback) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ suffix = defaultSettings.suffix;
+ if (defaultSettings.suffix) {
+ this.suffix = suffix;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return callback.apply(self, Array.prototype.slice.call(arguments, 2));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.defaultSettings = defaultSettings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hasClass(elm, className) {
- return className.constructor === RegExp ? className.test(elm.className) : DOM.hasClass(elm, className);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var pluginBaseUrls = defaultSettings.plugin_base_urls;
+ for (var name in pluginBaseUrls) {
+ AddOnManager.PluginManager.urls[name] = pluginBaseUrls[name];
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function findTargets(settings) {
- var l, targets = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Initializes a set of editors. This method will create editors based on various settings.
+ *
+ * @method init
+ * @param {Object} settings Settings object to be passed to each editor instance.
+ * @return {tinymce.util.Promise} Promise that gets resolved with an array of editors when all editor instances are initialized.
+ * @example
+ * // Initializes a editor using the longer method
+ * tinymce.EditorManager.init({
+ * some_settings : 'some value'
+ * });
+ *
+ * // Initializes a editor instance using the shorter version and with a promise
+ * tinymce.init({
+ * some_settings : 'some value'
+ * }).then(function(editors) {
+ * ...
+ * });
+ */
+ init: function (settings) {
+ var self = this, result, invalidInlineTargets;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.types) {
- each(settings.types, function(type) {
- targets = targets.concat(DOM.select(type.selector));
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ invalidInlineTargets = Tools.makeMap(
+ 'area base basefont br col frame hr img input isindex link meta param embed source wbr track ' +
+ 'colgroup option tbody tfoot thead tr script noscript style textarea video audio iframe object menu',
+ ' '
+ );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return targets;
- } else if (settings.selector) {
- return DOM.select(settings.selector);
- } else if (settings.target) {
- return [settings.target];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isInvalidInlineTarget(settings, elm) {
+ return settings.inline && elm.tagName.toLowerCase() in invalidInlineTargets;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Fallback to old setting
- switch (settings.mode) {
- case "exact":
- l = settings.elements || '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function createId(elm) {
+ var id = elm.id;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (l.length > 0) {
- each(explode(l), function(id) {
- var elm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Use element id, or unique name or generate a unique id
+ if (!id) {
+ id = elm.name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ((elm = DOM.get(id))) {
- targets.push(elm);
- } else {
- each(document.forms, function(f) {
- each(f.elements, function(e) {
- if (e.name === id) {
- id = 'mce_editor_' + instanceCounter++;
- DOM.setAttrib(e, 'id', id);
- targets.push(e);
- }
- });
- });
- }
- });
- }
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (id && !DOM.get(id)) {
+ id = elm.name;
+ } else {
+ // Generate unique name
+ id = DOM.uniqueId();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case "textareas":
- case "specific_textareas":
- each(DOM.select('textarea'), function(elm) {
- if (settings.editor_deselector && hasClass(elm, settings.editor_deselector)) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elm.setAttribute('id', id);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!settings.editor_selector || hasClass(elm, settings.editor_selector)) {
- targets.push(elm);
- }
- });
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return id;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return targets;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function execCallback(name) {
+ var callback = settings[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var provideResults = function(editors) {
- result = editors;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!callback) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function initEditors() {
- var initCount = 0, editors = [], targets;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return callback.apply(self, Array.prototype.slice.call(arguments, 2));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function createEditor(id, settings, targetElm) {
- var editor = new Editor(id, settings, self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hasClass(elm, className) {
+ return className.constructor === RegExp ? className.test(elm.className) : DOM.hasClass(elm, className);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editors.push(editor);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function findTargets(settings) {
+ var l, targets = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('init', function() {
- if (++initCount === targets.length) {
- provideResults(editors);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (Env.ie && Env.ie < 11) {
+ ErrorReporter.initError(
+ 'TinyMCE does not support the browser you are using. For a list of supported' +
+ ' browsers please see: https://www.tinymce.com/docs/get-started/system-requirements/'
+ );
+ return [];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.targetElm = editor.targetElm || targetElm;
- editor.render();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.types) {
+ each(settings.types, function (type) {
+ targets = targets.concat(DOM.select(type.selector));
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DOM.unbind(window, 'ready', initEditors);
- execCallback('onpageload');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return targets;
+ } else if (settings.selector) {
+ return DOM.select(settings.selector);
+ } else if (settings.target) {
+ return [settings.target];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- targets = $.unique(findTargets(settings));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Fallback to old setting
+ switch (settings.mode) {
+ case "exact":
+ l = settings.elements || '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // TODO: Deprecate this one
- if (settings.types) {
- each(settings.types, function(type) {
- Tools.each(targets, function(elm) {
- if (DOM.is(elm, type.selector)) {
- createEditor(createId(elm), extend({}, settings, type), elm);
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (l.length > 0) {
+ each(explode(l), function (id) {
+ var elm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- });
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((elm = DOM.get(id))) {
+ targets.push(elm);
+ } else {
+ each(document.forms, function (f) {
+ each(f.elements, function (e) {
+ if (e.name === id) {
+ id = 'mce_editor_' + instanceCounter++;
+ DOM.setAttrib(e, 'id', id);
+ targets.push(e);
+ }
+ });
+ });
+ }
+ });
+ }
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case "textareas":
+ case "specific_textareas":
+ each(DOM.select('textarea'), function (elm) {
+ if (settings.editor_deselector && hasClass(elm, settings.editor_deselector)) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(targets, function(elm) {
- purgeDestroyedEditor(self.get(elm.id));
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!settings.editor_selector || hasClass(elm, settings.editor_selector)) {
+ targets.push(elm);
+ }
+ });
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- targets = Tools.grep(targets, function(elm) {
- return !self.get(elm.id);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return targets;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(targets, function(elm) {
- if (isInvalidInlineTarget(settings, elm)) {
- report('Could not initialize inline editor on invalid inline target element', elm);
- } else {
- createEditor(createId(elm), settings, elm);
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var provideResults = function (editors) {
+ result = editors;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.settings = settings;
- DOM.bind(window, 'ready', initEditors);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function initEditors() {
+ var initCount = 0, editors = [], targets;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return new Promise(function(resolve) {
- if (result) {
- resolve(result);
- } else {
- provideResults = function(editors) {
- resolve(editors);
- };
- }
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function createEditor(id, settings, targetElm) {
+ var editor = new Editor(id, settings, self);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns a editor instance by id.
- *
- * @method get
- * @param {String/Number} id Editor instance id or index to return.
- * @return {tinymce.Editor} Editor instance to return.
- * @example
- * // Adds an onclick event to an editor by id (shorter version)
- * tinymce.get('mytextbox').on('click', function(e) {
- * ed.windowManager.alert('Hello world!');
- * });
- *
- * // Adds an onclick event to an editor by id (longer version)
- * tinymce.EditorManager.get('mytextbox').on('click', function(e) {
- * ed.windowManager.alert('Hello world!');
- * });
- */
- get: function(id) {
- if (!arguments.length) {
- return this.editors;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editors.push(editor);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return id in this.editors ? this.editors[id] : null;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('init', function () {
+ if (++initCount === targets.length) {
+ provideResults(editors);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds an editor instance to the editor collection. This will also set it as the active editor.
- *
- * @method add
- * @param {tinymce.Editor} editor Editor instance to add to the collection.
- * @return {tinymce.Editor} The same instance that got passed in.
- */
- add: function(editor) {
- var self = this, editors = self.editors;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.targetElm = editor.targetElm || targetElm;
+ editor.render();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add named and index editor instance
- editors[editor.id] = editor;
- editors.push(editor);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOM.unbind(window, 'ready', initEditors);
+ execCallback('onpageload');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- toggleGlobalEvents(editors, true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ targets = DomQuery.unique(findTargets(settings));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Doesn't call setActive method since we don't want
- // to fire a bunch of activate/deactivate calls while initializing
- self.activeEditor = editor;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // TODO: Deprecate this one
+ if (settings.types) {
+ each(settings.types, function (type) {
+ Tools.each(targets, function (elm) {
+ if (DOM.is(elm, type.selector)) {
+ createEditor(createId(elm), extend({}, settings, type), elm);
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.fire('AddEditor', {editor: editor});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!beforeUnloadDelegate) {
- beforeUnloadDelegate = function() {
- self.fire('BeforeUnload');
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DOM.bind(window, 'beforeunload', beforeUnloadDelegate);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(targets, function (elm) {
+ purgeDestroyedEditor(self.get(elm.id));
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return editor;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ targets = Tools.grep(targets, function (elm) {
+ return !self.get(elm.id);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Creates an editor instance and adds it to the EditorManager collection.
- *
- * @method createEditor
- * @param {String} id Instance id to use for editor.
- * @param {Object} settings Editor instance settings.
- * @return {tinymce.Editor} Editor instance that got created.
- */
- createEditor: function(id, settings) {
- return this.add(new Editor(id, settings, this));
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (targets.length === 0) {
+ provideResults([]);
+ } else {
+ each(targets, function (elm) {
+ if (isInvalidInlineTarget(settings, elm)) {
+ ErrorReporter.initError('Could not initialize inline editor on invalid inline target element', elm);
+ } else {
+ createEditor(createId(elm), settings, elm);
+ }
+ });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes a editor or editors form page.
- *
- * @example
- * // Remove all editors bound to divs
- * tinymce.remove('div');
- *
- * // Remove all editors bound to textareas
- * tinymce.remove('textarea');
- *
- * // Remove all editors
- * tinymce.remove();
- *
- * // Remove specific instance by id
- * tinymce.remove('#id');
- *
- * @method remove
- * @param {tinymce.Editor/String/Object} [selector] CSS selector or editor instance to remove.
- * @return {tinymce.Editor} The editor that got passed in will be return if it was found otherwise null.
- */
- remove: function(selector) {
- var self = this, i, editors = self.editors, editor;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.settings = settings;
+ DOM.bind(window, 'ready', initEditors);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove all editors
- if (!selector) {
- for (i = editors.length - 1; i >= 0; i--) {
- self.remove(editors[i]);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return new Promise(function (resolve) {
+ if (result) {
+ resolve(result);
+ } else {
+ provideResults = function (editors) {
+ resolve(editors);
+ };
+ }
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns a editor instance by id.
+ *
+ * @method get
+ * @param {String/Number} id Editor instance id or index to return.
+ * @return {tinymce.Editor} Editor instance to return.
+ * @example
+ * // Adds an onclick event to an editor by id (shorter version)
+ * tinymce.get('mytextbox').on('click', function(e) {
+ * ed.windowManager.alert('Hello world!');
+ * });
+ *
+ * // Adds an onclick event to an editor by id (longer version)
+ * tinymce.EditorManager.get('mytextbox').on('click', function(e) {
+ * ed.windowManager.alert('Hello world!');
+ * });
+ */
+ get: function (id) {
+ if (!arguments.length) {
+ return this.editors;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove editors by selector
- if (typeof selector == "string") {
- selector = selector.selector || selector;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return id in this.editors ? this.editors[id] : null;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(DOM.select(selector), function(elm) {
- editor = editors[elm.id];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds an editor instance to the editor collection. This will also set it as the active editor.
+ *
+ * @method add
+ * @param {tinymce.Editor} editor Editor instance to add to the collection.
+ * @return {tinymce.Editor} The same instance that got passed in.
+ */
+ add: function (editor) {
+ var self = this, editors = self.editors;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor) {
- self.remove(editor);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add named and index editor instance
+ editors[editor.id] = editor;
+ editors.push(editor);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ toggleGlobalEvents(editors, true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove specific editor
- editor = selector;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Doesn't call setActive method since we don't want
+ // to fire a bunch of activate/deactivate calls while initializing
+ self.activeEditor = editor;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Not in the collection
- if (!editors[editor.id]) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.fire('AddEditor', { editor: editor });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (removeEditorFromList(editor)) {
- self.fire('RemoveEditor', {editor: editor});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!beforeUnloadDelegate) {
+ beforeUnloadDelegate = function () {
+ self.fire('BeforeUnload');
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!editors.length) {
- DOM.unbind(window, 'beforeunload', beforeUnloadDelegate);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DOM.bind(window, 'beforeunload', beforeUnloadDelegate);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.remove();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return editor;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- toggleGlobalEvents(editors, editors.length > 0);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Creates an editor instance and adds it to the EditorManager collection.
+ *
+ * @method createEditor
+ * @param {String} id Instance id to use for editor.
+ * @param {Object} settings Editor instance settings.
+ * @return {tinymce.Editor} Editor instance that got created.
+ */
+ createEditor: function (id, settings) {
+ return this.add(new Editor(id, settings, this));
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return editor;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes a editor or editors form page.
+ *
+ * @example
+ * // Remove all editors bound to divs
+ * tinymce.remove('div');
+ *
+ * // Remove all editors bound to textareas
+ * tinymce.remove('textarea');
+ *
+ * // Remove all editors
+ * tinymce.remove();
+ *
+ * // Remove specific instance by id
+ * tinymce.remove('#id');
+ *
+ * @method remove
+ * @param {tinymce.Editor/String/Object} [selector] CSS selector or editor instance to remove.
+ * @return {tinymce.Editor} The editor that got passed in will be return if it was found otherwise null.
+ */
+ remove: function (selector) {
+ var self = this, i, editors = self.editors, editor;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Executes a specific command on the currently active editor.
- *
- * @method execCommand
- * @param {String} cmd Command to perform for example Bold.
- * @param {Boolean} ui Optional boolean state if a UI should be presented for the command or not.
- * @param {String} value Optional value parameter like for example an URL to a link.
- * @return {Boolean} true/false if the command was executed or not.
- */
- execCommand: function(cmd, ui, value) {
- var self = this, editor = self.get(value);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove all editors
+ if (!selector) {
+ for (i = editors.length - 1; i >= 0; i--) {
+ self.remove(editors[i]);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Manager commands
- switch (cmd) {
- case "mceAddEditor":
- if (!self.get(value)) {
- new Editor(value, self.settings, self).render();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove editors by selector
+ if (typeof selector == "string") {
+ selector = selector.selector || selector;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case "mceRemoveEditor":
- if (editor) {
- editor.remove();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(DOM.select(selector), function (elm) {
+ editor = editors[elm.id];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor) {
+ self.remove(editor);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case 'mceToggleEditor':
- if (!editor) {
- self.execCommand('mceAddEditor', 0, value);
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.isHidden()) {
- editor.show();
- } else {
- editor.hide();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Remove specific editor
+ editor = selector;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Not in the collection
+ if (!editors[editor.id]) {
+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Run command on active editor
- if (self.activeEditor) {
- return self.activeEditor.execCommand(cmd, ui, value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (removeEditorFromList(editor)) {
+ self.fire('RemoveEditor', { editor: editor });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!editors.length) {
+ DOM.unbind(window, 'beforeunload', beforeUnloadDelegate);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Calls the save method on all editor instances in the collection. This can be useful when a form is to be submitted.
- *
- * @method triggerSave
- * @example
- * // Saves all contents
- * tinyMCE.triggerSave();
- */
- triggerSave: function() {
- each(this.editors, function(editor) {
- editor.save();
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.remove();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Adds a language pack, this gets called by the loaded language files like en.js.
- *
- * @method addI18n
- * @param {String} code Optional language code.
- * @param {Object} items Name/value object with translations.
- */
- addI18n: function(code, items) {
- I18n.add(code, items);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ toggleGlobalEvents(editors, editors.length > 0);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Translates the specified string using the language pack items.
- *
- * @method translate
- * @param {String/Array/Object} text String to translate
- * @return {String} Translated string.
- */
- translate: function(text) {
- return I18n.translate(text);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return editor;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets the active editor instance and fires the deactivate/activate events.
- *
- * @method setActive
- * @param {tinymce.Editor} editor Editor instance to set as the active instance.
- */
- setActive: function(editor) {
- var activeEditor = this.activeEditor;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Executes a specific command on the currently active editor.
+ *
+ * @method execCommand
+ * @param {String} cmd Command to perform for example Bold.
+ * @param {Boolean} ui Optional boolean state if a UI should be presented for the command or not.
+ * @param {String} value Optional value parameter like for example an URL to a link.
+ * @return {Boolean} true/false if the command was executed or not.
+ */
+ execCommand: function (cmd, ui, value) {
+ var self = this, editor = self.get(value);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.activeEditor != editor) {
- if (activeEditor) {
- activeEditor.fire('deactivate', {relatedTarget: editor});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Manager commands
+ switch (cmd) {
+ case "mceAddEditor":
+ if (!self.get(value)) {
+ new Editor(value, self.settings, self).render();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.fire('activate', {relatedTarget: activeEditor});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.activeEditor = editor;
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case "mceRemoveEditor":
+ if (editor) {
+ editor.remove();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- extend(EditorManager, Observable);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- EditorManager.setup();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case 'mceToggleEditor':
+ if (!editor) {
+ self.execCommand('mceAddEditor', 0, value);
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Export EditorManager as tinymce/tinymce in global namespace
- window.tinymce = window.tinyMCE = EditorManager;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.isHidden()) {
+ editor.show();
+ } else {
+ editor.hide();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return EditorManager;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/LegacyInput.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Run command on active editor
+ if (self.activeEditor) {
+ return self.activeEditor.execCommand(cmd, ui, value);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * LegacyInput.js
- *
- * Released under LGPL License.
- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Converts legacy input to modern HTML.
- *
- * @class tinymce.LegacyInput
- * @private
- */
-define("tinymce/LegacyInput", [
- "tinymce/EditorManager",
- "tinymce/util/Tools"
-], function(EditorManager, Tools) {
- var each = Tools.each, explode = Tools.explode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Calls the save method on all editor instances in the collection. This can be useful when a form is to be submitted.
+ *
+ * @method triggerSave
+ * @example
+ * // Saves all contents
+ * tinyMCE.triggerSave();
+ */
+ triggerSave: function () {
+ each(this.editors, function (editor) {
+ editor.save();
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- EditorManager.on('AddEditor', function(e) {
- var editor = e.editor;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Adds a language pack, this gets called by the loaded language files like en.js.
+ *
+ * @method addI18n
+ * @param {String} code Optional language code.
+ * @param {Object} items Name/value object with translations.
+ */
+ addI18n: function (code, items) {
+ I18n.add(code, items);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('preInit', function() {
- var filters, fontSizes, dom, settings = editor.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Translates the specified string using the language pack items.
+ *
+ * @method translate
+ * @param {String/Array/Object} text String to translate
+ * @return {String} Translated string.
+ */
+ translate: function (text) {
+ return I18n.translate(text);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function replaceWithSpan(node, styles) {
- each(styles, function(value, name) {
- if (value) {
- dom.setStyle(node, name, value);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets the active editor instance and fires the deactivate/activate events.
+ *
+ * @method setActive
+ * @param {tinymce.Editor} editor Editor instance to set as the active instance.
+ */
+ setActive: function (editor) {
+ var activeEditor = this.activeEditor;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.rename(node, 'span');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.activeEditor != editor) {
+ if (activeEditor) {
+ activeEditor.fire('deactivate', { relatedTarget: editor });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function convert(e) {
- dom = editor.dom;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.fire('activate', { relatedTarget: activeEditor });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.convert_fonts_to_spans) {
- each(dom.select('font,u,strike', e.node), function(node) {
- filters[node.nodeName.toLowerCase()](dom, node);
- });
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.activeEditor = editor;
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.inline_styles) {
- fontSizes = explode(settings.font_size_legacy_values);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ extend(EditorManager, Observable);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- filters = {
- font: function(dom, node) {
- replaceWithSpan(node, {
- backgroundColor: node.style.backgroundColor,
- color: node.color,
- fontFamily: node.face,
- fontSize: fontSizes[parseInt(node.size, 10) - 1]
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ EditorManager.setup();
+ LegacyInput.register(EditorManager);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- u: function(dom, node) {
- // HTML5 allows U element
- if (editor.settings.schema === "html4") {
- replaceWithSpan(node, {
- textDecoration: 'underline'
- });
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return EditorManager;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- strike: function(dom, node) {
- replaceWithSpan(node, {
- textDecoration: 'line-through'
- });
- }
- };
-
- editor.on('PreProcess SetContent', convert);
- }
- });
- });
-});
-
-// Included from: js/tinymce/classes/util/XHR.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * XHR.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -41721,95 +46621,97 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * e.xhr.setRequestHeader('X-Requested-With', 'Something');
</span><span class="cx" style="display: block; padding: 0 10px"> * });
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/util/XHR", [
- "tinymce/util/Observable",
- "tinymce/util/Tools"
-], function(Observable, Tools) {
- var XHR = {
- /**
- * Sends a XMLHTTPRequest.
- * Consult the Wiki for details on what settings this method takes.
- *
- * @method send
- * @param {Object} settings Object will target URL, callbacks and other info needed to make the request.
- */
- send: function(settings) {
- var xhr, count = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.XHR',
+ [
+ "tinymce.core.util.Observable",
+ "tinymce.core.util.Tools"
+ ],
+ function (Observable, Tools) {
+ var XHR = {
+ /**
+ * Sends a XMLHTTPRequest.
+ * Consult the Wiki for details on what settings this method takes.
+ *
+ * @method send
+ * @param {Object} settings Object will target URL, callbacks and other info needed to make the request.
+ */
+ send: function (settings) {
+ var xhr, count = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function ready() {
- if (!settings.async || xhr.readyState == 4 || count++ > 10000) {
- if (settings.success && count < 10000 && xhr.status == 200) {
- settings.success.call(settings.success_scope, '' + xhr.responseText, xhr, settings);
- } else if (settings.error) {
- settings.error.call(settings.error_scope, count > 10000 ? 'TIMED_OUT' : 'GENERAL', xhr, settings);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function ready() {
+ if (!settings.async || xhr.readyState == 4 || count++ > 10000) {
+ if (settings.success && count < 10000 && xhr.status == 200) {
+ settings.success.call(settings.success_scope, '' + xhr.responseText, xhr, settings);
+ } else if (settings.error) {
+ settings.error.call(settings.error_scope, count > 10000 ? 'TIMED_OUT' : 'GENERAL', xhr, settings);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- xhr = null;
- } else {
- setTimeout(ready, 10);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ xhr = null;
+ } else {
+ setTimeout(ready, 10);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Default settings
- settings.scope = settings.scope || this;
- settings.success_scope = settings.success_scope || settings.scope;
- settings.error_scope = settings.error_scope || settings.scope;
- settings.async = settings.async === false ? false : true;
- settings.data = settings.data || '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Default settings
+ settings.scope = settings.scope || this;
+ settings.success_scope = settings.success_scope || settings.scope;
+ settings.error_scope = settings.error_scope || settings.scope;
+ settings.async = settings.async === false ? false : true;
+ settings.data = settings.data || '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- XHR.fire('beforeInitialize', {settings: settings});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ XHR.fire('beforeInitialize', { settings: settings });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- xhr = new XMLHttpRequest();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ xhr = new XMLHttpRequest();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (xhr) {
- if (xhr.overrideMimeType) {
- xhr.overrideMimeType(settings.content_type);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (xhr) {
+ if (xhr.overrideMimeType) {
+ xhr.overrideMimeType(settings.content_type);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- xhr.open(settings.type || (settings.data ? 'POST' : 'GET'), settings.url, settings.async);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ xhr.open(settings.type || (settings.data ? 'POST' : 'GET'), settings.url, settings.async);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.crossDomain) {
- xhr.withCredentials = true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.crossDomain) {
+ xhr.withCredentials = true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.content_type) {
- xhr.setRequestHeader('Content-Type', settings.content_type);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.content_type) {
+ xhr.setRequestHeader('Content-Type', settings.content_type);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.requestheaders) {
- Tools.each(settings.requestheaders, function(header) {
- xhr.setRequestHeader(header.key, header.value);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.requestheaders) {
+ Tools.each(settings.requestheaders, function (header) {
+ xhr.setRequestHeader(header.key, header.value);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- xhr = XHR.fire('beforeSend', {xhr: xhr, settings: settings}).xhr;
- xhr.send(settings.data);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ xhr = XHR.fire('beforeSend', { xhr: xhr, settings: settings }).xhr;
+ xhr.send(settings.data);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Syncronous request
- if (!settings.async) {
- return ready();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Syncronous request
+ if (!settings.async) {
+ return ready();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Wait for response, onReadyStateChange can not be used since it leaks memory in IE
- setTimeout(ready, 10);
- }
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Wait for response, onReadyStateChange can not be used since it leaks memory in IE
+ setTimeout(ready, 10);
+ }
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.extend(XHR, Observable);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.extend(XHR, Observable);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return XHR;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return XHR;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/util/JSON.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * JSON.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -41827,102 +46729,105 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * // JSON serialize a object into an string
</span><span class="cx" style="display: block; padding: 0 10px"> * var str = tinymce.util.JSON.serialize(obj);
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/util/JSON", [], function() {
- function serialize(o, quote) {
- var i, v, t, name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.JSON',
+ [
+ ],
+ function () {
+ function serialize(o, quote) {
+ var i, v, t, name;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- quote = quote || '"';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ quote = quote || '"';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (o === null) {
- return 'null';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (o === null) {
+ return 'null';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- t = typeof o;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ t = typeof o;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (t == 'string') {
- v = '\bb\tt\nn\ff\rr\""\'\'\\\\';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (t == 'string') {
+ v = '\bb\tt\nn\ff\rr\""\'\'\\\\';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /*eslint no-control-regex:0 */
- return quote + o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g, function(a, b) {
- // Make sure single quotes never get encoded inside double quotes for JSON compatibility
- if (quote === '"' && a === "'") {
- return a;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /*eslint no-control-regex:0 */
+ return quote + o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g, function (a, b) {
+ // Make sure single quotes never get encoded inside double quotes for JSON compatibility
+ if (quote === '"' && a === "'") {
+ return a;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- i = v.indexOf(b);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ i = v.indexOf(b);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (i + 1) {
- return '\\' + v.charAt(i + 1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (i + 1) {
+ return '\\' + v.charAt(i + 1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- a = b.charCodeAt().toString(16);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ a = b.charCodeAt().toString(16);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return '\\u' + '0000'.substring(a.length) + a;
- }) + quote;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return '\\u' + '0000'.substring(a.length) + a;
+ }) + quote;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (t == 'object') {
- if (o.hasOwnProperty && Object.prototype.toString.call(o) === '[object Array]') {
- for (i = 0, v = '['; i < o.length; i++) {
- v += (i > 0 ? ',' : '') + serialize(o[i], quote);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (t == 'object') {
+ if (o.hasOwnProperty && Object.prototype.toString.call(o) === '[object Array]') {
+ for (i = 0, v = '['; i < o.length; i++) {
+ v += (i > 0 ? ',' : '') + serialize(o[i], quote);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return v + ']';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return v + ']';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- v = '{';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ v = '{';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (name in o) {
- if (o.hasOwnProperty(name)) {
- v += typeof o[name] != 'function' ? (v.length > 1 ? ',' + quote : quote) + name +
- quote + ':' + serialize(o[name], quote) : '';
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (name in o) {
+ if (o.hasOwnProperty(name)) {
+ v += typeof o[name] != 'function' ? (v.length > 1 ? ',' + quote : quote) + name +
+ quote + ':' + serialize(o[name], quote) : '';
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return v + '}';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return v + '}';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return '' + o;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return '' + o;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- /**
- * Serializes the specified object as a JSON string.
- *
- * @method serialize
- * @param {Object} obj Object to serialize as a JSON string.
- * @param {String} quote Optional quote string defaults to ".
- * @return {string} JSON string serialized from input.
- */
- serialize: serialize,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ /**
+ * Serializes the specified object as a JSON string.
+ *
+ * @method serialize
+ * @param {Object} obj Object to serialize as a JSON string.
+ * @param {String} quote Optional quote string defaults to ".
+ * @return {string} JSON string serialized from input.
+ */
+ serialize: serialize,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Unserializes/parses the specified JSON string into a object.
- *
- * @method parse
- * @param {string} s JSON String to parse into a JavaScript object.
- * @return {Object} Object from input JSON string or undefined if it failed.
- */
- parse: function(text) {
- try {
- // Trick uglify JS
- return window[String.fromCharCode(101) + 'val']('(' + text + ')');
- } catch (ex) {
- // Ignore
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Unserializes/parses the specified JSON string into a object.
+ *
+ * @method parse
+ * @param {string} s JSON String to parse into a JavaScript object.
+ * @return {Object} Object from input JSON string or undefined if it failed.
+ */
+ parse: function (text) {
+ try {
+ // Trick uglify JS
+ return window[String.fromCharCode(101) + 'val']('(' + text + ')');
+ } catch (ex) {
+ // Ignore
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**#@-*/
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**#@-*/
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/util/JSONRequest.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * JSONRequest.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -41955,128 +46860,130 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * }
</span><span class="cx" style="display: block; padding: 0 10px"> * });
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/util/JSONRequest", [
- "tinymce/util/JSON",
- "tinymce/util/XHR",
- "tinymce/util/Tools"
-], function(JSON, XHR, Tools) {
- var extend = Tools.extend;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.JSONRequest',
+ [
+ "tinymce.core.util.JSON",
+ "tinymce.core.util.XHR",
+ "tinymce.core.util.Tools"
+ ],
+ function (JSON, XHR, Tools) {
+ var extend = Tools.extend;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function JSONRequest(settings) {
- this.settings = extend({}, settings);
- this.count = 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function JSONRequest(settings) {
+ this.settings = extend({}, settings);
+ this.count = 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Simple helper function to send a JSON-RPC request without the need to initialize an object.
- * Consult the Wiki API documentation for more details on what you can pass to this function.
- *
- * @method sendRPC
- * @static
- * @param {Object} o Call object where there are three field id, method and params this object should also contain callbacks etc.
- */
- JSONRequest.sendRPC = function(o) {
- return new JSONRequest().send(o);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Simple helper function to send a JSON-RPC request without the need to initialize an object.
+ * Consult the Wiki API documentation for more details on what you can pass to this function.
+ *
+ * @method sendRPC
+ * @static
+ * @param {Object} o Call object where there are three field id, method and params this object should also contain callbacks etc.
+ */
+ JSONRequest.sendRPC = function (o) {
+ return new JSONRequest().send(o);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- JSONRequest.prototype = {
- /**
- * Sends a JSON-RPC call. Consult the Wiki API documentation for more details on what you can pass to this function.
- *
- * @method send
- * @param {Object} args Call object where there are three field id, method and params this object should also contain callbacks etc.
- */
- send: function(args) {
- var ecb = args.error, scb = args.success;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ JSONRequest.prototype = {
+ /**
+ * Sends a JSON-RPC call. Consult the Wiki API documentation for more details on what you can pass to this function.
+ *
+ * @method send
+ * @param {Object} args Call object where there are three field id, method and params this object should also contain callbacks etc.
+ */
+ send: function (args) {
+ var ecb = args.error, scb = args.success;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args = extend(this.settings, args);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args = extend(this.settings, args);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args.success = function(c, x) {
- c = JSON.parse(c);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args.success = function (c, x) {
+ c = JSON.parse(c);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof c == 'undefined') {
- c = {
- error: 'JSON Parse error.'
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof c == 'undefined') {
+ c = {
+ error: 'JSON Parse error.'
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (c.error) {
- ecb.call(args.error_scope || args.scope, c.error, x);
- } else {
- scb.call(args.success_scope || args.scope, c.result);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (c.error) {
+ ecb.call(args.error_scope || args.scope, c.error, x);
+ } else {
+ scb.call(args.success_scope || args.scope, c.result);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args.error = function(ty, x) {
- if (ecb) {
- ecb.call(args.error_scope || args.scope, ty, x);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args.error = function (ty, x) {
+ if (ecb) {
+ ecb.call(args.error_scope || args.scope, ty, x);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- args.data = JSON.serialize({
- id: args.id || 'c' + (this.count++),
- method: args.method,
- params: args.params
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ args.data = JSON.serialize({
+ id: args.id || 'c' + (this.count++),
+ method: args.method,
+ params: args.params
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // JSON content type for Ruby on rails. Bug: #1883287
- args.content_type = 'application/json';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // JSON content type for Ruby on rails. Bug: #1883287
+ args.content_type = 'application/json';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- XHR.send(args);
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ XHR.send(args);
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return JSONRequest;
-});
-
-// Included from: js/tinymce/classes/util/JSONP.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return JSONRequest;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * JSONP.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/util/JSONP", [
- "tinymce/dom/DOMUtils"
-], function(DOMUtils) {
- return {
- callbacks: {},
- count: 0,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.JSONP',
+ [
+ "tinymce.core.dom.DOMUtils"
+ ],
+ function (DOMUtils) {
+ return {
+ callbacks: {},
+ count: 0,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- send: function(settings) {
- var self = this, dom = DOMUtils.DOM, count = settings.count !== undefined ? settings.count : self.count;
- var id = 'tinymce_jsonp_' + count;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ send: function (settings) {
+ var self = this, dom = DOMUtils.DOM, count = settings.count !== undefined ? settings.count : self.count;
+ var id = 'tinymce_jsonp_' + count;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.callbacks[count] = function(json) {
- dom.remove(id);
- delete self.callbacks[count];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.callbacks[count] = function (json) {
+ dom.remove(id);
+ delete self.callbacks[count];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- settings.callback(json);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ settings.callback(json);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.add(dom.doc.body, 'script', {
- id: id,
- src: settings.url,
- type: 'text/javascript'
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.add(dom.doc.body, 'script', {
+ id: id,
+ src: settings.url,
+ type: 'text/javascript'
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.count++;
- }
- };
-});
-
-// Included from: js/tinymce/classes/util/LocalStorage.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.count++;
+ }
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * LocalStorage.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -42101,198 +47008,201 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * tinymce.util.LocalStorage.setItem('key', 'value');
</span><span class="cx" style="display: block; padding: 0 10px"> * var value = tinymce.util.LocalStorage.getItem('key');
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/util/LocalStorage", [], function() {
- var LocalStorage, storageElm, items, keys, userDataKey, hasOldIEDataSupport;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.util.LocalStorage',
+ [
+ ],
+ function () {
+ var LocalStorage, storageElm, items, keys, userDataKey, hasOldIEDataSupport;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check for native support
- try {
- if (window.localStorage) {
- return localStorage;
- }
- } catch (ex) {
- // Ignore
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check for native support
+ try {
+ if (window.localStorage) {
+ return localStorage;
+ }
+ } catch (ex) {
+ // Ignore
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- userDataKey = "tinymce";
- storageElm = document.documentElement;
- hasOldIEDataSupport = !!storageElm.addBehavior;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ userDataKey = "tinymce";
+ storageElm = document.documentElement;
+ hasOldIEDataSupport = !!storageElm.addBehavior;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (hasOldIEDataSupport) {
- storageElm.addBehavior('#default#userData');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (hasOldIEDataSupport) {
+ storageElm.addBehavior('#default#userData');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Gets the keys names and updates LocalStorage.length property. Since IE7 doesn't have any getters/setters.
- */
- function updateKeys() {
- keys = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Gets the keys names and updates LocalStorage.length property. Since IE7 doesn't have any getters/setters.
+ */
+ function updateKeys() {
+ keys = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var key in items) {
- keys.push(key);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (var key in items) {
+ keys.push(key);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- LocalStorage.length = keys.length;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ LocalStorage.length = keys.length;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Loads the userData string and parses it into the items structure.
- */
- function load() {
- var key, data, value, pos = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Loads the userData string and parses it into the items structure.
+ */
+ function load() {
+ var key, data, value, pos = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- items = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ items = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // localStorage can be disabled on WebKit/Gecko so make a dummy storage
- if (!hasOldIEDataSupport) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // localStorage can be disabled on WebKit/Gecko so make a dummy storage
+ if (!hasOldIEDataSupport) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function next(end) {
- var value, nextPos;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function next(end) {
+ var value, nextPos;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- nextPos = end !== undefined ? pos + end : data.indexOf(',', pos);
- if (nextPos === -1 || nextPos > data.length) {
- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ nextPos = end !== undefined ? pos + end : data.indexOf(',', pos);
+ if (nextPos === -1 || nextPos > data.length) {
+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- value = data.substring(pos, nextPos);
- pos = nextPos + 1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ value = data.substring(pos, nextPos);
+ pos = nextPos + 1;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return value;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return value;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- storageElm.load(userDataKey);
- data = storageElm.getAttribute(userDataKey) || '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ storageElm.load(userDataKey);
+ data = storageElm.getAttribute(userDataKey) || '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- do {
- var offset = next();
- if (offset === null) {
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ do {
+ var offset = next();
+ if (offset === null) {
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- key = next(parseInt(offset, 32) || 0);
- if (key !== null) {
- offset = next();
- if (offset === null) {
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ key = next(parseInt(offset, 32) || 0);
+ if (key !== null) {
+ offset = next();
+ if (offset === null) {
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- value = next(parseInt(offset, 32) || 0);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ value = next(parseInt(offset, 32) || 0);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (key) {
- items[key] = value;
- }
- }
- } while (key !== null);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (key) {
+ items[key] = value;
+ }
+ }
+ } while (key !== null);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- updateKeys();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ updateKeys();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Saves the items structure into a the userData format.
- */
- function save() {
- var value, data = '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Saves the items structure into a the userData format.
+ */
+ function save() {
+ var value, data = '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // localStorage can be disabled on WebKit/Gecko so make a dummy storage
- if (!hasOldIEDataSupport) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // localStorage can be disabled on WebKit/Gecko so make a dummy storage
+ if (!hasOldIEDataSupport) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var key in items) {
- value = items[key];
- data += (data ? ',' : '') + key.length.toString(32) + ',' + key + ',' + value.length.toString(32) + ',' + value;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (var key in items) {
+ value = items[key];
+ data += (data ? ',' : '') + key.length.toString(32) + ',' + key + ',' + value.length.toString(32) + ',' + value;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- storageElm.setAttribute(userDataKey, data);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ storageElm.setAttribute(userDataKey, data);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- try {
- storageElm.save(userDataKey);
- } catch (ex) {
- // Ignore disk full
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ try {
+ storageElm.save(userDataKey);
+ } catch (ex) {
+ // Ignore disk full
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- updateKeys();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ updateKeys();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- LocalStorage = {
- /**
- * Length of the number of items in storage.
- *
- * @property length
- * @type Number
- * @return {Number} Number of items in storage.
- */
- //length:0,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ LocalStorage = {
+ /**
+ * Length of the number of items in storage.
+ *
+ * @property length
+ * @type Number
+ * @return {Number} Number of items in storage.
+ */
+ //length:0,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the key name by index.
- *
- * @method key
- * @param {Number} index Index of key to return.
- * @return {String} Key value or null if it wasn't found.
- */
- key: function(index) {
- return keys[index];
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the key name by index.
+ *
+ * @method key
+ * @param {Number} index Index of key to return.
+ * @return {String} Key value or null if it wasn't found.
+ */
+ key: function (index) {
+ return keys[index];
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns the value if the specified key or null if it wasn't found.
- *
- * @method getItem
- * @param {String} key Key of item to retrieve.
- * @return {String} Value of the specified item or null if it wasn't found.
- */
- getItem: function(key) {
- return key in items ? items[key] : null;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns the value if the specified key or null if it wasn't found.
+ *
+ * @method getItem
+ * @param {String} key Key of item to retrieve.
+ * @return {String} Value of the specified item or null if it wasn't found.
+ */
+ getItem: function (key) {
+ return key in items ? items[key] : null;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets the value of the specified item by it's key.
- *
- * @method setItem
- * @param {String} key Key of the item to set.
- * @param {String} value Value of the item to set.
- */
- setItem: function(key, value) {
- items[key] = "" + value;
- save();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets the value of the specified item by it's key.
+ *
+ * @method setItem
+ * @param {String} key Key of the item to set.
+ * @param {String} value Value of the item to set.
+ */
+ setItem: function (key, value) {
+ items[key] = "" + value;
+ save();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes the specified item by key.
- *
- * @method removeItem
- * @param {String} key Key of item to remove.
- */
- removeItem: function(key) {
- delete items[key];
- save();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes the specified item by key.
+ *
+ * @method removeItem
+ * @param {String} key Key of item to remove.
+ */
+ removeItem: function (key) {
+ delete items[key];
+ save();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes all items.
- *
- * @method clear
- */
- clear: function() {
- items = {};
- save();
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes all items.
+ *
+ * @method clear
+ */
+ clear: function () {
+ items = {};
+ save();
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- load();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ load();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return LocalStorage;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return LocalStorage;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/Compat.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Compat.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -42306,44 +47216,50 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @borrow-members tinymce.EditorManager
</span><span class="cx" style="display: block; padding: 0 10px"> * @borrow-members tinymce.util.Tools
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/Compat", [
- "tinymce/dom/DOMUtils",
- "tinymce/dom/EventUtils",
- "tinymce/dom/ScriptLoader",
- "tinymce/AddOnManager",
- "tinymce/util/Tools",
- "tinymce/Env"
-], function(DOMUtils, EventUtils, ScriptLoader, AddOnManager, Tools, Env) {
- var tinymce = window.tinymce;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.api.Compat',
+ [
+ "tinymce.core.dom.DOMUtils",
+ "tinymce.core.dom.EventUtils",
+ "tinymce.core.dom.ScriptLoader",
+ "tinymce.core.AddOnManager",
+ "tinymce.core.util.Tools",
+ "tinymce.core.Env"
+ ],
+ function (DOMUtils, EventUtils, ScriptLoader, AddOnManager, Tools, Env) {
+ var register = function (tinymce) {
+ /**
+ * @property {tinymce.dom.DOMUtils} DOM Global DOM instance.
+ * @property {tinymce.dom.ScriptLoader} ScriptLoader Global ScriptLoader instance.
+ * @property {tinymce.AddOnManager} PluginManager Global PluginManager instance.
+ * @property {tinymce.AddOnManager} ThemeManager Global ThemeManager instance.
+ */
+ tinymce.DOM = DOMUtils.DOM;
+ tinymce.ScriptLoader = ScriptLoader.ScriptLoader;
+ tinymce.PluginManager = AddOnManager.PluginManager;
+ tinymce.ThemeManager = AddOnManager.ThemeManager;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * @property {tinymce.dom.DOMUtils} DOM Global DOM instance.
- * @property {tinymce.dom.ScriptLoader} ScriptLoader Global ScriptLoader instance.
- * @property {tinymce.AddOnManager} PluginManager Global PluginManager instance.
- * @property {tinymce.AddOnManager} ThemeManager Global ThemeManager instance.
- */
- tinymce.DOM = DOMUtils.DOM;
- tinymce.ScriptLoader = ScriptLoader.ScriptLoader;
- tinymce.PluginManager = AddOnManager.PluginManager;
- tinymce.ThemeManager = AddOnManager.ThemeManager;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ tinymce.dom = tinymce.dom || {};
+ tinymce.dom.Event = EventUtils.Event;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tinymce.dom = tinymce.dom || {};
- tinymce.dom.Event = EventUtils.Event;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(
+ 'trim isArray is toArray makeMap each map grep inArray extend create walk createNS resolve explode _addCacheSuffix'.split(' '),
+ function (key) {
+ tinymce[key] = Tools[key];
+ }
+ );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(
- 'trim isArray is toArray makeMap each map grep inArray extend create walk createNS resolve explode _addCacheSuffix'.split(' '),
- function(key) {
- tinymce[key] = Tools[key];
- }
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each('isOpera isWebKit isIE isGecko isMac'.split(' '), function (name) {
+ tinymce[name] = Env[name.substr(2).toLowerCase()];
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each('isOpera isWebKit isIE isGecko isMac'.split(' '), function(name) {
- tinymce[name] = Env[name.substr(2).toLowerCase()];
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ register: register
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {};
-});
-
</del><span class="cx" style="display: block; padding: 0 10px"> // Describe the different namespaces
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -42382,13 +47298,252 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @namespace tinymce.data
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/Layout.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Color.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * This class lets you parse/serialize colors and convert rgb/hsb.
+ *
+ * @class tinymce.util.Color
+ * @example
+ * var white = new tinymce.util.Color({r: 255, g: 255, b: 255});
+ * var red = new tinymce.util.Color('#FF0000');
+ *
+ * console.log(white.toHex(), red.toHsv());
+ */
+define(
+ 'tinymce.core.util.Color',
+ [
+ ],
+ function () {
+ var min = Math.min, max = Math.max, round = Math.round;
+
+ /**
+ * Constructs a new color instance.
+ *
+ * @constructor
+ * @method Color
+ * @param {String} value Optional initial value to parse.
+ */
+ function Color(value) {
+ var self = this, r = 0, g = 0, b = 0;
+
+ function rgb2hsv(r, g, b) {
+ var h, s, v, d, minRGB, maxRGB;
+
+ h = 0;
+ s = 0;
+ v = 0;
+ r = r / 255;
+ g = g / 255;
+ b = b / 255;
+
+ minRGB = min(r, min(g, b));
+ maxRGB = max(r, max(g, b));
+
+ if (minRGB == maxRGB) {
+ v = minRGB;
+
+ return {
+ h: 0,
+ s: 0,
+ v: v * 100
+ };
+ }
+
+ /*eslint no-nested-ternary:0 */
+ d = (r == minRGB) ? g - b : ((b == minRGB) ? r - g : b - r);
+ h = (r == minRGB) ? 3 : ((b == minRGB) ? 1 : 5);
+ h = 60 * (h - d / (maxRGB - minRGB));
+ s = (maxRGB - minRGB) / maxRGB;
+ v = maxRGB;
+
+ return {
+ h: round(h),
+ s: round(s * 100),
+ v: round(v * 100)
+ };
+ }
+
+ function hsvToRgb(hue, saturation, brightness) {
+ var side, chroma, x, match;
+
+ hue = (parseInt(hue, 10) || 0) % 360;
+ saturation = parseInt(saturation, 10) / 100;
+ brightness = parseInt(brightness, 10) / 100;
+ saturation = max(0, min(saturation, 1));
+ brightness = max(0, min(brightness, 1));
+
+ if (saturation === 0) {
+ r = g = b = round(255 * brightness);
+ return;
+ }
+
+ side = hue / 60;
+ chroma = brightness * saturation;
+ x = chroma * (1 - Math.abs(side % 2 - 1));
+ match = brightness - chroma;
+
+ switch (Math.floor(side)) {
+ case 0:
+ r = chroma;
+ g = x;
+ b = 0;
+ break;
+
+ case 1:
+ r = x;
+ g = chroma;
+ b = 0;
+ break;
+
+ case 2:
+ r = 0;
+ g = chroma;
+ b = x;
+ break;
+
+ case 3:
+ r = 0;
+ g = x;
+ b = chroma;
+ break;
+
+ case 4:
+ r = x;
+ g = 0;
+ b = chroma;
+ break;
+
+ case 5:
+ r = chroma;
+ g = 0;
+ b = x;
+ break;
+
+ default:
+ r = g = b = 0;
+ }
+
+ r = round(255 * (r + match));
+ g = round(255 * (g + match));
+ b = round(255 * (b + match));
+ }
+
+ /**
+ * Returns the hex string of the current color. For example: #ff00ff
+ *
+ * @method toHex
+ * @return {String} Hex string of current color.
+ */
+ function toHex() {
+ function hex(val) {
+ val = parseInt(val, 10).toString(16);
+
+ return val.length > 1 ? val : '0' + val;
+ }
+
+ return '#' + hex(r) + hex(g) + hex(b);
+ }
+
+ /**
+ * Returns the r, g, b values of the color. Each channel has a range from 0-255.
+ *
+ * @method toRgb
+ * @return {Object} Object with r, g, b fields.
+ */
+ function toRgb() {
+ return {
+ r: r,
+ g: g,
+ b: b
+ };
+ }
+
+ /**
+ * Returns the h, s, v values of the color. Ranges: h=0-360, s=0-100, v=0-100.
+ *
+ * @method toHsv
+ * @return {Object} Object with h, s, v fields.
+ */
+ function toHsv() {
+ return rgb2hsv(r, g, b);
+ }
+
+ /**
+ * Parses the specified value and populates the color instance.
+ *
+ * Supported format examples:
+ * * rbg(255,0,0)
+ * * #ff0000
+ * * #fff
+ * * {r: 255, g: 0, b: 0}
+ * * {h: 360, s: 100, v: 100}
+ *
+ * @method parse
+ * @param {Object/String} value Color value to parse.
+ * @return {tinymce.util.Color} Current color instance.
+ */
+ function parse(value) {
+ var matches;
+
+ if (typeof value == 'object') {
+ if ("r" in value) {
+ r = value.r;
+ g = value.g;
+ b = value.b;
+ } else if ("v" in value) {
+ hsvToRgb(value.h, value.s, value.v);
+ }
+ } else {
+ if ((matches = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)[^\)]*\)/gi.exec(value))) {
+ r = parseInt(matches[1], 10);
+ g = parseInt(matches[2], 10);
+ b = parseInt(matches[3], 10);
+ } else if ((matches = /#([0-F]{2})([0-F]{2})([0-F]{2})/gi.exec(value))) {
+ r = parseInt(matches[1], 16);
+ g = parseInt(matches[2], 16);
+ b = parseInt(matches[3], 16);
+ } else if ((matches = /#([0-F])([0-F])([0-F])/gi.exec(value))) {
+ r = parseInt(matches[1] + matches[1], 16);
+ g = parseInt(matches[2] + matches[2], 16);
+ b = parseInt(matches[3] + matches[3], 16);
+ }
+ }
+
+ r = r < 0 ? 0 : (r > 255 ? 255 : r);
+ g = g < 0 ? 0 : (g > 255 ? 255 : g);
+ b = b < 0 ? 0 : (b > 255 ? 255 : b);
+
+ return self;
+ }
+
+ if (value) {
+ parse(value);
+ }
+
+ self.toRgb = toRgb;
+ self.toHsv = toHsv;
+ self.toHex = toHex;
+ self.parse = parse;
+ }
+
+ return Color;
+ }
+);
+
+/**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Layout.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -42399,119 +47554,120 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.Layout
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Layout", [
- "tinymce/util/Class",
- "tinymce/util/Tools"
-], function(Class, Tools) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Layout',
+ [
+ "tinymce.core.util.Class",
+ "tinymce.core.util.Tools"
+ ],
+ function (Class, Tools) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Class.extend({
- Defaults: {
- firstControlClass: 'first',
- lastControlClass: 'last'
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Class.extend({
+ Defaults: {
+ firstControlClass: 'first',
+ lastControlClass: 'last'
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a layout instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- */
- init: function(settings) {
- this.settings = Tools.extend({}, this.Defaults, settings);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a layout instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ */
+ init: function (settings) {
+ this.settings = Tools.extend({}, this.Defaults, settings);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * This method gets invoked before the layout renders the controls.
- *
- * @method preRender
- * @param {tinymce.ui.Container} container Container instance to preRender.
- */
- preRender: function(container) {
- container.bodyClasses.add(this.settings.containerClass);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * This method gets invoked before the layout renders the controls.
+ *
+ * @method preRender
+ * @param {tinymce.ui.Container} container Container instance to preRender.
+ */
+ preRender: function (container) {
+ container.bodyClasses.add(this.settings.containerClass);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Applies layout classes to the container.
- *
- * @private
- */
- applyClasses: function(items) {
- var self = this, settings = self.settings, firstClass, lastClass, firstItem, lastItem;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Applies layout classes to the container.
+ *
+ * @private
+ */
+ applyClasses: function (items) {
+ var self = this, settings = self.settings, firstClass, lastClass, firstItem, lastItem;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- firstClass = settings.firstControlClass;
- lastClass = settings.lastControlClass;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ firstClass = settings.firstControlClass;
+ lastClass = settings.lastControlClass;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- items.each(function(item) {
- item.classes.remove(firstClass).remove(lastClass).add(settings.controlClass);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ items.each(function (item) {
+ item.classes.remove(firstClass).remove(lastClass).add(settings.controlClass);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (item.visible()) {
- if (!firstItem) {
- firstItem = item;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (item.visible()) {
+ if (!firstItem) {
+ firstItem = item;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- lastItem = item;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ lastItem = item;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (firstItem) {
- firstItem.classes.add(firstClass);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (firstItem) {
+ firstItem.classes.add(firstClass);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (lastItem) {
- lastItem.classes.add(lastClass);
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (lastItem) {
+ lastItem.classes.add(lastClass);
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the specified container and any layout specific HTML.
- *
- * @method renderHtml
- * @param {tinymce.ui.Container} container Container to render HTML for.
- */
- renderHtml: function(container) {
- var self = this, html = '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the specified container and any layout specific HTML.
+ *
+ * @method renderHtml
+ * @param {tinymce.ui.Container} container Container to render HTML for.
+ */
+ renderHtml: function (container) {
+ var self = this, html = '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.applyClasses(container.items());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.applyClasses(container.items());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container.items().each(function(item) {
- html += item.renderHtml();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container.items().each(function (item) {
+ html += item.renderHtml();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return html;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return html;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Recalculates the positions of the controls in the specified container.
- *
- * @method recalc
- * @param {tinymce.ui.Container} container Container instance to recalc.
- */
- recalc: function() {
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Recalculates the positions of the controls in the specified container.
+ *
+ * @method recalc
+ * @param {tinymce.ui.Container} container Container instance to recalc.
+ */
+ recalc: function () {
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * This method gets invoked after the layout renders the controls.
- *
- * @method postRender
- * @param {tinymce.ui.Container} container Container instance to postRender.
- */
- postRender: function() {
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * This method gets invoked after the layout renders the controls.
+ *
+ * @method postRender
+ * @param {tinymce.ui.Container} container Container instance to postRender.
+ */
+ postRender: function () {
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- isNative: function() {
- return false;
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/AbsoluteLayout.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ isNative: function () {
+ return false;
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * AbsoluteLayout.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -42525,59 +47681,60 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.AbsoluteLayout
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Layout
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/AbsoluteLayout", [
- "tinymce/ui/Layout"
-], function(Layout) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.AbsoluteLayout',
+ [
+ "tinymce.core.ui.Layout"
+ ],
+ function (Layout) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Layout.extend({
- Defaults: {
- containerClass: 'abs-layout',
- controlClass: 'abs-layout-item'
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Layout.extend({
+ Defaults: {
+ containerClass: 'abs-layout',
+ controlClass: 'abs-layout-item'
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Recalculates the positions of the controls in the specified container.
- *
- * @method recalc
- * @param {tinymce.ui.Container} container Container instance to recalc.
- */
- recalc: function(container) {
- container.items().filter(':visible').each(function(ctrl) {
- var settings = ctrl.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Recalculates the positions of the controls in the specified container.
+ *
+ * @method recalc
+ * @param {tinymce.ui.Container} container Container instance to recalc.
+ */
+ recalc: function (container) {
+ container.items().filter(':visible').each(function (ctrl) {
+ var settings = ctrl.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ctrl.layoutRect({
- x: settings.x,
- y: settings.y,
- w: settings.w,
- h: settings.h
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ctrl.layoutRect({
+ x: settings.x,
+ y: settings.y,
+ w: settings.w,
+ h: settings.h
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (ctrl.recalc) {
- ctrl.recalc();
- }
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (ctrl.recalc) {
+ ctrl.recalc();
+ }
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the specified container and any layout specific HTML.
- *
- * @method renderHtml
- * @param {tinymce.ui.Container} container Container to render HTML for.
- */
- renderHtml: function(container) {
- return '<div id="' + container._id + '-absend" class="' + container.classPrefix + 'abs-end"></div>' + this._super(container);
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/Button.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the specified container and any layout specific HTML.
+ *
+ * @method renderHtml
+ * @param {tinymce.ui.Container} container Container to render HTML for.
+ */
+ renderHtml: function (container) {
+ return '<div id="' + container._id + '-absend" class="' + container.classPrefix + 'abs-end"></div>' + this._super(container);
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Button.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -42597,189 +47754,191 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.Button
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Widget
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Button", [
- "tinymce/ui/Widget"
-], function(Widget) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Button',
+ [
+ "tinymce.core.ui.Widget"
+ ],
+ function (Widget) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Widget.extend({
- Defaults: {
- classes: "widget btn",
- role: "button"
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Widget.extend({
+ Defaults: {
+ classes: "widget btn",
+ role: "button"
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a new button instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- * @setting {String} size Size of the button small|medium|large.
- * @setting {String} image Image to use for icon.
- * @setting {String} icon Icon to use for button.
- */
- init: function(settings) {
- var self = this, size;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a new button instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ * @setting {String} size Size of the button small|medium|large.
+ * @setting {String} image Image to use for icon.
+ * @setting {String} icon Icon to use for button.
+ */
+ init: function (settings) {
+ var self = this, size;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super(settings);
- settings = self.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super(settings);
+ settings = self.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- size = self.settings.size;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ size = self.settings.size;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('click mousedown', function(e) {
- e.preventDefault();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('click mousedown', function (e) {
+ e.preventDefault();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('touchstart', function(e) {
- self.fire('click', e);
- e.preventDefault();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('touchstart', function (e) {
+ self.fire('click', e);
+ e.preventDefault();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.subtype) {
- self.classes.add(settings.subtype);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.subtype) {
+ self.classes.add(settings.subtype);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (size) {
- self.classes.add('btn-' + size);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (size) {
+ self.classes.add('btn-' + size);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.icon) {
- self.icon(settings.icon);
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.icon) {
+ self.icon(settings.icon);
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets/gets the current button icon.
- *
- * @method icon
- * @param {String} [icon] New icon identifier.
- * @return {String|tinymce.ui.MenuButton} Current icon or current MenuButton instance.
- */
- icon: function(icon) {
- if (!arguments.length) {
- return this.state.get('icon');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets/gets the current button icon.
+ *
+ * @method icon
+ * @param {String} [icon] New icon identifier.
+ * @return {String|tinymce.ui.MenuButton} Current icon or current MenuButton instance.
+ */
+ icon: function (icon) {
+ if (!arguments.length) {
+ return this.state.get('icon');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.state.set('icon', icon);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.state.set('icon', icon);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Repaints the button for example after it's been resizes by a layout engine.
- *
- * @method repaint
- */
- repaint: function() {
- var btnElm = this.getEl().firstChild,
- btnStyle;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Repaints the button for example after it's been resizes by a layout engine.
+ *
+ * @method repaint
+ */
+ repaint: function () {
+ var btnElm = this.getEl().firstChild,
+ btnStyle;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (btnElm) {
- btnStyle = btnElm.style;
- btnStyle.width = btnStyle.height = "100%";
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (btnElm) {
+ btnStyle = btnElm.style;
+ btnStyle.width = btnStyle.height = "100%";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this._super();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this._super();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this, id = self._id, prefix = self.classPrefix;
- var icon = self.state.get('icon'), image, text = self.state.get('text'), textHtml = '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this, id = self._id, prefix = self.classPrefix;
+ var icon = self.state.get('icon'), image, text = self.state.get('text'), textHtml = '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- image = self.settings.image;
- if (image) {
- icon = 'none';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ image = self.settings.image;
+ if (image) {
+ icon = 'none';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Support for [high dpi, low dpi] image sources
- if (typeof image != "string") {
- image = window.getSelection ? image[0] : image[1];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Support for [high dpi, low dpi] image sources
+ if (typeof image != "string") {
+ image = window.getSelection ? image[0] : image[1];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- image = ' style="background-image: url(\'' + image + '\')"';
- } else {
- image = '';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ image = ' style="background-image: url(\'' + image + '\')"';
+ } else {
+ image = '';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (text) {
- self.classes.add('btn-has-text');
- textHtml = '<span class="' + prefix + 'txt">' + self.encode(text) + '</span>';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (text) {
+ self.classes.add('btn-has-text');
+ textHtml = '<span class="' + prefix + 'txt">' + self.encode(text) + '</span>';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- icon = icon ? prefix + 'ico ' + prefix + 'i-' + icon : '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ icon = icon ? prefix + 'ico ' + prefix + 'i-' + icon : '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<div id="' + id + '" class="' + self.classes + '" tabindex="-1" aria-labelledby="' + id + '">' +
- '<button role="presentation" type="button" tabindex="-1">' +
- (icon ? '<i class="' + icon + '"' + image + '></i>' : '') +
- textHtml +
- '</button>' +
- '</div>'
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<div id="' + id + '" class="' + self.classes + '" tabindex="-1">' +
+ '<button role="presentation" type="button" tabindex="-1">' +
+ (icon ? '<i class="' + icon + '"' + image + '></i>' : '') +
+ textHtml +
+ '</button>' +
+ '</div>'
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bindStates: function() {
- var self = this, $ = self.$, textCls = self.classPrefix + 'txt';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bindStates: function () {
+ var self = this, $ = self.$, textCls = self.classPrefix + 'txt';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setButtonText(text) {
- var $span = $('span.' + textCls, self.getEl());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setButtonText(text) {
+ var $span = $('span.' + textCls, self.getEl());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (text) {
- if (!$span[0]) {
- $('button:first', self.getEl()).append('<span class="' + textCls + '"></span>');
- $span = $('span.' + textCls, self.getEl());
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (text) {
+ if (!$span[0]) {
+ $('button:first', self.getEl()).append('<span class="' + textCls + '"></span>');
+ $span = $('span.' + textCls, self.getEl());
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $span.html(self.encode(text));
- } else {
- $span.remove();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $span.html(self.encode(text));
+ } else {
+ $span.remove();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.classes.toggle('btn-has-text', !!text);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.classes.toggle('btn-has-text', !!text);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:text', function(e) {
- setButtonText(e.value);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:text', function (e) {
+ setButtonText(e.value);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:icon', function(e) {
- var icon = e.value, prefix = self.classPrefix;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:icon', function (e) {
+ var icon = e.value, prefix = self.classPrefix;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.settings.icon = icon;
- icon = icon ? prefix + 'ico ' + prefix + 'i-' + self.settings.icon : '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.settings.icon = icon;
+ icon = icon ? prefix + 'ico ' + prefix + 'i-' + self.settings.icon : '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var btnElm = self.getEl().firstChild, iconElm = btnElm.getElementsByTagName('i')[0];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var btnElm = self.getEl().firstChild, iconElm = btnElm.getElementsByTagName('i')[0];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (icon) {
- if (!iconElm || iconElm != btnElm.firstChild) {
- iconElm = document.createElement('i');
- btnElm.insertBefore(iconElm, btnElm.firstChild);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (icon) {
+ if (!iconElm || iconElm != btnElm.firstChild) {
+ iconElm = document.createElement('i');
+ btnElm.insertBefore(iconElm, btnElm.firstChild);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- iconElm.className = icon;
- } else if (iconElm) {
- btnElm.removeChild(iconElm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ iconElm.className = icon;
+ } else if (iconElm) {
+ btnElm.removeChild(iconElm);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- setButtonText(self.state.get('text'));
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ setButtonText(self.state.get('text'));
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- }
- });
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/ButtonGroup.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * ButtonGroup.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -42803,48 +47962,49 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.ButtonGroup
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Container
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/ButtonGroup", [
- "tinymce/ui/Container"
-], function(Container) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.ButtonGroup',
+ [
+ "tinymce.core.ui.Container"
+ ],
+ function (Container) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Container.extend({
- Defaults: {
- defaultType: 'button',
- role: 'group'
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Container.extend({
+ Defaults: {
+ defaultType: 'button',
+ role: 'group'
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this, layout = self._layout;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this, layout = self._layout;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.classes.add('btn-group');
- self.preRender();
- layout.preRender(self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.classes.add('btn-group');
+ self.preRender();
+ layout.preRender(self);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<div id="' + self._id + '" class="' + self.classes + '">' +
- '<div id="' + self._id + '-body">' +
- (self.settings.html || '') + layout.renderHtml(self) +
- '</div>' +
- '</div>'
- );
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/Checkbox.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<div id="' + self._id + '" class="' + self.classes + '">' +
+ '<div id="' + self._id + '-body">' +
+ (self.settings.html || '') + layout.renderHtml(self) +
+ '</div>' +
+ '</div>'
+ );
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Checkbox.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -42865,151 +48025,152 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.Checkbox
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Widget
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Checkbox", [
- "tinymce/ui/Widget"
-], function(Widget) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Checkbox',
+ [
+ "tinymce.core.ui.Widget"
+ ],
+ function (Widget) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Widget.extend({
- Defaults: {
- classes: "checkbox",
- role: "checkbox",
- checked: false
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Widget.extend({
+ Defaults: {
+ classes: "checkbox",
+ role: "checkbox",
+ checked: false
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a new Checkbox instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- * @setting {Boolean} checked True if the checkbox should be checked by default.
- */
- init: function(settings) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a new Checkbox instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ * @setting {Boolean} checked True if the checkbox should be checked by default.
+ */
+ init: function (settings) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super(settings);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super(settings);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('click mousedown', function(e) {
- e.preventDefault();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('click mousedown', function (e) {
+ e.preventDefault();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('click', function(e) {
- e.preventDefault();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('click', function (e) {
+ e.preventDefault();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.disabled()) {
- self.checked(!self.checked());
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.disabled()) {
+ self.checked(!self.checked());
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.checked(self.settings.checked);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.checked(self.settings.checked);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Getter/setter function for the checked state.
- *
- * @method checked
- * @param {Boolean} [state] State to be set.
- * @return {Boolean|tinymce.ui.Checkbox} True/false or checkbox if it's a set operation.
- */
- checked: function(state) {
- if (!arguments.length) {
- return this.state.get('checked');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Getter/setter function for the checked state.
+ *
+ * @method checked
+ * @param {Boolean} [state] State to be set.
+ * @return {Boolean|tinymce.ui.Checkbox} True/false or checkbox if it's a set operation.
+ */
+ checked: function (state) {
+ if (!arguments.length) {
+ return this.state.get('checked');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.state.set('checked', state);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.state.set('checked', state);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Getter/setter function for the value state.
- *
- * @method value
- * @param {Boolean} [state] State to be set.
- * @return {Boolean|tinymce.ui.Checkbox} True/false or checkbox if it's a set operation.
- */
- value: function(state) {
- if (!arguments.length) {
- return this.checked();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Getter/setter function for the value state.
+ *
+ * @method value
+ * @param {Boolean} [state] State to be set.
+ * @return {Boolean|tinymce.ui.Checkbox} True/false or checkbox if it's a set operation.
+ */
+ value: function (state) {
+ if (!arguments.length) {
+ return this.checked();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this.checked(state);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this.checked(state);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this, id = self._id, prefix = self.classPrefix;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this, id = self._id, prefix = self.classPrefix;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<div id="' + id + '" class="' + self.classes + '" unselectable="on" aria-labelledby="' + id + '-al" tabindex="-1">' +
- '<i class="' + prefix + 'ico ' + prefix + 'i-checkbox"></i>' +
- '<span id="' + id + '-al" class="' + prefix + 'label">' + self.encode(self.state.get('text')) + '</span>' +
- '</div>'
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<div id="' + id + '" class="' + self.classes + '" unselectable="on" aria-labelledby="' + id + '-al" tabindex="-1">' +
+ '<i class="' + prefix + 'ico ' + prefix + 'i-checkbox"></i>' +
+ '<span id="' + id + '-al" class="' + prefix + 'label">' + self.encode(self.state.get('text')) + '</span>' +
+ '</div>'
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bindStates: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bindStates: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function checked(state) {
- self.classes.toggle("checked", state);
- self.aria('checked', state);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function checked(state) {
+ self.classes.toggle("checked", state);
+ self.aria('checked', state);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:text', function(e) {
- self.getEl('al').firstChild.data = self.translate(e.value);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:text', function (e) {
+ self.getEl('al').firstChild.data = self.translate(e.value);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:checked change:value', function(e) {
- self.fire('change');
- checked(e.value);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:checked change:value', function (e) {
+ self.fire('change');
+ checked(e.value);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:icon', function(e) {
- var icon = e.value, prefix = self.classPrefix;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:icon', function (e) {
+ var icon = e.value, prefix = self.classPrefix;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof icon == 'undefined') {
- return self.settings.icon;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof icon == 'undefined') {
+ return self.settings.icon;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.settings.icon = icon;
- icon = icon ? prefix + 'ico ' + prefix + 'i-' + self.settings.icon : '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.settings.icon = icon;
+ icon = icon ? prefix + 'ico ' + prefix + 'i-' + self.settings.icon : '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var btnElm = self.getEl().firstChild, iconElm = btnElm.getElementsByTagName('i')[0];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var btnElm = self.getEl().firstChild, iconElm = btnElm.getElementsByTagName('i')[0];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (icon) {
- if (!iconElm || iconElm != btnElm.firstChild) {
- iconElm = document.createElement('i');
- btnElm.insertBefore(iconElm, btnElm.firstChild);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (icon) {
+ if (!iconElm || iconElm != btnElm.firstChild) {
+ iconElm = document.createElement('i');
+ btnElm.insertBefore(iconElm, btnElm.firstChild);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- iconElm.className = icon;
- } else if (iconElm) {
- btnElm.removeChild(iconElm);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ iconElm.className = icon;
+ } else if (iconElm) {
+ btnElm.removeChild(iconElm);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.state.get('checked')) {
- checked(true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.state.get('checked')) {
+ checked(true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/ComboBox.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * ComboBox.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -43023,463 +48184,464 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.ComboBox
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Widget
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/ComboBox", [
- "tinymce/ui/Widget",
- "tinymce/ui/Factory",
- "tinymce/ui/DomUtils",
- "tinymce/dom/DomQuery",
- "tinymce/util/VK",
- "tinymce/util/Tools"
-], function(Widget, Factory, DomUtils, $, VK, Tools) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.ComboBox',
+ [
+ "tinymce.core.ui.Widget",
+ "tinymce.core.ui.Factory",
+ "tinymce.core.ui.DomUtils",
+ "tinymce.core.dom.DomQuery",
+ "tinymce.core.util.VK",
+ "tinymce.core.util.Tools"
+ ],
+ function (Widget, Factory, DomUtils, $, VK, Tools) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Widget.extend({
- /**
- * Constructs a new control instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- * @setting {String} placeholder Placeholder text to display.
- */
- init: function(settings) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Widget.extend({
+ /**
+ * Constructs a new control instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ * @setting {String} placeholder Placeholder text to display.
+ */
+ init: function (settings) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super(settings);
- settings = self.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super(settings);
+ settings = self.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.classes.add('combobox');
- self.subinput = true;
- self.ariaTarget = 'inp'; // TODO: Figure out a better way
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.classes.add('combobox');
+ self.subinput = true;
+ self.ariaTarget = 'inp'; // TODO: Figure out a better way
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- settings.menu = settings.menu || settings.values;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ settings.menu = settings.menu || settings.values;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.menu) {
- settings.icon = 'caret';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.menu) {
+ settings.icon = 'caret';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('click', function(e) {
- var elm = e.target, root = self.getEl();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('click', function (e) {
+ var elm = e.target, root = self.getEl();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!$.contains(root, elm) && elm != root) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!$.contains(root, elm) && elm != root) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (elm && elm != root) {
- if (elm.id && elm.id.indexOf('-open') != -1) {
- self.fire('action');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (elm && elm != root) {
+ if (elm.id && elm.id.indexOf('-open') != -1) {
+ self.fire('action');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.menu) {
- self.showMenu();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.menu) {
+ self.showMenu();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.aria) {
- self.menu.items()[0].focus();
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.aria) {
+ self.menu.items()[0].focus();
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elm = elm.parentNode;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elm = elm.parentNode;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // TODO: Rework this
- self.on('keydown', function(e) {
- var rootControl;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // TODO: Rework this
+ self.on('keydown', function (e) {
+ var rootControl;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.keyCode == 13 && e.target.nodeName === 'INPUT') {
- e.preventDefault();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.keyCode == 13 && e.target.nodeName === 'INPUT') {
+ e.preventDefault();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Find root control that we can do toJSON on
- self.parents().reverse().each(function(ctrl) {
- if (ctrl.toJSON) {
- rootControl = ctrl;
- return false;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find root control that we can do toJSON on
+ self.parents().reverse().each(function (ctrl) {
+ if (ctrl.toJSON) {
+ rootControl = ctrl;
+ return false;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Fire event on current text box with the serialized data of the whole form
- self.fire('submit', {data: rootControl.toJSON()});
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Fire event on current text box with the serialized data of the whole form
+ self.fire('submit', { data: rootControl.toJSON() });
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('keyup', function(e) {
- if (e.target.nodeName == "INPUT") {
- var oldValue = self.state.get('value');
- var newValue = e.target.value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('keyup', function (e) {
+ if (e.target.nodeName == "INPUT") {
+ var oldValue = self.state.get('value');
+ var newValue = e.target.value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (newValue !== oldValue) {
- self.state.set('value', newValue);
- self.fire('autocomplete', e);
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (newValue !== oldValue) {
+ self.state.set('value', newValue);
+ self.fire('autocomplete', e);
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('mouseover', function(e) {
- var tooltip = self.tooltip().moveTo(-0xFFFF);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('mouseover', function (e) {
+ var tooltip = self.tooltip().moveTo(-0xFFFF);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.statusLevel() && e.target.className.indexOf(self.classPrefix + 'status') !== -1) {
- var statusMessage = self.statusMessage() || 'Ok';
- var rel = tooltip.text(statusMessage).show().testMoveRel(e.target, ['bc-tc', 'bc-tl', 'bc-tr']);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.statusLevel() && e.target.className.indexOf(self.classPrefix + 'status') !== -1) {
+ var statusMessage = self.statusMessage() || 'Ok';
+ var rel = tooltip.text(statusMessage).show().testMoveRel(e.target, ['bc-tc', 'bc-tl', 'bc-tr']);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tooltip.classes.toggle('tooltip-n', rel == 'bc-tc');
- tooltip.classes.toggle('tooltip-nw', rel == 'bc-tl');
- tooltip.classes.toggle('tooltip-ne', rel == 'bc-tr');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ tooltip.classes.toggle('tooltip-n', rel == 'bc-tc');
+ tooltip.classes.toggle('tooltip-nw', rel == 'bc-tl');
+ tooltip.classes.toggle('tooltip-ne', rel == 'bc-tr');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tooltip.moveRel(e.target, rel);
- }
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ tooltip.moveRel(e.target, rel);
+ }
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- statusLevel: function (value) {
- if (arguments.length > 0) {
- this.state.set('statusLevel', value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ statusLevel: function (value) {
+ if (arguments.length > 0) {
+ this.state.set('statusLevel', value);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this.state.get('statusLevel');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this.state.get('statusLevel');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- statusMessage: function (value) {
- if (arguments.length > 0) {
- this.state.set('statusMessage', value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ statusMessage: function (value) {
+ if (arguments.length > 0) {
+ this.state.set('statusMessage', value);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this.state.get('statusMessage');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this.state.get('statusMessage');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- showMenu: function() {
- var self = this, settings = self.settings, menu;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ showMenu: function () {
+ var self = this, settings = self.settings, menu;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.menu) {
- menu = settings.menu || [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.menu) {
+ menu = settings.menu || [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Is menu array then auto constuct menu control
- if (menu.length) {
- menu = {
- type: 'menu',
- items: menu
- };
- } else {
- menu.type = menu.type || 'menu';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Is menu array then auto constuct menu control
+ if (menu.length) {
+ menu = {
+ type: 'menu',
+ items: menu
+ };
+ } else {
+ menu.type = menu.type || 'menu';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.menu = Factory.create(menu).parent(self).renderTo(self.getContainerElm());
- self.fire('createmenu');
- self.menu.reflow();
- self.menu.on('cancel', function(e) {
- if (e.control === self.menu) {
- self.focus();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.menu = Factory.create(menu).parent(self).renderTo(self.getContainerElm());
+ self.fire('createmenu');
+ self.menu.reflow();
+ self.menu.on('cancel', function (e) {
+ if (e.control === self.menu) {
+ self.focus();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.menu.on('show hide', function(e) {
- e.control.items().each(function(ctrl) {
- ctrl.active(ctrl.value() == self.value());
- });
- }).fire('show');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.menu.on('show hide', function (e) {
+ e.control.items().each(function (ctrl) {
+ ctrl.active(ctrl.value() == self.value());
+ });
+ }).fire('show');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.menu.on('select', function(e) {
- self.value(e.control.value());
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.menu.on('select', function (e) {
+ self.value(e.control.value());
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('focusin', function(e) {
- if (e.target.tagName.toUpperCase() == 'INPUT') {
- self.menu.hide();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('focusin', function (e) {
+ if (e.target.tagName.toUpperCase() == 'INPUT') {
+ self.menu.hide();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.aria('expanded', true);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.aria('expanded', true);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.menu.show();
- self.menu.layoutRect({w: self.layoutRect().w});
- self.menu.moveRel(self.getEl(), self.isRtl() ? ['br-tr', 'tr-br'] : ['bl-tl', 'tl-bl']);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.menu.show();
+ self.menu.layoutRect({ w: self.layoutRect().w });
+ self.menu.moveRel(self.getEl(), self.isRtl() ? ['br-tr', 'tr-br'] : ['bl-tl', 'tl-bl']);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Focuses the input area of the control.
- *
- * @method focus
- */
- focus: function() {
- this.getEl('inp').focus();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Focuses the input area of the control.
+ *
+ * @method focus
+ */
+ focus: function () {
+ this.getEl('inp').focus();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Repaints the control after a layout operation.
- *
- * @method repaint
- */
- repaint: function() {
- var self = this, elm = self.getEl(), openElm = self.getEl('open'), rect = self.layoutRect();
- var width, lineHeight, innerPadding = 0, inputElm = elm.firstChild;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Repaints the control after a layout operation.
+ *
+ * @method repaint
+ */
+ repaint: function () {
+ var self = this, elm = self.getEl(), openElm = self.getEl('open'), rect = self.layoutRect();
+ var width, lineHeight, innerPadding = 0, inputElm = elm.firstChild;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.statusLevel() && self.statusLevel() !== 'none') {
- innerPadding = (
- parseInt(DomUtils.getRuntimeStyle(inputElm, 'padding-right'), 10) -
- parseInt(DomUtils.getRuntimeStyle(inputElm, 'padding-left'), 10)
- );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.statusLevel() && self.statusLevel() !== 'none') {
+ innerPadding = (
+ parseInt(DomUtils.getRuntimeStyle(inputElm, 'padding-right'), 10) -
+ parseInt(DomUtils.getRuntimeStyle(inputElm, 'padding-left'), 10)
+ );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (openElm) {
- width = rect.w - DomUtils.getSize(openElm).width - 10;
- } else {
- width = rect.w - 10;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (openElm) {
+ width = rect.w - DomUtils.getSize(openElm).width - 10;
+ } else {
+ width = rect.w - 10;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Detect old IE 7+8 add lineHeight to align caret vertically in the middle
- var doc = document;
- if (doc.all && (!doc.documentMode || doc.documentMode <= 8)) {
- lineHeight = (self.layoutRect().h - 2) + 'px';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Detect old IE 7+8 add lineHeight to align caret vertically in the middle
+ var doc = document;
+ if (doc.all && (!doc.documentMode || doc.documentMode <= 8)) {
+ lineHeight = (self.layoutRect().h - 2) + 'px';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $(inputElm).css({
- width: width - innerPadding,
- lineHeight: lineHeight
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $(inputElm).css({
+ width: width - innerPadding,
+ lineHeight: lineHeight
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Post render method. Called after the control has been rendered to the target.
- *
- * @method postRender
- * @return {tinymce.ui.ComboBox} Current combobox instance.
- */
- postRender: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Post render method. Called after the control has been rendered to the target.
+ *
+ * @method postRender
+ * @return {tinymce.ui.ComboBox} Current combobox instance.
+ */
+ postRender: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $(this.getEl('inp')).on('change', function(e) {
- self.state.set('value', e.target.value);
- self.fire('change', e);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $(this.getEl('inp')).on('change', function (e) {
+ self.state.set('value', e.target.value);
+ self.fire('change', e);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this, id = self._id, settings = self.settings, prefix = self.classPrefix;
- var value = self.state.get('value') || '';
- var icon, text, openBtnHtml = '', extraAttrs = '', statusHtml = '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this, id = self._id, settings = self.settings, prefix = self.classPrefix;
+ var value = self.state.get('value') || '';
+ var icon, text, openBtnHtml = '', extraAttrs = '', statusHtml = '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ("spellcheck" in settings) {
- extraAttrs += ' spellcheck="' + settings.spellcheck + '"';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ("spellcheck" in settings) {
+ extraAttrs += ' spellcheck="' + settings.spellcheck + '"';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.maxLength) {
- extraAttrs += ' maxlength="' + settings.maxLength + '"';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.maxLength) {
+ extraAttrs += ' maxlength="' + settings.maxLength + '"';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.size) {
- extraAttrs += ' size="' + settings.size + '"';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.size) {
+ extraAttrs += ' size="' + settings.size + '"';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.subtype) {
- extraAttrs += ' type="' + settings.subtype + '"';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.subtype) {
+ extraAttrs += ' type="' + settings.subtype + '"';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- statusHtml = '<i id="' + id + '-status" class="mce-status mce-ico" style="display: none"></i>';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ statusHtml = '<i id="' + id + '-status" class="mce-status mce-ico" style="display: none"></i>';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.disabled()) {
- extraAttrs += ' disabled="disabled"';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.disabled()) {
+ extraAttrs += ' disabled="disabled"';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- icon = settings.icon;
- if (icon && icon != 'caret') {
- icon = prefix + 'ico ' + prefix + 'i-' + settings.icon;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ icon = settings.icon;
+ if (icon && icon != 'caret') {
+ icon = prefix + 'ico ' + prefix + 'i-' + settings.icon;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- text = self.state.get('text');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ text = self.state.get('text');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (icon || text) {
- openBtnHtml = (
- '<div id="' + id + '-open" class="' + prefix + 'btn ' + prefix + 'open" tabIndex="-1" role="button">' +
- '<button id="' + id + '-action" type="button" hidefocus="1" tabindex="-1">' +
- (icon != 'caret' ? '<i class="' + icon + '"></i>' : '<i class="' + prefix + 'caret"></i>') +
- (text ? (icon ? ' ' : '') + text : '') +
- '</button>' +
- '</div>'
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (icon || text) {
+ openBtnHtml = (
+ '<div id="' + id + '-open" class="' + prefix + 'btn ' + prefix + 'open" tabIndex="-1" role="button">' +
+ '<button id="' + id + '-action" type="button" hidefocus="1" tabindex="-1">' +
+ (icon != 'caret' ? '<i class="' + icon + '"></i>' : '<i class="' + prefix + 'caret"></i>') +
+ (text ? (icon ? ' ' : '') + text : '') +
+ '</button>' +
+ '</div>'
+ );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.classes.add('has-open');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.classes.add('has-open');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<div id="' + id + '" class="' + self.classes + '">' +
- '<input id="' + id + '-inp" class="' + prefix + 'textbox" value="' +
- self.encode(value, false) + '" hidefocus="1"' + extraAttrs + ' placeholder="' +
- self.encode(settings.placeholder) + '" />' +
- statusHtml +
- openBtnHtml +
- '</div>'
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<div id="' + id + '" class="' + self.classes + '">' +
+ '<input id="' + id + '-inp" class="' + prefix + 'textbox" value="' +
+ self.encode(value, false) + '" hidefocus="1"' + extraAttrs + ' placeholder="' +
+ self.encode(settings.placeholder) + '" />' +
+ statusHtml +
+ openBtnHtml +
+ '</div>'
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- value: function(value) {
- if (arguments.length) {
- this.state.set('value', value);
- return this;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ value: function (value) {
+ if (arguments.length) {
+ this.state.set('value', value);
+ return this;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Make sure the real state is in sync
- if (this.state.get('rendered')) {
- this.state.set('value', this.getEl('inp').value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Make sure the real state is in sync
+ if (this.state.get('rendered')) {
+ this.state.set('value', this.getEl('inp').value);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this.state.get('value');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this.state.get('value');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- showAutoComplete: function (items, term) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ showAutoComplete: function (items, term) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (items.length === 0) {
- self.hideMenu();
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (items.length === 0) {
+ self.hideMenu();
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var insert = function (value, title) {
- return function () {
- self.fire('selectitem', {
- title: title,
- value: value
- });
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var insert = function (value, title) {
+ return function () {
+ self.fire('selectitem', {
+ title: title,
+ value: value
+ });
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.menu) {
- self.menu.items().remove();
- } else {
- self.menu = Factory.create({
- type: 'menu',
- classes: 'combobox-menu',
- layout: 'flow'
- }).parent(self).renderTo();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.menu) {
+ self.menu.items().remove();
+ } else {
+ self.menu = Factory.create({
+ type: 'menu',
+ classes: 'combobox-menu',
+ layout: 'flow'
+ }).parent(self).renderTo();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(items, function (item) {
- self.menu.add({
- text: item.title,
- url: item.previewUrl,
- match: term,
- classes: 'menu-item-ellipsis',
- onclick: insert(item.value, item.title)
- });
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(items, function (item) {
+ self.menu.add({
+ text: item.title,
+ url: item.previewUrl,
+ match: term,
+ classes: 'menu-item-ellipsis',
+ onclick: insert(item.value, item.title)
+ });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.menu.renderNew();
- self.hideMenu();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.menu.renderNew();
+ self.hideMenu();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.menu.on('cancel', function(e) {
- if (e.control.parent() === self.menu) {
- e.stopPropagation();
- self.focus();
- self.hideMenu();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.menu.on('cancel', function (e) {
+ if (e.control.parent() === self.menu) {
+ e.stopPropagation();
+ self.focus();
+ self.hideMenu();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.menu.on('select', function() {
- self.focus();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.menu.on('select', function () {
+ self.focus();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var maxW = self.layoutRect().w;
- self.menu.layoutRect({w: maxW, minW: 0, maxW: maxW});
- self.menu.reflow();
- self.menu.show();
- self.menu.moveRel(self.getEl(), self.isRtl() ? ['br-tr', 'tr-br'] : ['bl-tl', 'tl-bl']);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var maxW = self.layoutRect().w;
+ self.menu.layoutRect({ w: maxW, minW: 0, maxW: maxW });
+ self.menu.reflow();
+ self.menu.show();
+ self.menu.moveRel(self.getEl(), self.isRtl() ? ['br-tr', 'tr-br'] : ['bl-tl', 'tl-bl']);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- hideMenu: function() {
- if (this.menu) {
- this.menu.hide();
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ hideMenu: function () {
+ if (this.menu) {
+ this.menu.hide();
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bindStates: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bindStates: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:value', function(e) {
- if (self.getEl('inp').value != e.value) {
- self.getEl('inp').value = e.value;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:value', function (e) {
+ if (self.getEl('inp').value != e.value) {
+ self.getEl('inp').value = e.value;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:disabled', function(e) {
- self.getEl('inp').disabled = e.value;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:disabled', function (e) {
+ self.getEl('inp').disabled = e.value;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:statusLevel', function(e) {
- var statusIconElm = self.getEl('status');
- var prefix = self.classPrefix, value = e.value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:statusLevel', function (e) {
+ var statusIconElm = self.getEl('status');
+ var prefix = self.classPrefix, value = e.value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DomUtils.css(statusIconElm, 'display', value === 'none' ? 'none' : '');
- DomUtils.toggleClass(statusIconElm, prefix + 'i-checkmark', value === 'ok');
- DomUtils.toggleClass(statusIconElm, prefix + 'i-warning', value === 'warn');
- DomUtils.toggleClass(statusIconElm, prefix + 'i-error', value === 'error');
- self.classes.toggle('has-status', value !== 'none');
- self.repaint();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DomUtils.css(statusIconElm, 'display', value === 'none' ? 'none' : '');
+ DomUtils.toggleClass(statusIconElm, prefix + 'i-checkmark', value === 'ok');
+ DomUtils.toggleClass(statusIconElm, prefix + 'i-warning', value === 'warn');
+ DomUtils.toggleClass(statusIconElm, prefix + 'i-error', value === 'error');
+ self.classes.toggle('has-status', value !== 'none');
+ self.repaint();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DomUtils.on(self.getEl('status'), 'mouseleave', function () {
- self.tooltip().hide();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DomUtils.on(self.getEl('status'), 'mouseleave', function () {
+ self.tooltip().hide();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('cancel', function (e) {
- if (self.menu && self.menu.visible()) {
- e.stopPropagation();
- self.hideMenu();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('cancel', function (e) {
+ if (self.menu && self.menu.visible()) {
+ e.stopPropagation();
+ self.hideMenu();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var focusIdx = function (idx, menu) {
- if (menu && menu.items().length > 0) {
- menu.items().eq(idx)[0].focus();
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var focusIdx = function (idx, menu) {
+ if (menu && menu.items().length > 0) {
+ menu.items().eq(idx)[0].focus();
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('keydown', function (e) {
- var keyCode = e.keyCode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('keydown', function (e) {
+ var keyCode = e.keyCode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.target.nodeName === 'INPUT') {
- if (keyCode === VK.DOWN) {
- e.preventDefault();
- self.fire('autocomplete');
- focusIdx(0, self.menu);
- } else if (keyCode === VK.UP) {
- e.preventDefault();
- focusIdx(-1, self.menu);
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.target.nodeName === 'INPUT') {
+ if (keyCode === VK.DOWN) {
+ e.preventDefault();
+ self.fire('autocomplete');
+ focusIdx(0, self.menu);
+ } else if (keyCode === VK.UP) {
+ e.preventDefault();
+ focusIdx(-1, self.menu);
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- remove: function() {
- $(this.getEl('inp')).off();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ remove: function () {
+ $(this.getEl('inp')).off();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.menu) {
- this.menu.remove();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.menu) {
+ this.menu.remove();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this._super();
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/ColorBox.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this._super();
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * ColorBox.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -43493,69 +48655,70 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.ColorBox
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.ComboBox
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/ColorBox", [
- "tinymce/ui/ComboBox"
-], function(ComboBox) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.ColorBox',
+ [
+ "tinymce.core.ui.ComboBox"
+ ],
+ function (ComboBox) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return ComboBox.extend({
- /**
- * Constructs a new control instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- */
- init: function(settings) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return ComboBox.extend({
+ /**
+ * Constructs a new control instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ */
+ init: function (settings) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- settings.spellcheck = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ settings.spellcheck = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.onaction) {
- settings.icon = 'none';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.onaction) {
+ settings.icon = 'none';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super(settings);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super(settings);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.classes.add('colorbox');
- self.on('change keyup postrender', function() {
- self.repaintColor(self.value());
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.classes.add('colorbox');
+ self.on('change keyup postrender', function () {
+ self.repaintColor(self.value());
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- repaintColor: function(value) {
- var openElm = this.getEl('open');
- var elm = openElm ? openElm.getElementsByTagName('i')[0] : null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ repaintColor: function (value) {
+ var openElm = this.getEl('open');
+ var elm = openElm ? openElm.getElementsByTagName('i')[0] : null;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elm) {
- try {
- elm.style.background = value;
- } catch (ex) {
- // Ignore
- }
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (elm) {
+ try {
+ elm.style.background = value;
+ } catch (ex) {
+ // Ignore
+ }
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bindStates: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bindStates: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:value', function(e) {
- if (self.state.get('rendered')) {
- self.repaintColor(e.value);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:value', function (e) {
+ if (self.state.get('rendered')) {
+ self.repaintColor(e.value);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/PanelButton.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * PanelButton.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -43567,112 +48730,113 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.PanelButton
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Button
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/PanelButton", [
- "tinymce/ui/Button",
- "tinymce/ui/FloatPanel"
-], function(Button, FloatPanel) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.PanelButton',
+ [
+ "tinymce.core.ui.Button",
+ "tinymce.core.ui.FloatPanel"
+ ],
+ function (Button, FloatPanel) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Button.extend({
- /**
- * Shows the panel for the button.
- *
- * @method showPanel
- */
- showPanel: function() {
- var self = this, settings = self.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Button.extend({
+ /**
+ * Shows the panel for the button.
+ *
+ * @method showPanel
+ */
+ showPanel: function () {
+ var self = this, settings = self.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.active(true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.active(true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.panel) {
- var panelSettings = settings.panel;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.panel) {
+ var panelSettings = settings.panel;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Wrap panel in grid layout if type if specified
- // This makes it possible to add forms or other containers directly in the panel option
- if (panelSettings.type) {
- panelSettings = {
- layout: 'grid',
- items: panelSettings
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Wrap panel in grid layout if type if specified
+ // This makes it possible to add forms or other containers directly in the panel option
+ if (panelSettings.type) {
+ panelSettings = {
+ layout: 'grid',
+ items: panelSettings
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- panelSettings.role = panelSettings.role || 'dialog';
- panelSettings.popover = true;
- panelSettings.autohide = true;
- panelSettings.ariaRoot = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ panelSettings.role = panelSettings.role || 'dialog';
+ panelSettings.popover = true;
+ panelSettings.autohide = true;
+ panelSettings.ariaRoot = true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.panel = new FloatPanel(panelSettings).on('hide', function() {
- self.active(false);
- }).on('cancel', function(e) {
- e.stopPropagation();
- self.focus();
- self.hidePanel();
- }).parent(self).renderTo(self.getContainerElm());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.panel = new FloatPanel(panelSettings).on('hide', function () {
+ self.active(false);
+ }).on('cancel', function (e) {
+ e.stopPropagation();
+ self.focus();
+ self.hidePanel();
+ }).parent(self).renderTo(self.getContainerElm());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.panel.fire('show');
- self.panel.reflow();
- } else {
- self.panel.show();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.panel.fire('show');
+ self.panel.reflow();
+ } else {
+ self.panel.show();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.panel.moveRel(self.getEl(), settings.popoverAlign || (self.isRtl() ? ['bc-tr', 'bc-tc'] : ['bc-tl', 'bc-tc']));
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.panel.moveRel(self.getEl(), settings.popoverAlign || (self.isRtl() ? ['bc-tr', 'bc-tc'] : ['bc-tl', 'bc-tc']));
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Hides the panel for the button.
- *
- * @method hidePanel
- */
- hidePanel: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Hides the panel for the button.
+ *
+ * @method hidePanel
+ */
+ hidePanel: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.panel) {
- self.panel.hide();
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.panel) {
+ self.panel.hide();
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Called after the control has been rendered.
- *
- * @method postRender
- */
- postRender: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Called after the control has been rendered.
+ *
+ * @method postRender
+ */
+ postRender: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.aria('haspopup', true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.aria('haspopup', true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('click', function(e) {
- if (e.control === self) {
- if (self.panel && self.panel.visible()) {
- self.hidePanel();
- } else {
- self.showPanel();
- self.panel.focus(!!e.aria);
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('click', function (e) {
+ if (e.control === self) {
+ if (self.panel && self.panel.visible()) {
+ self.hidePanel();
+ } else {
+ self.showPanel();
+ self.panel.focus(!!e.aria);
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- remove: function() {
- if (this.panel) {
- this.panel.remove();
- this.panel = null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ remove: function () {
+ if (this.panel) {
+ this.panel.remove();
+ this.panel = null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this._super();
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/ColorButton.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this._super();
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * ColorButton.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -43687,357 +48851,121 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.ColorButton
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.PanelButton
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/ColorButton", [
- "tinymce/ui/PanelButton",
- "tinymce/dom/DOMUtils"
-], function(PanelButton, DomUtils) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.ColorButton',
+ [
+ "tinymce.core.ui.PanelButton",
+ "tinymce.core.dom.DOMUtils"
+ ],
+ function (PanelButton, DomUtils) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var DOM = DomUtils.DOM;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var DOM = DomUtils.DOM;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return PanelButton.extend({
- /**
- * Constructs a new ColorButton instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- */
- init: function(settings) {
- this._super(settings);
- this.classes.add('colorbutton');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return PanelButton.extend({
+ /**
+ * Constructs a new ColorButton instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ */
+ init: function (settings) {
+ this._super(settings);
+ this.classes.add('colorbutton');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Getter/setter for the current color.
- *
- * @method color
- * @param {String} [color] Color to set.
- * @return {String|tinymce.ui.ColorButton} Current color or current instance.
- */
- color: function(color) {
- if (color) {
- this._color = color;
- this.getEl('preview').style.backgroundColor = color;
- return this;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Getter/setter for the current color.
+ *
+ * @method color
+ * @param {String} [color] Color to set.
+ * @return {String|tinymce.ui.ColorButton} Current color or current instance.
+ */
+ color: function (color) {
+ if (color) {
+ this._color = color;
+ this.getEl('preview').style.backgroundColor = color;
+ return this;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this._color;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this._color;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Resets the current color.
- *
- * @method resetColor
- * @return {tinymce.ui.ColorButton} Current instance.
- */
- resetColor: function() {
- this._color = null;
- this.getEl('preview').style.backgroundColor = null;
- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Resets the current color.
+ *
+ * @method resetColor
+ * @return {tinymce.ui.ColorButton} Current instance.
+ */
+ resetColor: function () {
+ this._color = null;
+ this.getEl('preview').style.backgroundColor = null;
+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this, id = self._id, prefix = self.classPrefix, text = self.state.get('text');
- var icon = self.settings.icon ? prefix + 'ico ' + prefix + 'i-' + self.settings.icon : '';
- var image = self.settings.image ? ' style="background-image: url(\'' + self.settings.image + '\')"' : '',
- textHtml = '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this, id = self._id, prefix = self.classPrefix, text = self.state.get('text');
+ var icon = self.settings.icon ? prefix + 'ico ' + prefix + 'i-' + self.settings.icon : '';
+ var image = self.settings.image ? ' style="background-image: url(\'' + self.settings.image + '\')"' : '',
+ textHtml = '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (text) {
- self.classes.add('btn-has-text');
- textHtml = '<span class="' + prefix + 'txt">' + self.encode(text) + '</span>';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (text) {
+ self.classes.add('btn-has-text');
+ textHtml = '<span class="' + prefix + 'txt">' + self.encode(text) + '</span>';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<div id="' + id + '" class="' + self.classes + '" role="button" tabindex="-1" aria-haspopup="true">' +
- '<button role="presentation" hidefocus="1" type="button" tabindex="-1">' +
- (icon ? '<i class="' + icon + '"' + image + '></i>' : '') +
- '<span id="' + id + '-preview" class="' + prefix + 'preview"></span>' +
- textHtml +
- '</button>' +
- '<button type="button" class="' + prefix + 'open" hidefocus="1" tabindex="-1">' +
- ' <i class="' + prefix + 'caret"></i>' +
- '</button>' +
- '</div>'
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<div id="' + id + '" class="' + self.classes + '" role="button" tabindex="-1" aria-haspopup="true">' +
+ '<button role="presentation" hidefocus="1" type="button" tabindex="-1">' +
+ (icon ? '<i class="' + icon + '"' + image + '></i>' : '') +
+ '<span id="' + id + '-preview" class="' + prefix + 'preview"></span>' +
+ textHtml +
+ '</button>' +
+ '<button type="button" class="' + prefix + 'open" hidefocus="1" tabindex="-1">' +
+ ' <i class="' + prefix + 'caret"></i>' +
+ '</button>' +
+ '</div>'
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Called after the control has been rendered.
- *
- * @method postRender
- */
- postRender: function() {
- var self = this, onClickHandler = self.settings.onclick;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Called after the control has been rendered.
+ *
+ * @method postRender
+ */
+ postRender: function () {
+ var self = this, onClickHandler = self.settings.onclick;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('click', function(e) {
- if (e.aria && e.aria.key == 'down') {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('click', function (e) {
+ if (e.aria && e.aria.key == 'down') {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.control == self && !DOM.getParent(e.target, '.' + self.classPrefix + 'open')) {
- e.stopImmediatePropagation();
- onClickHandler.call(self, e);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.control == self && !DOM.getParent(e.target, '.' + self.classPrefix + 'open')) {
+ e.stopImmediatePropagation();
+ onClickHandler.call(self, e);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- delete self.settings.onclick;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ delete self.settings.onclick;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- }
- });
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/util/Color.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Color.js
- *
- * Released under LGPL License.
- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- */
-
-/**
- * This class lets you parse/serialize colors and convert rgb/hsb.
- *
- * @class tinymce.util.Color
- * @example
- * var white = new tinymce.util.Color({r: 255, g: 255, b: 255});
- * var red = new tinymce.util.Color('#FF0000');
- *
- * console.log(white.toHex(), red.toHsv());
- */
-define("tinymce/util/Color", [], function() {
- var min = Math.min, max = Math.max, round = Math.round;
-
- /**
- * Constructs a new color instance.
- *
- * @constructor
- * @method Color
- * @param {String} value Optional initial value to parse.
- */
- function Color(value) {
- var self = this, r = 0, g = 0, b = 0;
-
- function rgb2hsv(r, g, b) {
- var h, s, v, d, minRGB, maxRGB;
-
- h = 0;
- s = 0;
- v = 0;
- r = r / 255;
- g = g / 255;
- b = b / 255;
-
- minRGB = min(r, min(g, b));
- maxRGB = max(r, max(g, b));
-
- if (minRGB == maxRGB) {
- v = minRGB;
-
- return {
- h: 0,
- s: 0,
- v: v * 100
- };
- }
-
- /*eslint no-nested-ternary:0 */
- d = (r == minRGB) ? g - b : ((b == minRGB) ? r - g : b - r);
- h = (r == minRGB) ? 3 : ((b == minRGB) ? 1 : 5);
- h = 60 * (h - d / (maxRGB - minRGB));
- s = (maxRGB - minRGB) / maxRGB;
- v = maxRGB;
-
- return {
- h: round(h),
- s: round(s * 100),
- v: round(v * 100)
- };
- }
-
- function hsvToRgb(hue, saturation, brightness) {
- var side, chroma, x, match;
-
- hue = (parseInt(hue, 10) || 0) % 360;
- saturation = parseInt(saturation, 10) / 100;
- brightness = parseInt(brightness, 10) / 100;
- saturation = max(0, min(saturation, 1));
- brightness = max(0, min(brightness, 1));
-
- if (saturation === 0) {
- r = g = b = round(255 * brightness);
- return;
- }
-
- side = hue / 60;
- chroma = brightness * saturation;
- x = chroma * (1 - Math.abs(side % 2 - 1));
- match = brightness - chroma;
-
- switch (Math.floor(side)) {
- case 0:
- r = chroma;
- g = x;
- b = 0;
- break;
-
- case 1:
- r = x;
- g = chroma;
- b = 0;
- break;
-
- case 2:
- r = 0;
- g = chroma;
- b = x;
- break;
-
- case 3:
- r = 0;
- g = x;
- b = chroma;
- break;
-
- case 4:
- r = x;
- g = 0;
- b = chroma;
- break;
-
- case 5:
- r = chroma;
- g = 0;
- b = x;
- break;
-
- default:
- r = g = b = 0;
- }
-
- r = round(255 * (r + match));
- g = round(255 * (g + match));
- b = round(255 * (b + match));
- }
-
- /**
- * Returns the hex string of the current color. For example: #ff00ff
- *
- * @method toHex
- * @return {String} Hex string of current color.
- */
- function toHex() {
- function hex(val) {
- val = parseInt(val, 10).toString(16);
-
- return val.length > 1 ? val : '0' + val;
- }
-
- return '#' + hex(r) + hex(g) + hex(b);
- }
-
- /**
- * Returns the r, g, b values of the color. Each channel has a range from 0-255.
- *
- * @method toRgb
- * @return {Object} Object with r, g, b fields.
- */
- function toRgb() {
- return {
- r: r,
- g: g,
- b: b
- };
- }
-
- /**
- * Returns the h, s, v values of the color. Ranges: h=0-360, s=0-100, v=0-100.
- *
- * @method toHsv
- * @return {Object} Object with h, s, v fields.
- */
- function toHsv() {
- return rgb2hsv(r, g, b);
- }
-
- /**
- * Parses the specified value and populates the color instance.
- *
- * Supported format examples:
- * * rbg(255,0,0)
- * * #ff0000
- * * #fff
- * * {r: 255, g: 0, b: 0}
- * * {h: 360, s: 100, v: 100}
- *
- * @method parse
- * @param {Object/String} value Color value to parse.
- * @return {tinymce.util.Color} Current color instance.
- */
- function parse(value) {
- var matches;
-
- if (typeof value == 'object') {
- if ("r" in value) {
- r = value.r;
- g = value.g;
- b = value.b;
- } else if ("v" in value) {
- hsvToRgb(value.h, value.s, value.v);
- }
- } else {
- if ((matches = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)[^\)]*\)/gi.exec(value))) {
- r = parseInt(matches[1], 10);
- g = parseInt(matches[2], 10);
- b = parseInt(matches[3], 10);
- } else if ((matches = /#([0-F]{2})([0-F]{2})([0-F]{2})/gi.exec(value))) {
- r = parseInt(matches[1], 16);
- g = parseInt(matches[2], 16);
- b = parseInt(matches[3], 16);
- } else if ((matches = /#([0-F])([0-F])([0-F])/gi.exec(value))) {
- r = parseInt(matches[1] + matches[1], 16);
- g = parseInt(matches[2] + matches[2], 16);
- b = parseInt(matches[3] + matches[3], 16);
- }
- }
-
- r = r < 0 ? 0 : (r > 255 ? 255 : r);
- g = g < 0 ? 0 : (g > 255 ? 255 : g);
- b = b < 0 ? 0 : (b > 255 ? 255 : b);
-
- return self;
- }
-
- if (value) {
- parse(value);
- }
-
- self.toRgb = toRgb;
- self.toHsv = toHsv;
- self.toHex = toHex;
- self.parse = parse;
- }
-
- return Color;
-});
-
-// Included from: js/tinymce/classes/ui/ColorPicker.js
-
-/**
</del><span class="cx" style="display: block; padding: 0 10px"> * ColorPicker.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -44050,203 +48978,204 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.ColorPicker
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Widget
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/ColorPicker", [
- "tinymce/ui/Widget",
- "tinymce/ui/DragHelper",
- "tinymce/ui/DomUtils",
- "tinymce/util/Color"
-], function(Widget, DragHelper, DomUtils, Color) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.ColorPicker',
+ [
+ "tinymce.core.ui.Widget",
+ "tinymce.core.ui.DragHelper",
+ "tinymce.core.ui.DomUtils",
+ "tinymce.core.util.Color"
+ ],
+ function (Widget, DragHelper, DomUtils, Color) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Widget.extend({
- Defaults: {
- classes: "widget colorpicker"
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Widget.extend({
+ Defaults: {
+ classes: "widget colorpicker"
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a new colorpicker instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- * @setting {String} color Initial color value.
- */
- init: function(settings) {
- this._super(settings);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a new colorpicker instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ * @setting {String} color Initial color value.
+ */
+ init: function (settings) {
+ this._super(settings);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- postRender: function() {
- var self = this, color = self.color(), hsv, hueRootElm, huePointElm, svRootElm, svPointElm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ postRender: function () {
+ var self = this, color = self.color(), hsv, hueRootElm, huePointElm, svRootElm, svPointElm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- hueRootElm = self.getEl('h');
- huePointElm = self.getEl('hp');
- svRootElm = self.getEl('sv');
- svPointElm = self.getEl('svp');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ hueRootElm = self.getEl('h');
+ huePointElm = self.getEl('hp');
+ svRootElm = self.getEl('sv');
+ svPointElm = self.getEl('svp');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getPos(elm, event) {
- var pos = DomUtils.getPos(elm), x, y;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getPos(elm, event) {
+ var pos = DomUtils.getPos(elm), x, y;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- x = event.pageX - pos.x;
- y = event.pageY - pos.y;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ x = event.pageX - pos.x;
+ y = event.pageY - pos.y;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- x = Math.max(0, Math.min(x / elm.clientWidth, 1));
- y = Math.max(0, Math.min(y / elm.clientHeight, 1));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ x = Math.max(0, Math.min(x / elm.clientWidth, 1));
+ y = Math.max(0, Math.min(y / elm.clientHeight, 1));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- x: x,
- y: y
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ x: x,
+ y: y
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function updateColor(hsv, hueUpdate) {
- var hue = (360 - hsv.h) / 360;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function updateColor(hsv, hueUpdate) {
+ var hue = (360 - hsv.h) / 360;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- DomUtils.css(huePointElm, {
- top: (hue * 100) + '%'
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ DomUtils.css(huePointElm, {
+ top: (hue * 100) + '%'
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!hueUpdate) {
- DomUtils.css(svPointElm, {
- left: hsv.s + '%',
- top: (100 - hsv.v) + '%'
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!hueUpdate) {
+ DomUtils.css(svPointElm, {
+ left: hsv.s + '%',
+ top: (100 - hsv.v) + '%'
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- svRootElm.style.background = new Color({s: 100, v: 100, h: hsv.h}).toHex();
- self.color().parse({s: hsv.s, v: hsv.v, h: hsv.h});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ svRootElm.style.background = new Color({ s: 100, v: 100, h: hsv.h }).toHex();
+ self.color().parse({ s: hsv.s, v: hsv.v, h: hsv.h });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function updateSaturationAndValue(e) {
- var pos;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function updateSaturationAndValue(e) {
+ var pos;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- pos = getPos(svRootElm, e);
- hsv.s = pos.x * 100;
- hsv.v = (1 - pos.y) * 100;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ pos = getPos(svRootElm, e);
+ hsv.s = pos.x * 100;
+ hsv.v = (1 - pos.y) * 100;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- updateColor(hsv);
- self.fire('change');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ updateColor(hsv);
+ self.fire('change');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function updateHue(e) {
- var pos;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function updateHue(e) {
+ var pos;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- pos = getPos(hueRootElm, e);
- hsv = color.toHsv();
- hsv.h = (1 - pos.y) * 360;
- updateColor(hsv, true);
- self.fire('change');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ pos = getPos(hueRootElm, e);
+ hsv = color.toHsv();
+ hsv.h = (1 - pos.y) * 360;
+ updateColor(hsv, true);
+ self.fire('change');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._repaint = function() {
- hsv = color.toHsv();
- updateColor(hsv);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._repaint = function () {
+ hsv = color.toHsv();
+ updateColor(hsv);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._svdraghelper = new DragHelper(self._id + '-sv', {
- start: updateSaturationAndValue,
- drag: updateSaturationAndValue
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._svdraghelper = new DragHelper(self._id + '-sv', {
+ start: updateSaturationAndValue,
+ drag: updateSaturationAndValue
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._hdraghelper = new DragHelper(self._id + '-h', {
- start: updateHue,
- drag: updateHue
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._hdraghelper = new DragHelper(self._id + '-h', {
+ start: updateHue,
+ drag: updateHue
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._repaint();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._repaint();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rgb: function() {
- return this.color().toRgb();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rgb: function () {
+ return this.color().toRgb();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- value: function(value) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ value: function (value) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (arguments.length) {
- self.color().parse(value);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (arguments.length) {
+ self.color().parse(value);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self._rendered) {
- self._repaint();
- }
- } else {
- return self.color().toHex();
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self._rendered) {
+ self._repaint();
+ }
+ } else {
+ return self.color().toHex();
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- color: function() {
- if (!this._color) {
- this._color = new Color();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ color: function () {
+ if (!this._color) {
+ this._color = new Color();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this._color;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this._color;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this, id = self._id, prefix = self.classPrefix, hueHtml;
- var stops = '#ff0000,#ff0080,#ff00ff,#8000ff,#0000ff,#0080ff,#00ffff,#00ff80,#00ff00,#80ff00,#ffff00,#ff8000,#ff0000';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this, id = self._id, prefix = self.classPrefix, hueHtml;
+ var stops = '#ff0000,#ff0080,#ff00ff,#8000ff,#0000ff,#0080ff,#00ffff,#00ff80,#00ff00,#80ff00,#ffff00,#ff8000,#ff0000';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getOldIeFallbackHtml() {
- var i, l, html = '', gradientPrefix, stopsList;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getOldIeFallbackHtml() {
+ var i, l, html = '', gradientPrefix, stopsList;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- gradientPrefix = 'filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr=';
- stopsList = stops.split(',');
- for (i = 0, l = stopsList.length - 1; i < l; i++) {
- html += (
- '<div class="' + prefix + 'colorpicker-h-chunk" style="' +
- 'height:' + (100 / l) + '%;' +
- gradientPrefix + stopsList[i] + ',endColorstr=' + stopsList[i + 1] + ');' +
- '-ms-' + gradientPrefix + stopsList[i] + ',endColorstr=' + stopsList[i + 1] + ')' +
- '"></div>'
- );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ gradientPrefix = 'filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr=';
+ stopsList = stops.split(',');
+ for (i = 0, l = stopsList.length - 1; i < l; i++) {
+ html += (
+ '<div class="' + prefix + 'colorpicker-h-chunk" style="' +
+ 'height:' + (100 / l) + '%;' +
+ gradientPrefix + stopsList[i] + ',endColorstr=' + stopsList[i + 1] + ');' +
+ '-ms-' + gradientPrefix + stopsList[i] + ',endColorstr=' + stopsList[i + 1] + ')' +
+ '"></div>'
+ );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return html;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return html;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var gradientCssText = (
- 'background: -ms-linear-gradient(top,' + stops + ');' +
- 'background: linear-gradient(to bottom,' + stops + ');'
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var gradientCssText = (
+ 'background: -ms-linear-gradient(top,' + stops + ');' +
+ 'background: linear-gradient(to bottom,' + stops + ');'
+ );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- hueHtml = (
- '<div id="' + id + '-h" class="' + prefix + 'colorpicker-h" style="' + gradientCssText + '">' +
- getOldIeFallbackHtml() +
- '<div id="' + id + '-hp" class="' + prefix + 'colorpicker-h-marker"></div>' +
- '</div>'
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ hueHtml = (
+ '<div id="' + id + '-h" class="' + prefix + 'colorpicker-h" style="' + gradientCssText + '">' +
+ getOldIeFallbackHtml() +
+ '<div id="' + id + '-hp" class="' + prefix + 'colorpicker-h-marker"></div>' +
+ '</div>'
+ );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<div id="' + id + '" class="' + self.classes + '">' +
- '<div id="' + id + '-sv" class="' + prefix + 'colorpicker-sv">' +
- '<div class="' + prefix + 'colorpicker-overlay1">' +
- '<div class="' + prefix + 'colorpicker-overlay2">' +
- '<div id="' + id + '-svp" class="' + prefix + 'colorpicker-selector1">' +
- '<div class="' + prefix + 'colorpicker-selector2"></div>' +
- '</div>' +
- '</div>' +
- '</div>' +
- '</div>' +
- hueHtml +
- '</div>'
- );
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/Path.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<div id="' + id + '" class="' + self.classes + '">' +
+ '<div id="' + id + '-sv" class="' + prefix + 'colorpicker-sv">' +
+ '<div class="' + prefix + 'colorpicker-overlay1">' +
+ '<div class="' + prefix + 'colorpicker-overlay2">' +
+ '<div id="' + id + '-svp" class="' + prefix + 'colorpicker-selector1">' +
+ '<div class="' + prefix + 'colorpicker-selector2"></div>' +
+ '</div>' +
+ '</div>' +
+ '</div>' +
+ '</div>' +
+ hueHtml +
+ '</div>'
+ );
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Path.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -44259,124 +49188,126 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.Path
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Widget
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Path", [
- "tinymce/ui/Widget"
-], function(Widget) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Path',
+ [
+ "tinymce.core.ui.Widget"
+ ],
+ function (Widget) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Widget.extend({
- /**
- * Constructs a instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- * @setting {String} delimiter Delimiter to display between row in path.
- */
- init: function(settings) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Widget.extend({
+ /**
+ * Constructs a instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ * @setting {String} delimiter Delimiter to display between row in path.
+ */
+ init: function (settings) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!settings.delimiter) {
- settings.delimiter = '\u00BB';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!settings.delimiter) {
+ settings.delimiter = '\u00BB';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super(settings);
- self.classes.add('path');
- self.canFocus = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super(settings);
+ self.classes.add('path');
+ self.canFocus = true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('click', function(e) {
- var index, target = e.target;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('click', function (e) {
+ var index, target = e.target;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ((index = target.getAttribute('data-index'))) {
- self.fire('select', {value: self.row()[index], index: index});
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((index = target.getAttribute('data-index'))) {
+ self.fire('select', { value: self.row()[index], index: index });
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.row(self.settings.row);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.row(self.settings.row);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Focuses the current control.
- *
- * @method focus
- * @return {tinymce.ui.Control} Current control instance.
- */
- focus: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Focuses the current control.
+ *
+ * @method focus
+ * @return {tinymce.ui.Control} Current control instance.
+ */
+ focus: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.getEl().firstChild.focus();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.getEl().firstChild.focus();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets/gets the data to be used for the path.
- *
- * @method row
- * @param {Array} row Array with row name is rendered to path.
- */
- row: function(row) {
- if (!arguments.length) {
- return this.state.get('row');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets/gets the data to be used for the path.
+ *
+ * @method row
+ * @param {Array} row Array with row name is rendered to path.
+ */
+ row: function (row) {
+ if (!arguments.length) {
+ return this.state.get('row');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.state.set('row', row);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.state.set('row', row);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<div id="' + self._id + '" class="' + self.classes + '">' +
- self._getDataPathHtml(self.state.get('row')) +
- '</div>'
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<div id="' + self._id + '" class="' + self.classes + '">' +
+ self._getDataPathHtml(self.state.get('row')) +
+ '</div>'
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bindStates: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bindStates: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:row', function(e) {
- self.innerHtml(self._getDataPathHtml(e.value));
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:row', function (e) {
+ self.innerHtml(self._getDataPathHtml(e.value));
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- _getDataPathHtml: function(data) {
- var self = this, parts = data || [], i, l, html = '', prefix = self.classPrefix;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ _getDataPathHtml: function (data) {
+ var self = this, parts = data || [], i, l, html = '', prefix = self.classPrefix;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0, l = parts.length; i < l; i++) {
- html += (
- (i > 0 ? '<div class="' + prefix + 'divider" aria-hidden="true"> ' + self.settings.delimiter + ' </div>' : '') +
- '<div role="button" class="' + prefix + 'path-item' + (i == l - 1 ? ' ' + prefix + 'last' : '') + '" data-index="' +
- i + '" tabindex="-1" id="' + self._id + '-' + i + '" aria-level="' + (i + 1) + '">' + parts[i].name + '</div>'
- );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0, l = parts.length; i < l; i++) {
+ html += (
+ (i > 0 ? '<div class="' + prefix + 'divider" aria-hidden="true"> ' + self.settings.delimiter + ' </div>' : '') +
+ '<div role="button" class="' + prefix + 'path-item' + (i == l - 1 ? ' ' + prefix + 'last' : '') + '" data-index="' +
+ i + '" tabindex="-1" id="' + self._id + '-' + i + '" aria-level="' + (i + 1) + '">' + parts[i].name + '</div>'
+ );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!html) {
- html = '<div class="' + prefix + 'path-item">\u00a0</div>';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!html) {
+ html = '<div class="' + prefix + 'path-item">\u00a0</div>';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return html;
- }
- });
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return html;
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/ElementPath.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * ElementPath.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -44388,76 +49319,77 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.ElementPath
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Path
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/ElementPath", [
- "tinymce/ui/Path"
-], function(Path) {
- return Path.extend({
- /**
- * Post render method. Called after the control has been rendered to the target.
- *
- * @method postRender
- * @return {tinymce.ui.ElementPath} Current combobox instance.
- */
- postRender: function() {
- var self = this, editor = self.settings.editor;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.ElementPath',
+ [
+ "tinymce.core.ui.Path"
+ ],
+ function (Path) {
+ return Path.extend({
+ /**
+ * Post render method. Called after the control has been rendered to the target.
+ *
+ * @method postRender
+ * @return {tinymce.ui.ElementPath} Current combobox instance.
+ */
+ postRender: function () {
+ var self = this, editor = self.settings.editor;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function isHidden(elm) {
- if (elm.nodeType === 1) {
- if (elm.nodeName == "BR" || !!elm.getAttribute('data-mce-bogus')) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function isHidden(elm) {
+ if (elm.nodeType === 1) {
+ if (elm.nodeName == "BR" || !!elm.getAttribute('data-mce-bogus')) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elm.getAttribute('data-mce-type') === 'bookmark') {
- return true;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (elm.getAttribute('data-mce-type') === 'bookmark') {
+ return true;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.settings.elementpath !== false) {
- self.on('select', function(e) {
- editor.focus();
- editor.selection.select(this.row()[e.index].element);
- editor.nodeChanged();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.settings.elementpath !== false) {
+ self.on('select', function (e) {
+ editor.focus();
+ editor.selection.select(this.row()[e.index].element);
+ editor.nodeChanged();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('nodeChange', function(e) {
- var outParents = [], parents = e.parents, i = parents.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('nodeChange', function (e) {
+ var outParents = [], parents = e.parents, i = parents.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- if (parents[i].nodeType == 1 && !isHidden(parents[i])) {
- var args = editor.fire('ResolveName', {
- name: parents[i].nodeName.toLowerCase(),
- target: parents[i]
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ if (parents[i].nodeType == 1 && !isHidden(parents[i])) {
+ var args = editor.fire('ResolveName', {
+ name: parents[i].nodeName.toLowerCase(),
+ target: parents[i]
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!args.isDefaultPrevented()) {
- outParents.push({name: args.name, element: parents[i]});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!args.isDefaultPrevented()) {
+ outParents.push({ name: args.name, element: parents[i] });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (args.isPropagationStopped()) {
- break;
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (args.isPropagationStopped()) {
+ break;
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.row(outParents);
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.row(outParents);
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/FormItem.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * FormItem.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -44471,52 +49403,53 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Container
</span><span class="cx" style="display: block; padding: 0 10px"> * @setting {String} label Label to display for the form item.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/FormItem", [
- "tinymce/ui/Container"
-], function(Container) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.FormItem',
+ [
+ "tinymce.core.ui.Container"
+ ],
+ function (Container) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Container.extend({
- Defaults: {
- layout: 'flex',
- align: 'center',
- defaults: {
- flex: 1
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Container.extend({
+ Defaults: {
+ layout: 'flex',
+ align: 'center',
+ defaults: {
+ flex: 1
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this, layout = self._layout, prefix = self.classPrefix;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this, layout = self._layout, prefix = self.classPrefix;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.classes.add('formitem');
- layout.preRender(self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.classes.add('formitem');
+ layout.preRender(self);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<div id="' + self._id + '" class="' + self.classes + '" hidefocus="1" tabindex="-1">' +
- (self.settings.title ? ('<div id="' + self._id + '-title" class="' + prefix + 'title">' +
- self.settings.title + '</div>') : '') +
- '<div id="' + self._id + '-body" class="' + self.bodyClasses + '">' +
- (self.settings.html || '') + layout.renderHtml(self) +
- '</div>' +
- '</div>'
- );
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/Form.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<div id="' + self._id + '" class="' + self.classes + '" hidefocus="1" tabindex="-1">' +
+ (self.settings.title ? ('<div id="' + self._id + '-title" class="' + prefix + 'title">' +
+ self.settings.title + '</div>') : '') +
+ '<div id="' + self._id + '-body" class="' + self.bodyClasses + '">' +
+ (self.settings.html || '') + layout.renderHtml(self) +
+ '</div>' +
+ '</div>'
+ );
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Form.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -44539,144 +49472,145 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.Form
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Container
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Form", [
- "tinymce/ui/Container",
- "tinymce/ui/FormItem",
- "tinymce/util/Tools"
-], function(Container, FormItem, Tools) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Form',
+ [
+ "tinymce.core.ui.Container",
+ "tinymce.core.ui.FormItem",
+ "tinymce.core.util.Tools"
+ ],
+ function (Container, FormItem, Tools) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Container.extend({
- Defaults: {
- containerCls: 'form',
- layout: 'flex',
- direction: 'column',
- align: 'stretch',
- flex: 1,
- padding: 20,
- labelGap: 30,
- spacing: 10,
- callbacks: {
- submit: function() {
- this.submit();
- }
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Container.extend({
+ Defaults: {
+ containerCls: 'form',
+ layout: 'flex',
+ direction: 'column',
+ align: 'stretch',
+ flex: 1,
+ padding: 20,
+ labelGap: 30,
+ spacing: 10,
+ callbacks: {
+ submit: function () {
+ this.submit();
+ }
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * This method gets invoked before the control is rendered.
- *
- * @method preRender
- */
- preRender: function() {
- var self = this, items = self.items();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * This method gets invoked before the control is rendered.
+ *
+ * @method preRender
+ */
+ preRender: function () {
+ var self = this, items = self.items();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.settings.formItemDefaults) {
- self.settings.formItemDefaults = {
- layout: 'flex',
- autoResize: "overflow",
- defaults: {flex: 1}
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.settings.formItemDefaults) {
+ self.settings.formItemDefaults = {
+ layout: 'flex',
+ autoResize: "overflow",
+ defaults: { flex: 1 }
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Wrap any labeled items in FormItems
- items.each(function(ctrl) {
- var formItem, label = ctrl.settings.label;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Wrap any labeled items in FormItems
+ items.each(function (ctrl) {
+ var formItem, label = ctrl.settings.label;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (label) {
- formItem = new FormItem(Tools.extend({
- items: {
- type: 'label',
- id: ctrl._id + '-l',
- text: label,
- flex: 0,
- forId: ctrl._id,
- disabled: ctrl.disabled()
- }
- }, self.settings.formItemDefaults));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (label) {
+ formItem = new FormItem(Tools.extend({
+ items: {
+ type: 'label',
+ id: ctrl._id + '-l',
+ text: label,
+ flex: 0,
+ forId: ctrl._id,
+ disabled: ctrl.disabled()
+ }
+ }, self.settings.formItemDefaults));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- formItem.type = 'formitem';
- ctrl.aria('labelledby', ctrl._id + '-l');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ formItem.type = 'formitem';
+ ctrl.aria('labelledby', ctrl._id + '-l');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof ctrl.settings.flex == "undefined") {
- ctrl.settings.flex = 1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof ctrl.settings.flex == "undefined") {
+ ctrl.settings.flex = 1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.replace(ctrl, formItem);
- formItem.add(ctrl);
- }
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.replace(ctrl, formItem);
+ formItem.add(ctrl);
+ }
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Fires a submit event with the serialized form.
- *
- * @method submit
- * @return {Object} Event arguments object.
- */
- submit: function() {
- return this.fire('submit', {data: this.toJSON()});
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Fires a submit event with the serialized form.
+ *
+ * @method submit
+ * @return {Object} Event arguments object.
+ */
+ submit: function () {
+ return this.fire('submit', { data: this.toJSON() });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Post render method. Called after the control has been rendered to the target.
- *
- * @method postRender
- * @return {tinymce.ui.ComboBox} Current combobox instance.
- */
- postRender: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Post render method. Called after the control has been rendered to the target.
+ *
+ * @method postRender
+ * @return {tinymce.ui.ComboBox} Current combobox instance.
+ */
+ postRender: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super();
- self.fromJSON(self.settings.data);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super();
+ self.fromJSON(self.settings.data);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bindStates: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bindStates: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function recalcLabels() {
- var maxLabelWidth = 0, labels = [], i, labelGap, items;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function recalcLabels() {
+ var maxLabelWidth = 0, labels = [], i, labelGap, items;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.settings.labelGapCalc === false) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.settings.labelGapCalc === false) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.settings.labelGapCalc == "children") {
- items = self.find('formitem');
- } else {
- items = self.items();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.settings.labelGapCalc == "children") {
+ items = self.find('formitem');
+ } else {
+ items = self.items();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- items.filter('formitem').each(function(item) {
- var labelCtrl = item.items()[0], labelWidth = labelCtrl.getEl().clientWidth;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ items.filter('formitem').each(function (item) {
+ var labelCtrl = item.items()[0], labelWidth = labelCtrl.getEl().clientWidth;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- maxLabelWidth = labelWidth > maxLabelWidth ? labelWidth : maxLabelWidth;
- labels.push(labelCtrl);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ maxLabelWidth = labelWidth > maxLabelWidth ? labelWidth : maxLabelWidth;
+ labels.push(labelCtrl);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- labelGap = self.settings.labelGap || 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ labelGap = self.settings.labelGap || 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- i = labels.length;
- while (i--) {
- labels[i].settings.minWidth = maxLabelWidth + labelGap;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ i = labels.length;
+ while (i--) {
+ labels[i].settings.minWidth = maxLabelWidth + labelGap;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('show', recalcLabels);
- recalcLabels();
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/FieldSet.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('show', recalcLabels);
+ recalcLabels();
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * FieldSet.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -44689,56 +49623,57 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.FieldSet
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Form
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/FieldSet", [
- "tinymce/ui/Form"
-], function(Form) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.FieldSet',
+ [
+ "tinymce.core.ui.Form"
+ ],
+ function (Form) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Form.extend({
- Defaults: {
- containerCls: 'fieldset',
- layout: 'flex',
- direction: 'column',
- align: 'stretch',
- flex: 1,
- padding: "25 15 5 15",
- labelGap: 30,
- spacing: 10,
- border: 1
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Form.extend({
+ Defaults: {
+ containerCls: 'fieldset',
+ layout: 'flex',
+ direction: 'column',
+ align: 'stretch',
+ flex: 1,
+ padding: "25 15 5 15",
+ labelGap: 30,
+ spacing: 10,
+ border: 1
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this, layout = self._layout, prefix = self.classPrefix;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this, layout = self._layout, prefix = self.classPrefix;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.preRender();
- layout.preRender(self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.preRender();
+ layout.preRender(self);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<fieldset id="' + self._id + '" class="' + self.classes + '" hidefocus="1" tabindex="-1">' +
- (self.settings.title ? ('<legend id="' + self._id + '-title" class="' + prefix + 'fieldset-title">' +
- self.settings.title + '</legend>') : '') +
- '<div id="' + self._id + '-body" class="' + self.bodyClasses + '">' +
- (self.settings.html || '') + layout.renderHtml(self) +
- '</div>' +
- '</fieldset>'
- );
- }
- });
-});
-
-// Included from: js/tinymce/classes/content/LinkTargets.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<fieldset id="' + self._id + '" class="' + self.classes + '" hidefocus="1" tabindex="-1">' +
+ (self.settings.title ? ('<legend id="' + self._id + '-title" class="' + prefix + 'fieldset-title">' +
+ self.settings.title + '</legend>') : '') +
+ '<div id="' + self._id + '-body" class="' + self.bodyClasses + '">' +
+ (self.settings.html || '') + layout.renderHtml(self) +
+ '</div>' +
+ '</fieldset>'
+ );
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * LinkTargets.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -44750,442 +49685,441 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.content.LinkTargets
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define('tinymce/content/LinkTargets', [
- 'tinymce/dom/DOMUtils',
- 'tinymce/util/Fun',
- 'tinymce/util/Arr',
- 'tinymce/util/Uuid',
- 'tinymce/util/Tools',
- 'tinymce/dom/NodeType'
-], function(
- DOMUtils,
- Fun,
- Arr,
- Uuid,
- Tools,
- NodeType
-) {
- var trim = Tools.trim;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.content.LinkTargets',
+ [
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.core.dom.NodeType',
+ 'tinymce.core.util.Arr',
+ 'tinymce.core.util.Fun',
+ 'tinymce.core.util.Tools',
+ 'tinymce.core.util.Uuid'
+ ],
+ function (DOMUtils, NodeType, Arr, Fun, Tools, Uuid) {
+ var trim = Tools.trim;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var create = function (type, title, url, level, attach) {
- return {
- type: type,
- title: title,
- url: url,
- level: level,
- attach: attach
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var create = function (type, title, url, level, attach) {
+ return {
+ type: type,
+ title: title,
+ url: url,
+ level: level,
+ attach: attach
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isChildOfContentEditableTrue = function (node) {
- while ((node = node.parentNode)) {
- var value = node.contentEditable;
- if (value && value !== 'inherit') {
- return NodeType.isContentEditableTrue(node);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isChildOfContentEditableTrue = function (node) {
+ while ((node = node.parentNode)) {
+ var value = node.contentEditable;
+ if (value && value !== 'inherit') {
+ return NodeType.isContentEditableTrue(node);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var select = function (selector, root) {
- return DOMUtils.DOM.select(selector, root);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var select = function (selector, root) {
+ return DOMUtils.DOM.select(selector, root);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getElementText = function (elm) {
- return elm.innerText || elm.textContent;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getElementText = function (elm) {
+ return elm.innerText || elm.textContent;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getOrGenerateId = function (elm) {
- return elm.id ? elm.id : Uuid.uuid('h');
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getOrGenerateId = function (elm) {
+ return elm.id ? elm.id : Uuid.uuid('h');
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isAnchor = function (elm) {
- return elm && elm.nodeName === 'A' && (elm.id || elm.name);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isAnchor = function (elm) {
+ return elm && elm.nodeName === 'A' && (elm.id || elm.name);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isValidAnchor = function (elm) {
- return isAnchor(elm) && isEditable(elm);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isValidAnchor = function (elm) {
+ return isAnchor(elm) && isEditable(elm);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isHeader = function (elm) {
- return elm && /^(H[1-6])$/.test(elm.nodeName);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isHeader = function (elm) {
+ return elm && /^(H[1-6])$/.test(elm.nodeName);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isEditable = function (elm) {
- return isChildOfContentEditableTrue(elm) && !NodeType.isContentEditableFalse(elm);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isEditable = function (elm) {
+ return isChildOfContentEditableTrue(elm) && !NodeType.isContentEditableFalse(elm);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isValidHeader = function (elm) {
- return isHeader(elm) && isEditable(elm);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isValidHeader = function (elm) {
+ return isHeader(elm) && isEditable(elm);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getLevel = function (elm) {
- return isHeader(elm) ? parseInt(elm.nodeName.substr(1), 10) : 0;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getLevel = function (elm) {
+ return isHeader(elm) ? parseInt(elm.nodeName.substr(1), 10) : 0;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var headerTarget = function (elm) {
- var headerId = getOrGenerateId(elm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var headerTarget = function (elm) {
+ var headerId = getOrGenerateId(elm);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var attach = function () {
- elm.id = headerId;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var attach = function () {
+ elm.id = headerId;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return create('header', getElementText(elm), '#' + headerId, getLevel(elm), attach);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return create('header', getElementText(elm), '#' + headerId, getLevel(elm), attach);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var anchorTarget = function (elm) {
- var anchorId = elm.id || elm.name;
- var anchorText = getElementText(elm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var anchorTarget = function (elm) {
+ var anchorId = elm.id || elm.name;
+ var anchorText = getElementText(elm);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return create('anchor', anchorText ? anchorText : '#' + anchorId, '#' + anchorId, 0, Fun.noop);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return create('anchor', anchorText ? anchorText : '#' + anchorId, '#' + anchorId, 0, Fun.noop);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getHeaderTargets = function (elms) {
- return Arr.map(Arr.filter(elms, isValidHeader), headerTarget);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getHeaderTargets = function (elms) {
+ return Arr.map(Arr.filter(elms, isValidHeader), headerTarget);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getAnchorTargets = function (elms) {
- return Arr.map(Arr.filter(elms, isValidAnchor), anchorTarget);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getAnchorTargets = function (elms) {
+ return Arr.map(Arr.filter(elms, isValidAnchor), anchorTarget);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getTargetElements = function (elm) {
- var elms = select('h1,h2,h3,h4,h5,h6,a:not([href])', elm);
- return elms;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getTargetElements = function (elm) {
+ var elms = select('h1,h2,h3,h4,h5,h6,a:not([href])', elm);
+ return elms;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var hasTitle = function (target) {
- return trim(target.title).length > 0;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var hasTitle = function (target) {
+ return trim(target.title).length > 0;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var find = function (elm) {
- var elms = getTargetElements(elm);
- return Arr.filter(getHeaderTargets(elms).concat(getAnchorTargets(elms)), hasTitle);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var find = function (elm) {
+ var elms = getTargetElements(elm);
+ return Arr.filter(getHeaderTargets(elms).concat(getAnchorTargets(elms)), hasTitle);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- find: find
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ find: find
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/FilePicker.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * FilePicker.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/*global tinymce:true */
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * This class creates a file picker control.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.FilePicker
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.ComboBox
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/FilePicker", [
- "tinymce/ui/ComboBox",
- "tinymce/util/Tools",
- "tinymce/util/Arr",
- "tinymce/util/Fun",
- "tinymce/util/VK",
- "tinymce/content/LinkTargets"
-], function(ComboBox, Tools, Arr, Fun, VK, LinkTargets) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.FilePicker',
+ [
+ 'global!window',
+ 'tinymce.core.content.LinkTargets',
+ 'tinymce.core.EditorManager',
+ 'tinymce.core.ui.ComboBox',
+ 'tinymce.core.util.Arr',
+ 'tinymce.core.util.Fun',
+ 'tinymce.core.util.Tools'
+ ],
+ function (window, LinkTargets, EditorManager, ComboBox, Arr, Fun, Tools) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var history = {};
- var HISTORY_LENGTH = 5;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getActiveEditor = function () {
+ return window.tinymce ? window.tinymce.activeEditor : EditorManager.activeEditor;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var toMenuItem = function (target) {
- return {
- title: target.title,
- value: {
- title: {raw: target.title},
- url: target.url,
- attach: target.attach
- }
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var history = {};
+ var HISTORY_LENGTH = 5;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var toMenuItems = function (targets) {
- return Tools.map(targets, toMenuItem);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var toMenuItem = function (target) {
+ return {
+ title: target.title,
+ value: {
+ title: { raw: target.title },
+ url: target.url,
+ attach: target.attach
+ }
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var staticMenuItem = function (title, url) {
- return {
- title: title,
- value: {
- title: title,
- url: url,
- attach: Fun.noop
- }
- };
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var toMenuItems = function (targets) {
+ return Tools.map(targets, toMenuItem);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var isUniqueUrl = function (url, targets) {
- var foundTarget = Arr.find(targets, function (target) {
- return target.url === url;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var staticMenuItem = function (title, url) {
+ return {
+ title: title,
+ value: {
+ title: title,
+ url: url,
+ attach: Fun.noop
+ }
+ };
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return !foundTarget;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var isUniqueUrl = function (url, targets) {
+ var foundTarget = Arr.find(targets, function (target) {
+ return target.url === url;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getSetting = function (editorSettings, name, defaultValue) {
- var value = name in editorSettings ? editorSettings[name] : defaultValue;
- return value === false ? null : value;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return !foundTarget;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var createMenuItems = function (term, targets, fileType, editorSettings) {
- var separator = {title: '-'};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getSetting = function (editorSettings, name, defaultValue) {
+ var value = name in editorSettings ? editorSettings[name] : defaultValue;
+ return value === false ? null : value;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var fromHistoryMenuItems = function (history) {
- var uniqueHistory = Arr.filter(history[fileType], function (url) {
- return isUniqueUrl(url, targets);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createMenuItems = function (term, targets, fileType, editorSettings) {
+ var separator = { title: '-' };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Tools.map(uniqueHistory, function (url) {
- return {
- title: url,
- value: {
- title: url,
- url: url,
- attach: Fun.noop
- }
- };
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var fromHistoryMenuItems = function (history) {
+ var uniqueHistory = Arr.filter(history[fileType], function (url) {
+ return isUniqueUrl(url, targets);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var fromMenuItems = function (type) {
- var filteredTargets = Arr.filter(targets, function (target) {
- return target.type == type;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Tools.map(uniqueHistory, function (url) {
+ return {
+ title: url,
+ value: {
+ title: url,
+ url: url,
+ attach: Fun.noop
+ }
+ };
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return toMenuItems(filteredTargets);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var fromMenuItems = function (type) {
+ var filteredTargets = Arr.filter(targets, function (target) {
+ return target.type == type;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var anchorMenuItems = function () {
- var anchorMenuItems = fromMenuItems('anchor');
- var topAnchor = getSetting(editorSettings, 'anchor_top', '#top');
- var bottomAchor = getSetting(editorSettings, 'anchor_bottom', '#bottom');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return toMenuItems(filteredTargets);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (topAnchor !== null) {
- anchorMenuItems.unshift(staticMenuItem('<top>', topAnchor));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var anchorMenuItems = function () {
+ var anchorMenuItems = fromMenuItems('anchor');
+ var topAnchor = getSetting(editorSettings, 'anchor_top', '#top');
+ var bottomAchor = getSetting(editorSettings, 'anchor_bottom', '#bottom');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (bottomAchor !== null) {
- anchorMenuItems.push(staticMenuItem('<bottom>', bottomAchor));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (topAnchor !== null) {
+ anchorMenuItems.unshift(staticMenuItem('<top>', topAnchor));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return anchorMenuItems;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (bottomAchor !== null) {
+ anchorMenuItems.push(staticMenuItem('<bottom>', bottomAchor));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var join = function (items) {
- return Arr.reduce(items, function (a, b) {
- var bothEmpty = a.length === 0 || b.length === 0;
- return bothEmpty ? a.concat(b) : a.concat(separator, b);
- }, []);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return anchorMenuItems;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editorSettings.typeahead_urls === false) {
- return [];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var join = function (items) {
+ return Arr.reduce(items, function (a, b) {
+ var bothEmpty = a.length === 0 || b.length === 0;
+ return bothEmpty ? a.concat(b) : a.concat(separator, b);
+ }, []);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return fileType === 'file' ? join([
- filterByQuery(term, fromHistoryMenuItems(history)),
- filterByQuery(term, fromMenuItems('header')),
- filterByQuery(term, anchorMenuItems())
- ]) : filterByQuery(term, fromHistoryMenuItems(history));
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editorSettings.typeahead_urls === false) {
+ return [];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var addToHistory = function (url, fileType) {
- var items = history[fileType];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return fileType === 'file' ? join([
+ filterByQuery(term, fromHistoryMenuItems(history)),
+ filterByQuery(term, fromMenuItems('header')),
+ filterByQuery(term, anchorMenuItems())
+ ]) : filterByQuery(term, fromHistoryMenuItems(history));
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!/^https?/.test(url)) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var addToHistory = function (url, fileType) {
+ var items = history[fileType];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (items) {
- if (Arr.indexOf(items, url) === -1) {
- history[fileType] = items.slice(0, HISTORY_LENGTH).concat(url);
- }
- } else {
- history[fileType] = [url];
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!/^https?/.test(url)) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var filterByQuery = function (term, menuItems) {
- var lowerCaseTerm = term.toLowerCase();
- var result = Tools.grep(menuItems, function (item) {
- return item.title.toLowerCase().indexOf(lowerCaseTerm) !== -1;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (items) {
+ if (Arr.indexOf(items, url) === -1) {
+ history[fileType] = items.slice(0, HISTORY_LENGTH).concat(url);
+ }
+ } else {
+ history[fileType] = [url];
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return result.length === 1 && result[0].title === term ? [] : result;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var filterByQuery = function (term, menuItems) {
+ var lowerCaseTerm = term.toLowerCase();
+ var result = Tools.grep(menuItems, function (item) {
+ return item.title.toLowerCase().indexOf(lowerCaseTerm) !== -1;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getTitle = function (linkDetails) {
- var title = linkDetails.title;
- return title.raw ? title.raw : title;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return result.length === 1 && result[0].title === term ? [] : result;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var setupAutoCompleteHandler = function (ctrl, editorSettings, bodyElm, fileType) {
- var autocomplete = function (term) {
- var linkTargets = LinkTargets.find(bodyElm);
- var menuItems = createMenuItems(term, linkTargets, fileType, editorSettings);
- ctrl.showAutoComplete(menuItems, term);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getTitle = function (linkDetails) {
+ var title = linkDetails.title;
+ return title.raw ? title.raw : title;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ctrl.on('autocomplete', function () {
- autocomplete(ctrl.value());
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var setupAutoCompleteHandler = function (ctrl, editorSettings, bodyElm, fileType) {
+ var autocomplete = function (term) {
+ var linkTargets = LinkTargets.find(bodyElm);
+ var menuItems = createMenuItems(term, linkTargets, fileType, editorSettings);
+ ctrl.showAutoComplete(menuItems, term);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ctrl.on('selectitem', function (e) {
- var linkDetails = e.value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ctrl.on('autocomplete', function () {
+ autocomplete(ctrl.value());
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ctrl.value(linkDetails.url);
- var title = getTitle(linkDetails);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ctrl.on('selectitem', function (e) {
+ var linkDetails = e.value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (fileType === 'image') {
- ctrl.fire('change', {meta: {alt: title, attach: linkDetails.attach}});
- } else {
- ctrl.fire('change', {meta: {text: title, attach: linkDetails.attach}});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ctrl.value(linkDetails.url);
+ var title = getTitle(linkDetails);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ctrl.focus();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (fileType === 'image') {
+ ctrl.fire('change', { meta: { alt: title, attach: linkDetails.attach } });
+ } else {
+ ctrl.fire('change', { meta: { text: title, attach: linkDetails.attach } });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ctrl.on('click', function (e) {
- if (ctrl.value().length === 0 && e.target.nodeName === 'INPUT') {
- autocomplete('');
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ctrl.focus();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ctrl.on('PostRender', function () {
- ctrl.getRoot().on('submit', function (e) {
- if (!e.isDefaultPrevented()) {
- addToHistory(ctrl.value(), fileType);
- }
- });
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ctrl.on('click', function (e) {
+ if (ctrl.value().length === 0 && e.target.nodeName === 'INPUT') {
+ autocomplete('');
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var statusToUiState = function (result) {
- var status = result.status, message = result.message;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ctrl.on('PostRender', function () {
+ ctrl.getRoot().on('submit', function (e) {
+ if (!e.isDefaultPrevented()) {
+ addToHistory(ctrl.value(), fileType);
+ }
+ });
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (status === 'valid') {
- return {status: 'ok', message: message};
- } else if (status === 'unknown') {
- return {status: 'warn', message: message};
- } else if (status === 'invalid') {
- return {status: 'warn', message: message};
- } else {
- return {status: 'none', message: ''};
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var statusToUiState = function (result) {
+ var status = result.status, message = result.message;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var setupLinkValidatorHandler = function (ctrl, editorSettings, fileType) {
- var validatorHandler = editorSettings.filepicker_validator_handler;
- if (validatorHandler) {
- var validateUrl = function (url) {
- if (url.length === 0) {
- ctrl.statusLevel('none');
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (status === 'valid') {
+ return { status: 'ok', message: message };
+ } else if (status === 'unknown') {
+ return { status: 'warn', message: message };
+ } else if (status === 'invalid') {
+ return { status: 'warn', message: message };
+ } else {
+ return { status: 'none', message: '' };
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- validatorHandler({
- url: url,
- type: fileType
- }, function (result) {
- var uiState = statusToUiState(result);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var setupLinkValidatorHandler = function (ctrl, editorSettings, fileType) {
+ var validatorHandler = editorSettings.filepicker_validator_handler;
+ if (validatorHandler) {
+ var validateUrl = function (url) {
+ if (url.length === 0) {
+ ctrl.statusLevel('none');
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ctrl.statusMessage(uiState.message);
- ctrl.statusLevel(uiState.status);
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ validatorHandler({
+ url: url,
+ type: fileType
+ }, function (result) {
+ var uiState = statusToUiState(result);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ctrl.state.on('change:value', function (e) {
- validateUrl(e.value);
- });
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ctrl.statusMessage(uiState.message);
+ ctrl.statusLevel(uiState.status);
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return ComboBox.extend({
- /**
- * Constructs a new control instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- */
- init: function(settings) {
- var self = this, editor = tinymce.activeEditor, editorSettings = editor.settings;
- var actionCallback, fileBrowserCallback, fileBrowserCallbackTypes;
- var fileType = settings.filetype;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ctrl.state.on('change:value', function (e) {
+ validateUrl(e.value);
+ });
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- settings.spellcheck = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return ComboBox.extend({
+ /**
+ * Constructs a new control instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ */
+ init: function (settings) {
+ var self = this, editor = getActiveEditor(), editorSettings = editor.settings;
+ var actionCallback, fileBrowserCallback, fileBrowserCallbackTypes;
+ var fileType = settings.filetype;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- fileBrowserCallbackTypes = editorSettings.file_picker_types || editorSettings.file_browser_callback_types;
- if (fileBrowserCallbackTypes) {
- fileBrowserCallbackTypes = Tools.makeMap(fileBrowserCallbackTypes, /[, ]/);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ settings.spellcheck = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!fileBrowserCallbackTypes || fileBrowserCallbackTypes[fileType]) {
- fileBrowserCallback = editorSettings.file_picker_callback;
- if (fileBrowserCallback && (!fileBrowserCallbackTypes || fileBrowserCallbackTypes[fileType])) {
- actionCallback = function() {
- var meta = self.fire('beforecall').meta;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ fileBrowserCallbackTypes = editorSettings.file_picker_types || editorSettings.file_browser_callback_types;
+ if (fileBrowserCallbackTypes) {
+ fileBrowserCallbackTypes = Tools.makeMap(fileBrowserCallbackTypes, /[, ]/);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- meta = Tools.extend({filetype: fileType}, meta);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!fileBrowserCallbackTypes || fileBrowserCallbackTypes[fileType]) {
+ fileBrowserCallback = editorSettings.file_picker_callback;
+ if (fileBrowserCallback && (!fileBrowserCallbackTypes || fileBrowserCallbackTypes[fileType])) {
+ actionCallback = function () {
+ var meta = self.fire('beforecall').meta;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // file_picker_callback(callback, currentValue, metaData)
- fileBrowserCallback.call(
- editor,
- function(value, meta) {
- self.value(value).fire('change', {meta: meta});
- },
- self.value(),
- meta
- );
- };
- } else {
- // Legacy callback: file_picker_callback(id, currentValue, filetype, window)
- fileBrowserCallback = editorSettings.file_browser_callback;
- if (fileBrowserCallback && (!fileBrowserCallbackTypes || fileBrowserCallbackTypes[fileType])) {
- actionCallback = function() {
- fileBrowserCallback(
- self.getEl('inp').id,
- self.value(),
- fileType,
- window
- );
- };
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ meta = Tools.extend({ filetype: fileType }, meta);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (actionCallback) {
- settings.icon = 'browse';
- settings.onaction = actionCallback;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // file_picker_callback(callback, currentValue, metaData)
+ fileBrowserCallback.call(
+ editor,
+ function (value, meta) {
+ self.value(value).fire('change', { meta: meta });
+ },
+ self.value(),
+ meta
+ );
+ };
+ } else {
+ // Legacy callback: file_picker_callback(id, currentValue, filetype, window)
+ fileBrowserCallback = editorSettings.file_browser_callback;
+ if (fileBrowserCallback && (!fileBrowserCallbackTypes || fileBrowserCallbackTypes[fileType])) {
+ actionCallback = function () {
+ fileBrowserCallback(
+ self.getEl('inp').id,
+ self.value(),
+ fileType,
+ window
+ );
+ };
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super(settings);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (actionCallback) {
+ settings.icon = 'browse';
+ settings.onaction = actionCallback;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- setupAutoCompleteHandler(self, editorSettings, editor.getBody(), fileType);
- setupLinkValidatorHandler(self, editorSettings, fileType);
- }
- });
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super(settings);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/FitLayout.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ setupAutoCompleteHandler(self, editorSettings, editor.getBody(), fileType);
+ setupLinkValidatorHandler(self, editorSettings, fileType);
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * FitLayout.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -45199,44 +50133,45 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.FitLayout
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.AbsoluteLayout
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/FitLayout", [
- "tinymce/ui/AbsoluteLayout"
-], function(AbsoluteLayout) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.FitLayout',
+ [
+ "tinymce.core.ui.AbsoluteLayout"
+ ],
+ function (AbsoluteLayout) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return AbsoluteLayout.extend({
- /**
- * Recalculates the positions of the controls in the specified container.
- *
- * @method recalc
- * @param {tinymce.ui.Container} container Container instance to recalc.
- */
- recalc: function(container) {
- var contLayoutRect = container.layoutRect(), paddingBox = container.paddingBox;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return AbsoluteLayout.extend({
+ /**
+ * Recalculates the positions of the controls in the specified container.
+ *
+ * @method recalc
+ * @param {tinymce.ui.Container} container Container instance to recalc.
+ */
+ recalc: function (container) {
+ var contLayoutRect = container.layoutRect(), paddingBox = container.paddingBox;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container.items().filter(':visible').each(function(ctrl) {
- ctrl.layoutRect({
- x: paddingBox.left,
- y: paddingBox.top,
- w: contLayoutRect.innerW - paddingBox.right - paddingBox.left,
- h: contLayoutRect.innerH - paddingBox.top - paddingBox.bottom
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container.items().filter(':visible').each(function (ctrl) {
+ ctrl.layoutRect({
+ x: paddingBox.left,
+ y: paddingBox.top,
+ w: contLayoutRect.innerW - paddingBox.right - paddingBox.left,
+ h: contLayoutRect.innerH - paddingBox.top - paddingBox.bottom
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (ctrl.recalc) {
- ctrl.recalc();
- }
- });
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/FlexLayout.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (ctrl.recalc) {
+ ctrl.recalc();
+ }
+ });
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * FlexLayout.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -45253,239 +50188,240 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.FlexLayout
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.AbsoluteLayout
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/FlexLayout", [
- "tinymce/ui/AbsoluteLayout"
-], function(AbsoluteLayout) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.FlexLayout',
+ [
+ "tinymce.core.ui.AbsoluteLayout"
+ ],
+ function (AbsoluteLayout) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return AbsoluteLayout.extend({
- /**
- * Recalculates the positions of the controls in the specified container.
- *
- * @method recalc
- * @param {tinymce.ui.Container} container Container instance to recalc.
- */
- recalc: function(container) {
- // A ton of variables, needs to be in the same scope for performance
- var i, l, items, contLayoutRect, contPaddingBox, contSettings, align, pack, spacing, totalFlex, availableSpace, direction;
- var ctrl, ctrlLayoutRect, ctrlSettings, flex, maxSizeItems = [], size, maxSize, ratio, rect, pos, maxAlignEndPos;
- var sizeName, minSizeName, posName, maxSizeName, beforeName, innerSizeName, deltaSizeName, contentSizeName;
- var alignAxisName, alignInnerSizeName, alignSizeName, alignMinSizeName, alignBeforeName, alignAfterName;
- var alignDeltaSizeName, alignContentSizeName;
- var max = Math.max, min = Math.min;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return AbsoluteLayout.extend({
+ /**
+ * Recalculates the positions of the controls in the specified container.
+ *
+ * @method recalc
+ * @param {tinymce.ui.Container} container Container instance to recalc.
+ */
+ recalc: function (container) {
+ // A ton of variables, needs to be in the same scope for performance
+ var i, l, items, contLayoutRect, contPaddingBox, contSettings, align, pack, spacing, totalFlex, availableSpace, direction;
+ var ctrl, ctrlLayoutRect, ctrlSettings, flex, maxSizeItems = [], size, maxSize, ratio, rect, pos, maxAlignEndPos;
+ var sizeName, minSizeName, posName, maxSizeName, beforeName, innerSizeName, deltaSizeName, contentSizeName;
+ var alignAxisName, alignInnerSizeName, alignSizeName, alignMinSizeName, alignBeforeName, alignAfterName;
+ var alignDeltaSizeName, alignContentSizeName;
+ var max = Math.max, min = Math.min;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Get container items, properties and settings
- items = container.items().filter(':visible');
- contLayoutRect = container.layoutRect();
- contPaddingBox = container.paddingBox;
- contSettings = container.settings;
- direction = container.isRtl() ? (contSettings.direction || 'row-reversed') : contSettings.direction;
- align = contSettings.align;
- pack = container.isRtl() ? (contSettings.pack || 'end') : contSettings.pack;
- spacing = contSettings.spacing || 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get container items, properties and settings
+ items = container.items().filter(':visible');
+ contLayoutRect = container.layoutRect();
+ contPaddingBox = container.paddingBox;
+ contSettings = container.settings;
+ direction = container.isRtl() ? (contSettings.direction || 'row-reversed') : contSettings.direction;
+ align = contSettings.align;
+ pack = container.isRtl() ? (contSettings.pack || 'end') : contSettings.pack;
+ spacing = contSettings.spacing || 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (direction == "row-reversed" || direction == "column-reverse") {
- items = items.set(items.toArray().reverse());
- direction = direction.split('-')[0];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (direction == "row-reversed" || direction == "column-reverse") {
+ items = items.set(items.toArray().reverse());
+ direction = direction.split('-')[0];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup axis variable name for row/column direction since the calculations is the same
- if (direction == "column") {
- posName = "y";
- sizeName = "h";
- minSizeName = "minH";
- maxSizeName = "maxH";
- innerSizeName = "innerH";
- beforeName = 'top';
- deltaSizeName = "deltaH";
- contentSizeName = "contentH";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup axis variable name for row/column direction since the calculations is the same
+ if (direction == "column") {
+ posName = "y";
+ sizeName = "h";
+ minSizeName = "minH";
+ maxSizeName = "maxH";
+ innerSizeName = "innerH";
+ beforeName = 'top';
+ deltaSizeName = "deltaH";
+ contentSizeName = "contentH";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- alignBeforeName = "left";
- alignSizeName = "w";
- alignAxisName = "x";
- alignInnerSizeName = "innerW";
- alignMinSizeName = "minW";
- alignAfterName = "right";
- alignDeltaSizeName = "deltaW";
- alignContentSizeName = "contentW";
- } else {
- posName = "x";
- sizeName = "w";
- minSizeName = "minW";
- maxSizeName = "maxW";
- innerSizeName = "innerW";
- beforeName = 'left';
- deltaSizeName = "deltaW";
- contentSizeName = "contentW";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ alignBeforeName = "left";
+ alignSizeName = "w";
+ alignAxisName = "x";
+ alignInnerSizeName = "innerW";
+ alignMinSizeName = "minW";
+ alignAfterName = "right";
+ alignDeltaSizeName = "deltaW";
+ alignContentSizeName = "contentW";
+ } else {
+ posName = "x";
+ sizeName = "w";
+ minSizeName = "minW";
+ maxSizeName = "maxW";
+ innerSizeName = "innerW";
+ beforeName = 'left';
+ deltaSizeName = "deltaW";
+ contentSizeName = "contentW";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- alignBeforeName = "top";
- alignSizeName = "h";
- alignAxisName = "y";
- alignInnerSizeName = "innerH";
- alignMinSizeName = "minH";
- alignAfterName = "bottom";
- alignDeltaSizeName = "deltaH";
- alignContentSizeName = "contentH";
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ alignBeforeName = "top";
+ alignSizeName = "h";
+ alignAxisName = "y";
+ alignInnerSizeName = "innerH";
+ alignMinSizeName = "minH";
+ alignAfterName = "bottom";
+ alignDeltaSizeName = "deltaH";
+ alignContentSizeName = "contentH";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Figure out total flex, availableSpace and collect any max size elements
- availableSpace = contLayoutRect[innerSizeName] - contPaddingBox[beforeName] - contPaddingBox[beforeName];
- maxAlignEndPos = totalFlex = 0;
- for (i = 0, l = items.length; i < l; i++) {
- ctrl = items[i];
- ctrlLayoutRect = ctrl.layoutRect();
- ctrlSettings = ctrl.settings;
- flex = ctrlSettings.flex;
- availableSpace -= (i < l - 1 ? spacing : 0);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Figure out total flex, availableSpace and collect any max size elements
+ availableSpace = contLayoutRect[innerSizeName] - contPaddingBox[beforeName] - contPaddingBox[beforeName];
+ maxAlignEndPos = totalFlex = 0;
+ for (i = 0, l = items.length; i < l; i++) {
+ ctrl = items[i];
+ ctrlLayoutRect = ctrl.layoutRect();
+ ctrlSettings = ctrl.settings;
+ flex = ctrlSettings.flex;
+ availableSpace -= (i < l - 1 ? spacing : 0);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (flex > 0) {
- totalFlex += flex;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (flex > 0) {
+ totalFlex += flex;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Flexed item has a max size then we need to check if we will hit that size
- if (ctrlLayoutRect[maxSizeName]) {
- maxSizeItems.push(ctrl);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Flexed item has a max size then we need to check if we will hit that size
+ if (ctrlLayoutRect[maxSizeName]) {
+ maxSizeItems.push(ctrl);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ctrlLayoutRect.flex = flex;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ctrlLayoutRect.flex = flex;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- availableSpace -= ctrlLayoutRect[minSizeName];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ availableSpace -= ctrlLayoutRect[minSizeName];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Calculate the align end position to be used to check for overflow/underflow
- size = contPaddingBox[alignBeforeName] + ctrlLayoutRect[alignMinSizeName] + contPaddingBox[alignAfterName];
- if (size > maxAlignEndPos) {
- maxAlignEndPos = size;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Calculate the align end position to be used to check for overflow/underflow
+ size = contPaddingBox[alignBeforeName] + ctrlLayoutRect[alignMinSizeName] + contPaddingBox[alignAfterName];
+ if (size > maxAlignEndPos) {
+ maxAlignEndPos = size;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Calculate minW/minH
- rect = {};
- if (availableSpace < 0) {
- rect[minSizeName] = contLayoutRect[minSizeName] - availableSpace + contLayoutRect[deltaSizeName];
- } else {
- rect[minSizeName] = contLayoutRect[innerSizeName] - availableSpace + contLayoutRect[deltaSizeName];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Calculate minW/minH
+ rect = {};
+ if (availableSpace < 0) {
+ rect[minSizeName] = contLayoutRect[minSizeName] - availableSpace + contLayoutRect[deltaSizeName];
+ } else {
+ rect[minSizeName] = contLayoutRect[innerSizeName] - availableSpace + contLayoutRect[deltaSizeName];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rect[alignMinSizeName] = maxAlignEndPos + contLayoutRect[alignDeltaSizeName];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rect[alignMinSizeName] = maxAlignEndPos + contLayoutRect[alignDeltaSizeName];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rect[contentSizeName] = contLayoutRect[innerSizeName] - availableSpace;
- rect[alignContentSizeName] = maxAlignEndPos;
- rect.minW = min(rect.minW, contLayoutRect.maxW);
- rect.minH = min(rect.minH, contLayoutRect.maxH);
- rect.minW = max(rect.minW, contLayoutRect.startMinWidth);
- rect.minH = max(rect.minH, contLayoutRect.startMinHeight);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rect[contentSizeName] = contLayoutRect[innerSizeName] - availableSpace;
+ rect[alignContentSizeName] = maxAlignEndPos;
+ rect.minW = min(rect.minW, contLayoutRect.maxW);
+ rect.minH = min(rect.minH, contLayoutRect.maxH);
+ rect.minW = max(rect.minW, contLayoutRect.startMinWidth);
+ rect.minH = max(rect.minH, contLayoutRect.startMinHeight);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Resize container container if minSize was changed
- if (contLayoutRect.autoResize && (rect.minW != contLayoutRect.minW || rect.minH != contLayoutRect.minH)) {
- rect.w = rect.minW;
- rect.h = rect.minH;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Resize container container if minSize was changed
+ if (contLayoutRect.autoResize && (rect.minW != contLayoutRect.minW || rect.minH != contLayoutRect.minH)) {
+ rect.w = rect.minW;
+ rect.h = rect.minH;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container.layoutRect(rect);
- this.recalc(container);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container.layoutRect(rect);
+ this.recalc(container);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Forced recalc for example if items are hidden/shown
- if (container._lastRect === null) {
- var parentCtrl = container.parent();
- if (parentCtrl) {
- parentCtrl._lastRect = null;
- parentCtrl.recalc();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Forced recalc for example if items are hidden/shown
+ if (container._lastRect === null) {
+ var parentCtrl = container.parent();
+ if (parentCtrl) {
+ parentCtrl._lastRect = null;
+ parentCtrl.recalc();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle max size elements, check if they will become to wide with current options
- ratio = availableSpace / totalFlex;
- for (i = 0, l = maxSizeItems.length; i < l; i++) {
- ctrl = maxSizeItems[i];
- ctrlLayoutRect = ctrl.layoutRect();
- maxSize = ctrlLayoutRect[maxSizeName];
- size = ctrlLayoutRect[minSizeName] + ctrlLayoutRect.flex * ratio;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handle max size elements, check if they will become to wide with current options
+ ratio = availableSpace / totalFlex;
+ for (i = 0, l = maxSizeItems.length; i < l; i++) {
+ ctrl = maxSizeItems[i];
+ ctrlLayoutRect = ctrl.layoutRect();
+ maxSize = ctrlLayoutRect[maxSizeName];
+ size = ctrlLayoutRect[minSizeName] + ctrlLayoutRect.flex * ratio;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (size > maxSize) {
- availableSpace -= (ctrlLayoutRect[maxSizeName] - ctrlLayoutRect[minSizeName]);
- totalFlex -= ctrlLayoutRect.flex;
- ctrlLayoutRect.flex = 0;
- ctrlLayoutRect.maxFlexSize = maxSize;
- } else {
- ctrlLayoutRect.maxFlexSize = 0;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (size > maxSize) {
+ availableSpace -= (ctrlLayoutRect[maxSizeName] - ctrlLayoutRect[minSizeName]);
+ totalFlex -= ctrlLayoutRect.flex;
+ ctrlLayoutRect.flex = 0;
+ ctrlLayoutRect.maxFlexSize = maxSize;
+ } else {
+ ctrlLayoutRect.maxFlexSize = 0;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup new ratio, target layout rect, start position
- ratio = availableSpace / totalFlex;
- pos = contPaddingBox[beforeName];
- rect = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup new ratio, target layout rect, start position
+ ratio = availableSpace / totalFlex;
+ pos = contPaddingBox[beforeName];
+ rect = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Handle pack setting moves the start position to end, center
- if (totalFlex === 0) {
- if (pack == "end") {
- pos = availableSpace + contPaddingBox[beforeName];
- } else if (pack == "center") {
- pos = Math.round(
- (contLayoutRect[innerSizeName] / 2) - ((contLayoutRect[innerSizeName] - availableSpace) / 2)
- ) + contPaddingBox[beforeName];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Handle pack setting moves the start position to end, center
+ if (totalFlex === 0) {
+ if (pack == "end") {
+ pos = availableSpace + contPaddingBox[beforeName];
+ } else if (pack == "center") {
+ pos = Math.round(
+ (contLayoutRect[innerSizeName] / 2) - ((contLayoutRect[innerSizeName] - availableSpace) / 2)
+ ) + contPaddingBox[beforeName];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (pos < 0) {
- pos = contPaddingBox[beforeName];
- }
- } else if (pack == "justify") {
- pos = contPaddingBox[beforeName];
- spacing = Math.floor(availableSpace / (items.length - 1));
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (pos < 0) {
+ pos = contPaddingBox[beforeName];
+ }
+ } else if (pack == "justify") {
+ pos = contPaddingBox[beforeName];
+ spacing = Math.floor(availableSpace / (items.length - 1));
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Default aligning (start) the other ones needs to be calculated while doing the layout
- rect[alignAxisName] = contPaddingBox[alignBeforeName];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Default aligning (start) the other ones needs to be calculated while doing the layout
+ rect[alignAxisName] = contPaddingBox[alignBeforeName];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Start laying out controls
- for (i = 0, l = items.length; i < l; i++) {
- ctrl = items[i];
- ctrlLayoutRect = ctrl.layoutRect();
- size = ctrlLayoutRect.maxFlexSize || ctrlLayoutRect[minSizeName];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Start laying out controls
+ for (i = 0, l = items.length; i < l; i++) {
+ ctrl = items[i];
+ ctrlLayoutRect = ctrl.layoutRect();
+ size = ctrlLayoutRect.maxFlexSize || ctrlLayoutRect[minSizeName];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Align the control on the other axis
- if (align === "center") {
- rect[alignAxisName] = Math.round((contLayoutRect[alignInnerSizeName] / 2) - (ctrlLayoutRect[alignSizeName] / 2));
- } else if (align === "stretch") {
- rect[alignSizeName] = max(
- ctrlLayoutRect[alignMinSizeName] || 0,
- contLayoutRect[alignInnerSizeName] - contPaddingBox[alignBeforeName] - contPaddingBox[alignAfterName]
- );
- rect[alignAxisName] = contPaddingBox[alignBeforeName];
- } else if (align === "end") {
- rect[alignAxisName] = contLayoutRect[alignInnerSizeName] - ctrlLayoutRect[alignSizeName] - contPaddingBox.top;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Align the control on the other axis
+ if (align === "center") {
+ rect[alignAxisName] = Math.round((contLayoutRect[alignInnerSizeName] / 2) - (ctrlLayoutRect[alignSizeName] / 2));
+ } else if (align === "stretch") {
+ rect[alignSizeName] = max(
+ ctrlLayoutRect[alignMinSizeName] || 0,
+ contLayoutRect[alignInnerSizeName] - contPaddingBox[alignBeforeName] - contPaddingBox[alignAfterName]
+ );
+ rect[alignAxisName] = contPaddingBox[alignBeforeName];
+ } else if (align === "end") {
+ rect[alignAxisName] = contLayoutRect[alignInnerSizeName] - ctrlLayoutRect[alignSizeName] - contPaddingBox.top;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Calculate new size based on flex
- if (ctrlLayoutRect.flex > 0) {
- size += ctrlLayoutRect.flex * ratio;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Calculate new size based on flex
+ if (ctrlLayoutRect.flex > 0) {
+ size += ctrlLayoutRect.flex * ratio;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rect[sizeName] = size;
- rect[posName] = pos;
- ctrl.layoutRect(rect);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rect[sizeName] = size;
+ rect[posName] = pos;
+ ctrl.layoutRect(rect);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Recalculate containers
- if (ctrl.recalc) {
- ctrl.recalc();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Recalculate containers
+ if (ctrl.recalc) {
+ ctrl.recalc();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move x/y position
- pos += size + spacing;
- }
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/FlowLayout.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move x/y position
+ pos += size + spacing;
+ }
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * FlowLayout.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -45498,43 +50434,44 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.FlowLayout
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Layout
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/FlowLayout", [
- "tinymce/ui/Layout"
-], function(Layout) {
- return Layout.extend({
- Defaults: {
- containerClass: 'flow-layout',
- controlClass: 'flow-layout-item',
- endClass: 'break'
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.FlowLayout',
+ [
+ "tinymce.core.ui.Layout"
+ ],
+ function (Layout) {
+ return Layout.extend({
+ Defaults: {
+ containerClass: 'flow-layout',
+ controlClass: 'flow-layout-item',
+ endClass: 'break'
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Recalculates the positions of the controls in the specified container.
- *
- * @method recalc
- * @param {tinymce.ui.Container} container Container instance to recalc.
- */
- recalc: function(container) {
- container.items().filter(':visible').each(function(ctrl) {
- if (ctrl.recalc) {
- ctrl.recalc();
- }
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Recalculates the positions of the controls in the specified container.
+ *
+ * @method recalc
+ * @param {tinymce.ui.Container} container Container instance to recalc.
+ */
+ recalc: function (container) {
+ container.items().filter(':visible').each(function (ctrl) {
+ if (ctrl.recalc) {
+ ctrl.recalc();
+ }
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- isNative: function() {
- return true;
- }
- });
-});
-
-// Included from: js/tinymce/classes/fmt/FontInfo.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ isNative: function () {
+ return true;
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * FontInfo.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -45546,64 +50483,66 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.fmt.FontInfo
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/fmt/FontInfo", [
- "tinymce/dom/DOMUtils"
-], function(DOMUtils) {
- var getSpecifiedFontProp = function (propName, rootElm, elm) {
- while (elm !== rootElm) {
- if (elm.style[propName]) {
- return elm.style[propName];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.fmt.FontInfo',
+ [
+ "tinymce.core.dom.DOMUtils"
+ ],
+ function (DOMUtils) {
+ var getSpecifiedFontProp = function (propName, rootElm, elm) {
+ while (elm !== rootElm) {
+ if (elm.style[propName]) {
+ return elm.style[propName];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elm = elm.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elm = elm.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return '';
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return '';
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var toPt = function (fontSize) {
- if (/[0-9.]+px$/.test(fontSize)) {
- return Math.round(parseInt(fontSize, 10) * 72 / 96) + 'pt';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var toPt = function (fontSize) {
+ if (/[0-9.]+px$/.test(fontSize)) {
+ return Math.round(parseInt(fontSize, 10) * 72 / 96) + 'pt';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return fontSize;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return fontSize;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var normalizeFontFamily = function (fontFamily) {
- // 'Font name', Font -> Font name,Font
- return fontFamily.replace(/[\'\"]/g, '').replace(/,\s+/g, ',');
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var normalizeFontFamily = function (fontFamily) {
+ // 'Font name', Font -> Font name,Font
+ return fontFamily.replace(/[\'\"]/g, '').replace(/,\s+/g, ',');
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getComputedFontProp = function (propName, elm) {
- return DOMUtils.DOM.getStyle(elm, propName, true);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getComputedFontProp = function (propName, elm) {
+ return DOMUtils.DOM.getStyle(elm, propName, true);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getFontSize = function (rootElm, elm) {
- var specifiedFontSize = getSpecifiedFontProp('fontSize', rootElm, elm);
- return specifiedFontSize !== '' ? specifiedFontSize : getComputedFontProp('fontSize', elm);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getFontSize = function (rootElm, elm) {
+ var specifiedFontSize = getSpecifiedFontProp('fontSize', rootElm, elm);
+ return specifiedFontSize !== '' ? specifiedFontSize : getComputedFontProp('fontSize', elm);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getFontFamily = function (rootElm, elm) {
- var specifiedFontSize = getSpecifiedFontProp('fontFamily', rootElm, elm);
- var fontValue = specifiedFontSize !== '' ? specifiedFontSize : getComputedFontProp('fontFamily', elm);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getFontFamily = function (rootElm, elm) {
+ var specifiedFontSize = getSpecifiedFontProp('fontFamily', rootElm, elm);
+ var fontValue = specifiedFontSize !== '' ? specifiedFontSize : getComputedFontProp('fontFamily', elm);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return fontValue !== undefined ? normalizeFontFamily(fontValue) : '';
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return fontValue !== undefined ? normalizeFontFamily(fontValue) : '';
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- getFontSize: getFontSize,
- getFontFamily: getFontFamily,
- toPt: toPt
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ getFontSize: getFontSize,
+ getFontFamily: getFontFamily,
+ toPt: toPt
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/FormatControls.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * FormatControls.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -45615,740 +50554,752 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.FormatControls
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/FormatControls", [
- "tinymce/ui/Control",
- "tinymce/ui/Widget",
- "tinymce/ui/FloatPanel",
- "tinymce/util/Tools",
- "tinymce/util/Arr",
- "tinymce/dom/DOMUtils",
- "tinymce/EditorManager",
- "tinymce/Env",
- "tinymce/fmt/FontInfo"
-], function(Control, Widget, FloatPanel, Tools, Arr, DOMUtils, EditorManager, Env, FontInfo) {
- var each = Tools.each;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.FormatControls',
+ [
+ "tinymce.core.ui.Control",
+ "tinymce.core.ui.Widget",
+ "tinymce.core.ui.FloatPanel",
+ "tinymce.core.util.Tools",
+ "tinymce.core.util.Arr",
+ "tinymce.core.dom.DOMUtils",
+ "tinymce.core.EditorManager",
+ "tinymce.core.Env",
+ "tinymce.core.fmt.FontInfo"
+ ],
+ function (Control, Widget, FloatPanel, Tools, Arr, DOMUtils, EditorManager, Env, FontInfo) {
+ var each = Tools.each;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var flatten = function (ar) {
- return Arr.reduce(ar, function (result, item) {
- return result.concat(item);
- }, []);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var flatten = function (ar) {
+ return Arr.reduce(ar, function (result, item) {
+ return result.concat(item);
+ }, []);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- EditorManager.on('AddEditor', function(e) {
- var editor = e.editor;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ EditorManager.on('AddEditor', function (e) {
+ var editor = e.editor;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- setupRtlMode(editor);
- registerControls(editor);
- setupContainer(editor);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ setupRtlMode(editor);
+ registerControls(editor);
+ setupContainer(editor);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Control.translate = function(text) {
- return EditorManager.translate(text);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Control.translate = function (text) {
+ return EditorManager.translate(text);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Widget.tooltips = !Env.iOS;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Widget.tooltips = !Env.iOS;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setupContainer(editor) {
- if (editor.settings.ui_container) {
- Env.container = DOMUtils.DOM.select(editor.settings.ui_container)[0];
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setupContainer(editor) {
+ if (editor.settings.ui_container) {
+ Env.container = DOMUtils.DOM.select(editor.settings.ui_container)[0];
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setupRtlMode(editor) {
- editor.on('ScriptsLoaded', function () {
- if (editor.rtl) {
- Control.rtl = true;
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setupRtlMode(editor) {
+ editor.on('ScriptsLoaded', function () {
+ if (editor.rtl) {
+ Control.rtl = true;
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function registerControls(editor) {
- var formatMenu;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function registerControls(editor) {
+ var formatMenu;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function createListBoxChangeHandler(items, formatName) {
- return function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function createListBoxChangeHandler(items, formatName) {
+ return function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('nodeChange', function(e) {
- var formatter = editor.formatter;
- var value = null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('nodeChange', function (e) {
+ var formatter = editor.formatter;
+ var value = null;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(e.parents, function(node) {
- each(items, function(item) {
- if (formatName) {
- if (formatter.matchNode(node, formatName, {value: item.value})) {
- value = item.value;
- }
- } else {
- if (formatter.matchNode(node, item.value)) {
- value = item.value;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(e.parents, function (node) {
+ each(items, function (item) {
+ if (formatName) {
+ if (formatter.matchNode(node, formatName, { value: item.value })) {
+ value = item.value;
+ }
+ } else {
+ if (formatter.matchNode(node, item.value)) {
+ value = item.value;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value) {
- return false;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value) {
+ return false;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value) {
- return false;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value) {
+ return false;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.value(value);
- });
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.value(value);
+ });
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function createFontNameListBoxChangeHandler(items) {
- return function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function createFontNameListBoxChangeHandler(items) {
+ return function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var getFirstFont = function (fontFamily) {
- return fontFamily ? fontFamily.split(',')[0] : '';
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var getFirstFont = function (fontFamily) {
+ return fontFamily ? fontFamily.split(',')[0] : '';
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('nodeChange', function(e) {
- var fontFamily, value = null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('nodeChange', function (e) {
+ var fontFamily, value = null;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- fontFamily = FontInfo.getFontFamily(editor.getBody(), e.element);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ fontFamily = FontInfo.getFontFamily(editor.getBody(), e.element);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(items, function(item) {
- if (item.value.toLowerCase() === fontFamily.toLowerCase()) {
- value = item.value;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(items, function (item) {
+ if (item.value.toLowerCase() === fontFamily.toLowerCase()) {
+ value = item.value;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(items, function(item) {
- if (!value && getFirstFont(item.value).toLowerCase() === getFirstFont(fontFamily).toLowerCase()) {
- value = item.value;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(items, function (item) {
+ if (!value && getFirstFont(item.value).toLowerCase() === getFirstFont(fontFamily).toLowerCase()) {
+ value = item.value;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.value(value);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.value(value);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!value && fontFamily) {
- self.text(getFirstFont(fontFamily));
- }
- });
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!value && fontFamily) {
+ self.text(getFirstFont(fontFamily));
+ }
+ });
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function createFontSizeListBoxChangeHandler(items) {
- return function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function createFontSizeListBoxChangeHandler(items) {
+ return function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('nodeChange', function(e) {
- var px, pt, value = null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('nodeChange', function (e) {
+ var px, pt, value = null;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- px = FontInfo.getFontSize(editor.getBody(), e.element);
- pt = FontInfo.toPt(px);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ px = FontInfo.getFontSize(editor.getBody(), e.element);
+ pt = FontInfo.toPt(px);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(items, function(item) {
- if (item.value === px) {
- value = px;
- } else if (item.value === pt) {
- value = pt;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(items, function (item) {
+ if (item.value === px) {
+ value = px;
+ } else if (item.value === pt) {
+ value = pt;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.value(value);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.value(value);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!value) {
- self.text(pt);
- }
- });
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!value) {
+ self.text(pt);
+ }
+ });
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function createFormats(formats) {
- formats = formats.replace(/;$/, '').split(';');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function createFormats(formats) {
+ formats = formats.replace(/;$/, '').split(';');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var i = formats.length;
- while (i--) {
- formats[i] = formats[i].split('=');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var i = formats.length;
+ while (i--) {
+ formats[i] = formats[i].split('=');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return formats;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return formats;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function createFormatMenu() {
- var count = 0, newFormats = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function createFormatMenu() {
+ var count = 0, newFormats = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var defaultStyleFormats = [
- {title: 'Headings', items: [
- {title: 'Heading 1', format: 'h1'},
- {title: 'Heading 2', format: 'h2'},
- {title: 'Heading 3', format: 'h3'},
- {title: 'Heading 4', format: 'h4'},
- {title: 'Heading 5', format: 'h5'},
- {title: 'Heading 6', format: 'h6'}
- ]},
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var defaultStyleFormats = [
+ {
+ title: 'Headings', items: [
+ { title: 'Heading 1', format: 'h1' },
+ { title: 'Heading 2', format: 'h2' },
+ { title: 'Heading 3', format: 'h3' },
+ { title: 'Heading 4', format: 'h4' },
+ { title: 'Heading 5', format: 'h5' },
+ { title: 'Heading 6', format: 'h6' }
+ ]
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- {title: 'Inline', items: [
- {title: 'Bold', icon: 'bold', format: 'bold'},
- {title: 'Italic', icon: 'italic', format: 'italic'},
- {title: 'Underline', icon: 'underline', format: 'underline'},
- {title: 'Strikethrough', icon: 'strikethrough', format: 'strikethrough'},
- {title: 'Superscript', icon: 'superscript', format: 'superscript'},
- {title: 'Subscript', icon: 'subscript', format: 'subscript'},
- {title: 'Code', icon: 'code', format: 'code'}
- ]},
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ {
+ title: 'Inline', items: [
+ { title: 'Bold', icon: 'bold', format: 'bold' },
+ { title: 'Italic', icon: 'italic', format: 'italic' },
+ { title: 'Underline', icon: 'underline', format: 'underline' },
+ { title: 'Strikethrough', icon: 'strikethrough', format: 'strikethrough' },
+ { title: 'Superscript', icon: 'superscript', format: 'superscript' },
+ { title: 'Subscript', icon: 'subscript', format: 'subscript' },
+ { title: 'Code', icon: 'code', format: 'code' }
+ ]
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- {title: 'Blocks', items: [
- {title: 'Paragraph', format: 'p'},
- {title: 'Blockquote', format: 'blockquote'},
- {title: 'Div', format: 'div'},
- {title: 'Pre', format: 'pre'}
- ]},
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ {
+ title: 'Blocks', items: [
+ { title: 'Paragraph', format: 'p' },
+ { title: 'Blockquote', format: 'blockquote' },
+ { title: 'Div', format: 'div' },
+ { title: 'Pre', format: 'pre' }
+ ]
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- {title: 'Alignment', items: [
- {title: 'Left', icon: 'alignleft', format: 'alignleft'},
- {title: 'Center', icon: 'aligncenter', format: 'aligncenter'},
- {title: 'Right', icon: 'alignright', format: 'alignright'},
- {title: 'Justify', icon: 'alignjustify', format: 'alignjustify'}
- ]}
- ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ {
+ title: 'Alignment', items: [
+ { title: 'Left', icon: 'alignleft', format: 'alignleft' },
+ { title: 'Center', icon: 'aligncenter', format: 'aligncenter' },
+ { title: 'Right', icon: 'alignright', format: 'alignright' },
+ { title: 'Justify', icon: 'alignjustify', format: 'alignjustify' }
+ ]
+ }
+ ];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function createMenu(formats) {
- var menu = [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function createMenu(formats) {
+ var menu = [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!formats) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!formats) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(formats, function(format) {
- var menuItem = {
- text: format.title,
- icon: format.icon
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(formats, function (format) {
+ var menuItem = {
+ text: format.title,
+ icon: format.icon
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (format.items) {
- menuItem.menu = createMenu(format.items);
- } else {
- var formatName = format.format || "custom" + count++;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (format.items) {
+ menuItem.menu = createMenu(format.items);
+ } else {
+ var formatName = format.format || "custom" + count++;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!format.format) {
- format.name = formatName;
- newFormats.push(format);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!format.format) {
+ format.name = formatName;
+ newFormats.push(format);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- menuItem.format = formatName;
- menuItem.cmd = format.cmd;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ menuItem.format = formatName;
+ menuItem.cmd = format.cmd;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- menu.push(menuItem);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ menu.push(menuItem);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return menu;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return menu;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function createStylesMenu() {
- var menu;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function createStylesMenu() {
+ var menu;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (editor.settings.style_formats_merge) {
- if (editor.settings.style_formats) {
- menu = createMenu(defaultStyleFormats.concat(editor.settings.style_formats));
- } else {
- menu = createMenu(defaultStyleFormats);
- }
- } else {
- menu = createMenu(editor.settings.style_formats || defaultStyleFormats);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (editor.settings.style_formats_merge) {
+ if (editor.settings.style_formats) {
+ menu = createMenu(defaultStyleFormats.concat(editor.settings.style_formats));
+ } else {
+ menu = createMenu(defaultStyleFormats);
+ }
+ } else {
+ menu = createMenu(editor.settings.style_formats || defaultStyleFormats);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return menu;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return menu;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('init', function() {
- each(newFormats, function(format) {
- editor.formatter.register(format.name, format);
- });
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('init', function () {
+ each(newFormats, function (format) {
+ editor.formatter.register(format.name, format);
+ });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- type: 'menu',
- items: createStylesMenu(),
- onPostRender: function(e) {
- editor.fire('renderFormatsMenu', {control: e.control});
- },
- itemDefaults: {
- preview: true,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ type: 'menu',
+ items: createStylesMenu(),
+ onPostRender: function (e) {
+ editor.fire('renderFormatsMenu', { control: e.control });
+ },
+ itemDefaults: {
+ preview: true,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- textStyle: function() {
- if (this.settings.format) {
- return editor.formatter.getCssText(this.settings.format);
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ textStyle: function () {
+ if (this.settings.format) {
+ return editor.formatter.getCssText(this.settings.format);
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- onPostRender: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ onPostRender: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.parent().on('show', function() {
- var formatName, command;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.parent().on('show', function () {
+ var formatName, command;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- formatName = self.settings.format;
- if (formatName) {
- self.disabled(!editor.formatter.canApply(formatName));
- self.active(editor.formatter.match(formatName));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ formatName = self.settings.format;
+ if (formatName) {
+ self.disabled(!editor.formatter.canApply(formatName));
+ self.active(editor.formatter.match(formatName));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- command = self.settings.cmd;
- if (command) {
- self.active(editor.queryCommandState(command));
- }
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ command = self.settings.cmd;
+ if (command) {
+ self.active(editor.queryCommandState(command));
+ }
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- onclick: function() {
- if (this.settings.format) {
- toggleFormat(this.settings.format);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ onclick: function () {
+ if (this.settings.format) {
+ toggleFormat(this.settings.format);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.settings.cmd) {
- editor.execCommand(this.settings.cmd);
- }
- }
- }
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.settings.cmd) {
+ editor.execCommand(this.settings.cmd);
+ }
+ }
+ }
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- formatMenu = createFormatMenu();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ formatMenu = createFormatMenu();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function initOnPostRender(name) {
- return function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function initOnPostRender(name) {
+ return function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // TODO: Fix this
- if (editor.formatter) {
- editor.formatter.formatChanged(name, function(state) {
- self.active(state);
- });
- } else {
- editor.on('init', function() {
- editor.formatter.formatChanged(name, function(state) {
- self.active(state);
- });
- });
- }
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // TODO: Fix this
+ if (editor.formatter) {
+ editor.formatter.formatChanged(name, function (state) {
+ self.active(state);
+ });
+ } else {
+ editor.on('init', function () {
+ editor.formatter.formatChanged(name, function (state) {
+ self.active(state);
+ });
+ });
+ }
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Simple format controls <control/format>:<UI text>
- each({
- bold: 'Bold',
- italic: 'Italic',
- underline: 'Underline',
- strikethrough: 'Strikethrough',
- subscript: 'Subscript',
- superscript: 'Superscript'
- }, function(text, name) {
- editor.addButton(name, {
- tooltip: text,
- onPostRender: initOnPostRender(name),
- onclick: function() {
- toggleFormat(name);
- }
- });
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Simple format controls <control/format>:<UI text>
+ each({
+ bold: 'Bold',
+ italic: 'Italic',
+ underline: 'Underline',
+ strikethrough: 'Strikethrough',
+ subscript: 'Subscript',
+ superscript: 'Superscript'
+ }, function (text, name) {
+ editor.addButton(name, {
+ tooltip: text,
+ onPostRender: initOnPostRender(name),
+ onclick: function () {
+ toggleFormat(name);
+ }
+ });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Simple command controls <control>:[<UI text>,<Command>]
- each({
- outdent: ['Decrease indent', 'Outdent'],
- indent: ['Increase indent', 'Indent'],
- cut: ['Cut', 'Cut'],
- copy: ['Copy', 'Copy'],
- paste: ['Paste', 'Paste'],
- help: ['Help', 'mceHelp'],
- selectall: ['Select all', 'SelectAll'],
- removeformat: ['Clear formatting', 'RemoveFormat'],
- visualaid: ['Visual aids', 'mceToggleVisualAid'],
- newdocument: ['New document', 'mceNewDocument']
- }, function(item, name) {
- editor.addButton(name, {
- tooltip: item[0],
- cmd: item[1]
- });
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Simple command controls <control>:[<UI text>,<Command>]
+ each({
+ outdent: ['Decrease indent', 'Outdent'],
+ indent: ['Increase indent', 'Indent'],
+ cut: ['Cut', 'Cut'],
+ copy: ['Copy', 'Copy'],
+ paste: ['Paste', 'Paste'],
+ help: ['Help', 'mceHelp'],
+ selectall: ['Select all', 'SelectAll'],
+ removeformat: ['Clear formatting', 'RemoveFormat'],
+ visualaid: ['Visual aids', 'mceToggleVisualAid'],
+ newdocument: ['New document', 'mceNewDocument']
+ }, function (item, name) {
+ editor.addButton(name, {
+ tooltip: item[0],
+ cmd: item[1]
+ });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Simple command controls with format state
- each({
- blockquote: ['Blockquote', 'mceBlockQuote'],
- subscript: ['Subscript', 'Subscript'],
- superscript: ['Superscript', 'Superscript'],
- alignleft: ['Align left', 'JustifyLeft'],
- aligncenter: ['Align center', 'JustifyCenter'],
- alignright: ['Align right', 'JustifyRight'],
- alignjustify: ['Justify', 'JustifyFull'],
- alignnone: ['No alignment', 'JustifyNone']
- }, function(item, name) {
- editor.addButton(name, {
- tooltip: item[0],
- cmd: item[1],
- onPostRender: initOnPostRender(name)
- });
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Simple command controls with format state
+ each({
+ blockquote: ['Blockquote', 'mceBlockQuote'],
+ subscript: ['Subscript', 'Subscript'],
+ superscript: ['Superscript', 'Superscript'],
+ alignleft: ['Align left', 'JustifyLeft'],
+ aligncenter: ['Align center', 'JustifyCenter'],
+ alignright: ['Align right', 'JustifyRight'],
+ alignjustify: ['Justify', 'JustifyFull'],
+ alignnone: ['No alignment', 'JustifyNone']
+ }, function (item, name) {
+ editor.addButton(name, {
+ tooltip: item[0],
+ cmd: item[1],
+ onPostRender: initOnPostRender(name)
+ });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function toggleUndoRedoState(type) {
- return function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function toggleUndoRedoState(type) {
+ return function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function checkState() {
- var typeFn = type == 'redo' ? 'hasRedo' : 'hasUndo';
- return editor.undoManager ? editor.undoManager[typeFn]() : false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function checkState() {
+ var typeFn = type == 'redo' ? 'hasRedo' : 'hasUndo';
+ return editor.undoManager ? editor.undoManager[typeFn]() : false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.disabled(!checkState());
- editor.on('Undo Redo AddUndo TypingUndo ClearUndos SwitchMode', function() {
- self.disabled(editor.readonly || !checkState());
- });
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.disabled(!checkState());
+ editor.on('Undo Redo AddUndo TypingUndo ClearUndos SwitchMode', function () {
+ self.disabled(editor.readonly || !checkState());
+ });
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function toggleVisualAidState() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function toggleVisualAidState() {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('VisualAid', function(e) {
- self.active(e.hasVisual);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('VisualAid', function (e) {
+ self.active(e.hasVisual);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.active(editor.hasVisual);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.active(editor.hasVisual);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var trimMenuItems = function (menuItems) {
- var outputMenuItems = menuItems;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var trimMenuItems = function (menuItems) {
+ var outputMenuItems = menuItems;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (outputMenuItems.length > 0 && outputMenuItems[0].text === '-') {
- outputMenuItems = outputMenuItems.slice(1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (outputMenuItems.length > 0 && outputMenuItems[0].text === '-') {
+ outputMenuItems = outputMenuItems.slice(1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (outputMenuItems.length > 0 && outputMenuItems[outputMenuItems.length - 1].text === '-') {
- outputMenuItems = outputMenuItems.slice(0, outputMenuItems.length - 1);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (outputMenuItems.length > 0 && outputMenuItems[outputMenuItems.length - 1].text === '-') {
+ outputMenuItems = outputMenuItems.slice(0, outputMenuItems.length - 1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return outputMenuItems;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return outputMenuItems;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var createCustomMenuItems = function (names) {
- var items, nameList;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createCustomMenuItems = function (names) {
+ var items, nameList;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof names === 'string') {
- nameList = names.split(' ');
- } else if (Tools.isArray(names)) {
- return flatten(Tools.map(names, createCustomMenuItems));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof names === 'string') {
+ nameList = names.split(' ');
+ } else if (Tools.isArray(names)) {
+ return flatten(Tools.map(names, createCustomMenuItems));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- items = Tools.grep(nameList, function (name) {
- return name === '|' || name in editor.menuItems;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ items = Tools.grep(nameList, function (name) {
+ return name === '|' || name in editor.menuItems;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Tools.map(items, function (name) {
- return name === '|' ? {text: '-'} : editor.menuItems[name];
- });
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Tools.map(items, function (name) {
+ return name === '|' ? { text: '-' } : editor.menuItems[name];
+ });
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var createContextMenuItems = function (context) {
- var outputMenuItems = [{text: '-'}];
- var menuItems = Tools.grep(editor.menuItems, function (menuItem) {
- return menuItem.context === context;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createContextMenuItems = function (context) {
+ var outputMenuItems = [{ text: '-' }];
+ var menuItems = Tools.grep(editor.menuItems, function (menuItem) {
+ return menuItem.context === context;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(menuItems, function (menuItem) {
- if (menuItem.separator == 'before') {
- outputMenuItems.push({text: '|'});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(menuItems, function (menuItem) {
+ if (menuItem.separator == 'before') {
+ outputMenuItems.push({ text: '|' });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (menuItem.prependToContext) {
- outputMenuItems.unshift(menuItem);
- } else {
- outputMenuItems.push(menuItem);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (menuItem.prependToContext) {
+ outputMenuItems.unshift(menuItem);
+ } else {
+ outputMenuItems.push(menuItem);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (menuItem.separator == 'after') {
- outputMenuItems.push({text: '|'});
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (menuItem.separator == 'after') {
+ outputMenuItems.push({ text: '|' });
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return outputMenuItems;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return outputMenuItems;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var createInsertMenu = function (editorSettings) {
- if (editorSettings.insert_button_items) {
- return trimMenuItems(createCustomMenuItems(editorSettings.insert_button_items));
- } else {
- return trimMenuItems(createContextMenuItems('insert'));
- }
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var createInsertMenu = function (editorSettings) {
+ if (editorSettings.insert_button_items) {
+ return trimMenuItems(createCustomMenuItems(editorSettings.insert_button_items));
+ } else {
+ return trimMenuItems(createContextMenuItems('insert'));
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addButton('undo', {
- tooltip: 'Undo',
- onPostRender: toggleUndoRedoState('undo'),
- cmd: 'undo'
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addButton('undo', {
+ tooltip: 'Undo',
+ onPostRender: toggleUndoRedoState('undo'),
+ cmd: 'undo'
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addButton('redo', {
- tooltip: 'Redo',
- onPostRender: toggleUndoRedoState('redo'),
- cmd: 'redo'
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addButton('redo', {
+ tooltip: 'Redo',
+ onPostRender: toggleUndoRedoState('redo'),
+ cmd: 'redo'
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addMenuItem('newdocument', {
- text: 'New document',
- icon: 'newdocument',
- cmd: 'mceNewDocument'
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addMenuItem('newdocument', {
+ text: 'New document',
+ icon: 'newdocument',
+ cmd: 'mceNewDocument'
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addMenuItem('undo', {
- text: 'Undo',
- icon: 'undo',
- shortcut: 'Meta+Z',
- onPostRender: toggleUndoRedoState('undo'),
- cmd: 'undo'
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addMenuItem('undo', {
+ text: 'Undo',
+ icon: 'undo',
+ shortcut: 'Meta+Z',
+ onPostRender: toggleUndoRedoState('undo'),
+ cmd: 'undo'
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addMenuItem('redo', {
- text: 'Redo',
- icon: 'redo',
- shortcut: 'Meta+Y',
- onPostRender: toggleUndoRedoState('redo'),
- cmd: 'redo'
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addMenuItem('redo', {
+ text: 'Redo',
+ icon: 'redo',
+ shortcut: 'Meta+Y',
+ onPostRender: toggleUndoRedoState('redo'),
+ cmd: 'redo'
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addMenuItem('visualaid', {
- text: 'Visual aids',
- selectable: true,
- onPostRender: toggleVisualAidState,
- cmd: 'mceToggleVisualAid'
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addMenuItem('visualaid', {
+ text: 'Visual aids',
+ selectable: true,
+ onPostRender: toggleVisualAidState,
+ cmd: 'mceToggleVisualAid'
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addButton('remove', {
- tooltip: 'Remove',
- icon: 'remove',
- cmd: 'Delete'
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addButton('remove', {
+ tooltip: 'Remove',
+ icon: 'remove',
+ cmd: 'Delete'
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addButton('insert', {
- type: 'menubutton',
- icon: 'insert',
- menu: [],
- oncreatemenu: function () {
- this.menu.add(createInsertMenu(editor.settings));
- this.menu.renderNew();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addButton('insert', {
+ type: 'menubutton',
+ icon: 'insert',
+ menu: [],
+ oncreatemenu: function () {
+ this.menu.add(createInsertMenu(editor.settings));
+ this.menu.renderNew();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each({
- cut: ['Cut', 'Cut', 'Meta+X'],
- copy: ['Copy', 'Copy', 'Meta+C'],
- paste: ['Paste', 'Paste', 'Meta+V'],
- selectall: ['Select all', 'SelectAll', 'Meta+A'],
- bold: ['Bold', 'Bold', 'Meta+B'],
- italic: ['Italic', 'Italic', 'Meta+I'],
- underline: ['Underline', 'Underline', 'Meta+U'],
- strikethrough: ['Strikethrough', 'Strikethrough'],
- subscript: ['Subscript', 'Subscript'],
- superscript: ['Superscript', 'Superscript'],
- removeformat: ['Clear formatting', 'RemoveFormat']
- }, function(item, name) {
- editor.addMenuItem(name, {
- text: item[0],
- icon: name,
- shortcut: item[2],
- cmd: item[1]
- });
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each({
+ cut: ['Cut', 'Cut', 'Meta+X'],
+ copy: ['Copy', 'Copy', 'Meta+C'],
+ paste: ['Paste', 'Paste', 'Meta+V'],
+ selectall: ['Select all', 'SelectAll', 'Meta+A'],
+ bold: ['Bold', 'Bold', 'Meta+B'],
+ italic: ['Italic', 'Italic', 'Meta+I'],
+ underline: ['Underline', 'Underline', 'Meta+U'],
+ strikethrough: ['Strikethrough', 'Strikethrough'],
+ subscript: ['Subscript', 'Subscript'],
+ superscript: ['Superscript', 'Superscript'],
+ removeformat: ['Clear formatting', 'RemoveFormat']
+ }, function (item, name) {
+ editor.addMenuItem(name, {
+ text: item[0],
+ icon: name,
+ shortcut: item[2],
+ cmd: item[1]
+ });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.on('mousedown', function() {
- FloatPanel.hideAll();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.on('mousedown', function () {
+ FloatPanel.hideAll();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function toggleFormat(fmt) {
- if (fmt.control) {
- fmt = fmt.control.value();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function toggleFormat(fmt) {
+ if (fmt.control) {
+ fmt = fmt.control.value();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (fmt) {
- editor.execCommand('mceToggleFormat', false, fmt);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (fmt) {
+ editor.execCommand('mceToggleFormat', false, fmt);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hideMenuObjects(menu) {
- var count = menu.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hideMenuObjects(menu) {
+ var count = menu.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each(menu, function (item) {
- if (item.menu) {
- item.hidden = hideMenuObjects(item.menu) === 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each(menu, function (item) {
+ if (item.menu) {
+ item.hidden = hideMenuObjects(item.menu) === 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var formatName = item.format;
- if (formatName) {
- item.hidden = !editor.formatter.canApply(formatName);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var formatName = item.format;
+ if (formatName) {
+ item.hidden = !editor.formatter.canApply(formatName);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (item.hidden) {
- count--;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (item.hidden) {
+ count--;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return count;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return count;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hideFormatMenuItems(menu) {
- var count = menu.items().length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hideFormatMenuItems(menu) {
+ var count = menu.items().length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- menu.items().each(function (item) {
- if (item.menu) {
- item.visible(hideFormatMenuItems(item.menu) > 0);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ menu.items().each(function (item) {
+ if (item.menu) {
+ item.visible(hideFormatMenuItems(item.menu) > 0);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!item.menu && item.settings.menu) {
- item.visible(hideMenuObjects(item.settings.menu) > 0);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!item.menu && item.settings.menu) {
+ item.visible(hideMenuObjects(item.settings.menu) > 0);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var formatName = item.settings.format;
- if (formatName) {
- item.visible(editor.formatter.canApply(formatName));
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var formatName = item.settings.format;
+ if (formatName) {
+ item.visible(editor.formatter.canApply(formatName));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!item.visible()) {
- count--;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!item.visible()) {
+ count--;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return count;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return count;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addButton('styleselect', {
- type: 'menubutton',
- text: 'Formats',
- menu: formatMenu,
- onShowMenu: function () {
- if (editor.settings.style_formats_autohide) {
- hideFormatMenuItems(this.menu);
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addButton('styleselect', {
+ type: 'menubutton',
+ text: 'Formats',
+ menu: formatMenu,
+ onShowMenu: function () {
+ if (editor.settings.style_formats_autohide) {
+ hideFormatMenuItems(this.menu);
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addButton('formatselect', function() {
- var items = [], blocks = createFormats(editor.settings.block_formats ||
- 'Paragraph=p;' +
- 'Heading 1=h1;' +
- 'Heading 2=h2;' +
- 'Heading 3=h3;' +
- 'Heading 4=h4;' +
- 'Heading 5=h5;' +
- 'Heading 6=h6;' +
- 'Preformatted=pre'
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addButton('formatselect', function () {
+ var items = [], blocks = createFormats(editor.settings.block_formats ||
+ 'Paragraph=p;' +
+ 'Heading 1=h1;' +
+ 'Heading 2=h2;' +
+ 'Heading 3=h3;' +
+ 'Heading 4=h4;' +
+ 'Heading 5=h5;' +
+ 'Heading 6=h6;' +
+ 'Preformatted=pre'
+ );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(blocks, function(block) {
- items.push({
- text: block[0],
- value: block[1],
- textStyle: function() {
- return editor.formatter.getCssText(block[1]);
- }
- });
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(blocks, function (block) {
+ items.push({
+ text: block[0],
+ value: block[1],
+ textStyle: function () {
+ return editor.formatter.getCssText(block[1]);
+ }
+ });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- type: 'listbox',
- text: blocks[0][0],
- values: items,
- fixedWidth: true,
- onselect: toggleFormat,
- onPostRender: createListBoxChangeHandler(items)
- };
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ type: 'listbox',
+ text: blocks[0][0],
+ values: items,
+ fixedWidth: true,
+ onselect: toggleFormat,
+ onPostRender: createListBoxChangeHandler(items)
+ };
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addButton('fontselect', function() {
- var defaultFontsFormats =
- 'Andale Mono=andale mono,monospace;' +
- 'Arial=arial,helvetica,sans-serif;' +
- 'Arial Black=arial black,sans-serif;' +
- 'Book Antiqua=book antiqua,palatino,serif;' +
- 'Comic Sans MS=comic sans ms,sans-serif;' +
- 'Courier New=courier new,courier,monospace;' +
- 'Georgia=georgia,palatino,serif;' +
- 'Helvetica=helvetica,arial,sans-serif;' +
- 'Impact=impact,sans-serif;' +
- 'Symbol=symbol;' +
- 'Tahoma=tahoma,arial,helvetica,sans-serif;' +
- 'Terminal=terminal,monaco,monospace;' +
- 'Times New Roman=times new roman,times,serif;' +
- 'Trebuchet MS=trebuchet ms,geneva,sans-serif;' +
- 'Verdana=verdana,geneva,sans-serif;' +
- 'Webdings=webdings;' +
- 'Wingdings=wingdings,zapf dingbats';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addButton('fontselect', function () {
+ var defaultFontsFormats =
+ 'Andale Mono=andale mono,monospace;' +
+ 'Arial=arial,helvetica,sans-serif;' +
+ 'Arial Black=arial black,sans-serif;' +
+ 'Book Antiqua=book antiqua,palatino,serif;' +
+ 'Comic Sans MS=comic sans ms,sans-serif;' +
+ 'Courier New=courier new,courier,monospace;' +
+ 'Georgia=georgia,palatino,serif;' +
+ 'Helvetica=helvetica,arial,sans-serif;' +
+ 'Impact=impact,sans-serif;' +
+ 'Symbol=symbol;' +
+ 'Tahoma=tahoma,arial,helvetica,sans-serif;' +
+ 'Terminal=terminal,monaco,monospace;' +
+ 'Times New Roman=times new roman,times,serif;' +
+ 'Trebuchet MS=trebuchet ms,geneva,sans-serif;' +
+ 'Verdana=verdana,geneva,sans-serif;' +
+ 'Webdings=webdings;' +
+ 'Wingdings=wingdings,zapf dingbats';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var items = [], fonts = createFormats(editor.settings.font_formats || defaultFontsFormats);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var items = [], fonts = createFormats(editor.settings.font_formats || defaultFontsFormats);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(fonts, function(font) {
- items.push({
- text: {raw: font[0]},
- value: font[1],
- textStyle: font[1].indexOf('dings') == -1 ? 'font-family:' + font[1] : ''
- });
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(fonts, function (font) {
+ items.push({
+ text: { raw: font[0] },
+ value: font[1],
+ textStyle: font[1].indexOf('dings') == -1 ? 'font-family:' + font[1] : ''
+ });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- type: 'listbox',
- text: 'Font Family',
- tooltip: 'Font Family',
- values: items,
- fixedWidth: true,
- onPostRender: createFontNameListBoxChangeHandler(items),
- onselect: function(e) {
- if (e.control.settings.value) {
- editor.execCommand('FontName', false, e.control.settings.value);
- }
- }
- };
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ type: 'listbox',
+ text: 'Font Family',
+ tooltip: 'Font Family',
+ values: items,
+ fixedWidth: true,
+ onPostRender: createFontNameListBoxChangeHandler(items),
+ onselect: function (e) {
+ if (e.control.settings.value) {
+ editor.execCommand('FontName', false, e.control.settings.value);
+ }
+ }
+ };
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addButton('fontsizeselect', function() {
- var items = [], defaultFontsizeFormats = '8pt 10pt 12pt 14pt 18pt 24pt 36pt';
- var fontsize_formats = editor.settings.fontsize_formats || defaultFontsizeFormats;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addButton('fontsizeselect', function () {
+ var items = [], defaultFontsizeFormats = '8pt 10pt 12pt 14pt 18pt 24pt 36pt';
+ var fontsizeFormats = editor.settings.fontsizeFormats || defaultFontsizeFormats;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(fontsize_formats.split(' '), function(item) {
- var text = item, value = item;
- // Allow text=value font sizes.
- var values = item.split('=');
- if (values.length > 1) {
- text = values[0];
- value = values[1];
- }
- items.push({text: text, value: value});
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(fontsizeFormats.split(' '), function (item) {
+ var text = item, value = item;
+ // Allow text=value font sizes.
+ var values = item.split('=');
+ if (values.length > 1) {
+ text = values[0];
+ value = values[1];
+ }
+ items.push({ text: text, value: value });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {
- type: 'listbox',
- text: 'Font Sizes',
- tooltip: 'Font Sizes',
- values: items,
- fixedWidth: true,
- onPostRender: createFontSizeListBoxChangeHandler(items),
- onclick: function(e) {
- if (e.control.settings.value) {
- editor.execCommand('FontSize', false, e.control.settings.value);
- }
- }
- };
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ type: 'listbox',
+ text: 'Font Sizes',
+ tooltip: 'Font Sizes',
+ values: items,
+ fixedWidth: true,
+ onPostRender: createFontSizeListBoxChangeHandler(items),
+ onclick: function (e) {
+ if (e.control.settings.value) {
+ editor.execCommand('FontSize', false, e.control.settings.value);
+ }
+ }
+ };
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editor.addMenuItem('formats', {
- text: 'Formats',
- menu: formatMenu
- });
- }
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editor.addMenuItem('formats', {
+ text: 'Formats',
+ menu: formatMenu
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/GridLayout.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {};
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * GridLayout.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -46368,223 +51319,225 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.GridLayout
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.AbsoluteLayout
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/GridLayout", [
- "tinymce/ui/AbsoluteLayout"
-], function(AbsoluteLayout) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.GridLayout',
+ [
+ "tinymce.core.ui.AbsoluteLayout"
+ ],
+ function (AbsoluteLayout) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return AbsoluteLayout.extend({
- /**
- * Recalculates the positions of the controls in the specified container.
- *
- * @method recalc
- * @param {tinymce.ui.Container} container Container instance to recalc.
- */
- recalc: function(container) {
- var settings, rows, cols, items, contLayoutRect, width, height, rect,
- ctrlLayoutRect, ctrl, x, y, posX, posY, ctrlSettings, contPaddingBox, align, spacingH, spacingV, alignH, alignV, maxX, maxY,
- colWidths = [], rowHeights = [], ctrlMinWidth, ctrlMinHeight, availableWidth, availableHeight, reverseRows, idx;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return AbsoluteLayout.extend({
+ /**
+ * Recalculates the positions of the controls in the specified container.
+ *
+ * @method recalc
+ * @param {tinymce.ui.Container} container Container instance to recalc.
+ */
+ recalc: function (container) {
+ var settings, rows, cols, items, contLayoutRect, width, height, rect,
+ ctrlLayoutRect, ctrl, x, y, posX, posY, ctrlSettings, contPaddingBox, align, spacingH, spacingV, alignH, alignV, maxX, maxY,
+ colWidths = [], rowHeights = [], ctrlMinWidth, ctrlMinHeight, availableWidth, availableHeight, reverseRows, idx;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Get layout settings
- settings = container.settings;
- items = container.items().filter(':visible');
- contLayoutRect = container.layoutRect();
- cols = settings.columns || Math.ceil(Math.sqrt(items.length));
- rows = Math.ceil(items.length / cols);
- spacingH = settings.spacingH || settings.spacing || 0;
- spacingV = settings.spacingV || settings.spacing || 0;
- alignH = settings.alignH || settings.align;
- alignV = settings.alignV || settings.align;
- contPaddingBox = container.paddingBox;
- reverseRows = 'reverseRows' in settings ? settings.reverseRows : container.isRtl();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get layout settings
+ settings = container.settings;
+ items = container.items().filter(':visible');
+ contLayoutRect = container.layoutRect();
+ cols = settings.columns || Math.ceil(Math.sqrt(items.length));
+ rows = Math.ceil(items.length / cols);
+ spacingH = settings.spacingH || settings.spacing || 0;
+ spacingV = settings.spacingV || settings.spacing || 0;
+ alignH = settings.alignH || settings.align;
+ alignV = settings.alignV || settings.align;
+ contPaddingBox = container.paddingBox;
+ reverseRows = 'reverseRows' in settings ? settings.reverseRows : container.isRtl();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (alignH && typeof alignH == "string") {
- alignH = [alignH];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (alignH && typeof alignH == "string") {
+ alignH = [alignH];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (alignV && typeof alignV == "string") {
- alignV = [alignV];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (alignV && typeof alignV == "string") {
+ alignV = [alignV];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Zero padd columnWidths
- for (x = 0; x < cols; x++) {
- colWidths.push(0);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Zero padd columnWidths
+ for (x = 0; x < cols; x++) {
+ colWidths.push(0);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Zero padd rowHeights
- for (y = 0; y < rows; y++) {
- rowHeights.push(0);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Zero padd rowHeights
+ for (y = 0; y < rows; y++) {
+ rowHeights.push(0);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Calculate columnWidths and rowHeights
- for (y = 0; y < rows; y++) {
- for (x = 0; x < cols; x++) {
- ctrl = items[y * cols + x];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Calculate columnWidths and rowHeights
+ for (y = 0; y < rows; y++) {
+ for (x = 0; x < cols; x++) {
+ ctrl = items[y * cols + x];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Out of bounds
- if (!ctrl) {
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Out of bounds
+ if (!ctrl) {
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ctrlLayoutRect = ctrl.layoutRect();
- ctrlMinWidth = ctrlLayoutRect.minW;
- ctrlMinHeight = ctrlLayoutRect.minH;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ctrlLayoutRect = ctrl.layoutRect();
+ ctrlMinWidth = ctrlLayoutRect.minW;
+ ctrlMinHeight = ctrlLayoutRect.minH;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- colWidths[x] = ctrlMinWidth > colWidths[x] ? ctrlMinWidth : colWidths[x];
- rowHeights[y] = ctrlMinHeight > rowHeights[y] ? ctrlMinHeight : rowHeights[y];
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ colWidths[x] = ctrlMinWidth > colWidths[x] ? ctrlMinWidth : colWidths[x];
+ rowHeights[y] = ctrlMinHeight > rowHeights[y] ? ctrlMinHeight : rowHeights[y];
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Calculate maxX
- availableWidth = contLayoutRect.innerW - contPaddingBox.left - contPaddingBox.right;
- for (maxX = 0, x = 0; x < cols; x++) {
- maxX += colWidths[x] + (x > 0 ? spacingH : 0);
- availableWidth -= (x > 0 ? spacingH : 0) + colWidths[x];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Calculate maxX
+ availableWidth = contLayoutRect.innerW - contPaddingBox.left - contPaddingBox.right;
+ for (maxX = 0, x = 0; x < cols; x++) {
+ maxX += colWidths[x] + (x > 0 ? spacingH : 0);
+ availableWidth -= (x > 0 ? spacingH : 0) + colWidths[x];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Calculate maxY
- availableHeight = contLayoutRect.innerH - contPaddingBox.top - contPaddingBox.bottom;
- for (maxY = 0, y = 0; y < rows; y++) {
- maxY += rowHeights[y] + (y > 0 ? spacingV : 0);
- availableHeight -= (y > 0 ? spacingV : 0) + rowHeights[y];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Calculate maxY
+ availableHeight = contLayoutRect.innerH - contPaddingBox.top - contPaddingBox.bottom;
+ for (maxY = 0, y = 0; y < rows; y++) {
+ maxY += rowHeights[y] + (y > 0 ? spacingV : 0);
+ availableHeight -= (y > 0 ? spacingV : 0) + rowHeights[y];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- maxX += contPaddingBox.left + contPaddingBox.right;
- maxY += contPaddingBox.top + contPaddingBox.bottom;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ maxX += contPaddingBox.left + contPaddingBox.right;
+ maxY += contPaddingBox.top + contPaddingBox.bottom;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Calculate minW/minH
- rect = {};
- rect.minW = maxX + (contLayoutRect.w - contLayoutRect.innerW);
- rect.minH = maxY + (contLayoutRect.h - contLayoutRect.innerH);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Calculate minW/minH
+ rect = {};
+ rect.minW = maxX + (contLayoutRect.w - contLayoutRect.innerW);
+ rect.minH = maxY + (contLayoutRect.h - contLayoutRect.innerH);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rect.contentW = rect.minW - contLayoutRect.deltaW;
- rect.contentH = rect.minH - contLayoutRect.deltaH;
- rect.minW = Math.min(rect.minW, contLayoutRect.maxW);
- rect.minH = Math.min(rect.minH, contLayoutRect.maxH);
- rect.minW = Math.max(rect.minW, contLayoutRect.startMinWidth);
- rect.minH = Math.max(rect.minH, contLayoutRect.startMinHeight);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rect.contentW = rect.minW - contLayoutRect.deltaW;
+ rect.contentH = rect.minH - contLayoutRect.deltaH;
+ rect.minW = Math.min(rect.minW, contLayoutRect.maxW);
+ rect.minH = Math.min(rect.minH, contLayoutRect.maxH);
+ rect.minW = Math.max(rect.minW, contLayoutRect.startMinWidth);
+ rect.minH = Math.max(rect.minH, contLayoutRect.startMinHeight);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Resize container container if minSize was changed
- if (contLayoutRect.autoResize && (rect.minW != contLayoutRect.minW || rect.minH != contLayoutRect.minH)) {
- rect.w = rect.minW;
- rect.h = rect.minH;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Resize container container if minSize was changed
+ if (contLayoutRect.autoResize && (rect.minW != contLayoutRect.minW || rect.minH != contLayoutRect.minH)) {
+ rect.w = rect.minW;
+ rect.h = rect.minH;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- container.layoutRect(rect);
- this.recalc(container);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ container.layoutRect(rect);
+ this.recalc(container);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Forced recalc for example if items are hidden/shown
- if (container._lastRect === null) {
- var parentCtrl = container.parent();
- if (parentCtrl) {
- parentCtrl._lastRect = null;
- parentCtrl.recalc();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Forced recalc for example if items are hidden/shown
+ if (container._lastRect === null) {
+ var parentCtrl = container.parent();
+ if (parentCtrl) {
+ parentCtrl._lastRect = null;
+ parentCtrl.recalc();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Update contentW/contentH so absEnd moves correctly
- if (contLayoutRect.autoResize) {
- rect = container.layoutRect(rect);
- rect.contentW = rect.minW - contLayoutRect.deltaW;
- rect.contentH = rect.minH - contLayoutRect.deltaH;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Update contentW/contentH so absEnd moves correctly
+ if (contLayoutRect.autoResize) {
+ rect = container.layoutRect(rect);
+ rect.contentW = rect.minW - contLayoutRect.deltaW;
+ rect.contentH = rect.minH - contLayoutRect.deltaH;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var flexV;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var flexV;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.packV == 'start') {
- flexV = 0;
- } else {
- flexV = availableHeight > 0 ? Math.floor(availableHeight / rows) : 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.packV == 'start') {
+ flexV = 0;
+ } else {
+ flexV = availableHeight > 0 ? Math.floor(availableHeight / rows) : 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Calculate totalFlex
- var totalFlex = 0;
- var flexWidths = settings.flexWidths;
- if (flexWidths) {
- for (x = 0; x < flexWidths.length; x++) {
- totalFlex += flexWidths[x];
- }
- } else {
- totalFlex = cols;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Calculate totalFlex
+ var totalFlex = 0;
+ var flexWidths = settings.flexWidths;
+ if (flexWidths) {
+ for (x = 0; x < flexWidths.length; x++) {
+ totalFlex += flexWidths[x];
+ }
+ } else {
+ totalFlex = cols;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Calculate new column widths based on flex values
- var ratio = availableWidth / totalFlex;
- for (x = 0; x < cols; x++) {
- colWidths[x] += flexWidths ? flexWidths[x] * ratio : ratio;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Calculate new column widths based on flex values
+ var ratio = availableWidth / totalFlex;
+ for (x = 0; x < cols; x++) {
+ colWidths[x] += flexWidths ? flexWidths[x] * ratio : ratio;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move/resize controls
- posY = contPaddingBox.top;
- for (y = 0; y < rows; y++) {
- posX = contPaddingBox.left;
- height = rowHeights[y] + flexV;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move/resize controls
+ posY = contPaddingBox.top;
+ for (y = 0; y < rows; y++) {
+ posX = contPaddingBox.left;
+ height = rowHeights[y] + flexV;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (x = 0; x < cols; x++) {
- if (reverseRows) {
- idx = y * cols + cols - 1 - x;
- } else {
- idx = y * cols + x;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (x = 0; x < cols; x++) {
+ if (reverseRows) {
+ idx = y * cols + cols - 1 - x;
+ } else {
+ idx = y * cols + x;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ctrl = items[idx];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ctrl = items[idx];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // No more controls to render then break
- if (!ctrl) {
- break;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // No more controls to render then break
+ if (!ctrl) {
+ break;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Get control settings and calculate x, y
- ctrlSettings = ctrl.settings;
- ctrlLayoutRect = ctrl.layoutRect();
- width = Math.max(colWidths[x], ctrlLayoutRect.startMinWidth);
- ctrlLayoutRect.x = posX;
- ctrlLayoutRect.y = posY;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get control settings and calculate x, y
+ ctrlSettings = ctrl.settings;
+ ctrlLayoutRect = ctrl.layoutRect();
+ width = Math.max(colWidths[x], ctrlLayoutRect.startMinWidth);
+ ctrlLayoutRect.x = posX;
+ ctrlLayoutRect.y = posY;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Align control horizontal
- align = ctrlSettings.alignH || (alignH ? (alignH[x] || alignH[0]) : null);
- if (align == "center") {
- ctrlLayoutRect.x = posX + (width / 2) - (ctrlLayoutRect.w / 2);
- } else if (align == "right") {
- ctrlLayoutRect.x = posX + width - ctrlLayoutRect.w;
- } else if (align == "stretch") {
- ctrlLayoutRect.w = width;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Align control horizontal
+ align = ctrlSettings.alignH || (alignH ? (alignH[x] || alignH[0]) : null);
+ if (align == "center") {
+ ctrlLayoutRect.x = posX + (width / 2) - (ctrlLayoutRect.w / 2);
+ } else if (align == "right") {
+ ctrlLayoutRect.x = posX + width - ctrlLayoutRect.w;
+ } else if (align == "stretch") {
+ ctrlLayoutRect.w = width;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Align control vertical
- align = ctrlSettings.alignV || (alignV ? (alignV[x] || alignV[0]) : null);
- if (align == "center") {
- ctrlLayoutRect.y = posY + (height / 2) - (ctrlLayoutRect.h / 2);
- } else if (align == "bottom") {
- ctrlLayoutRect.y = posY + height - ctrlLayoutRect.h;
- } else if (align == "stretch") {
- ctrlLayoutRect.h = height;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Align control vertical
+ align = ctrlSettings.alignV || (alignV ? (alignV[x] || alignV[0]) : null);
+ if (align == "center") {
+ ctrlLayoutRect.y = posY + (height / 2) - (ctrlLayoutRect.h / 2);
+ } else if (align == "bottom") {
+ ctrlLayoutRect.y = posY + height - ctrlLayoutRect.h;
+ } else if (align == "stretch") {
+ ctrlLayoutRect.h = height;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ctrl.layoutRect(ctrlLayoutRect);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ctrl.layoutRect(ctrlLayoutRect);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- posX += width + spacingH;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ posX += width + spacingH;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (ctrl.recalc) {
- ctrl.recalc();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (ctrl.recalc) {
+ ctrl.recalc();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- posY += height + spacingV;
- }
- }
- });
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ posY += height + spacingV;
+ }
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/Iframe.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Iframe.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -46601,78 +51554,80 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.Iframe
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Widget
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Iframe", [
- "tinymce/ui/Widget",
- "tinymce/util/Delay"
-], function(Widget, Delay) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Iframe',
+ [
+ "tinymce.core.ui.Widget",
+ "tinymce.core.util.Delay"
+ ],
+ function (Widget, Delay) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Widget.extend({
- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Widget.extend({
+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.classes.add('iframe');
- self.canFocus = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.classes.add('iframe');
+ self.canFocus = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /*eslint no-script-url:0 */
- return (
- '<iframe id="' + self._id + '" class="' + self.classes + '" tabindex="-1" src="' +
- (self.settings.url || "javascript:''") + '" frameborder="0"></iframe>'
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /*eslint no-script-url:0 */
+ return (
+ '<iframe id="' + self._id + '" class="' + self.classes + '" tabindex="-1" src="' +
+ (self.settings.url || "javascript:''") + '" frameborder="0"></iframe>'
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Setter for the iframe source.
- *
- * @method src
- * @param {String} src Source URL for iframe.
- */
- src: function(src) {
- this.getEl().src = src;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Setter for the iframe source.
+ *
+ * @method src
+ * @param {String} src Source URL for iframe.
+ */
+ src: function (src) {
+ this.getEl().src = src;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Inner HTML for the iframe.
- *
- * @method html
- * @param {String} html HTML string to set as HTML inside the iframe.
- * @param {function} callback Optional callback to execute when the iframe body is filled with contents.
- * @return {tinymce.ui.Iframe} Current iframe control.
- */
- html: function(html, callback) {
- var self = this, body = this.getEl().contentWindow.document.body;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Inner HTML for the iframe.
+ *
+ * @method html
+ * @param {String} html HTML string to set as HTML inside the iframe.
+ * @param {function} callback Optional callback to execute when the iframe body is filled with contents.
+ * @return {tinymce.ui.Iframe} Current iframe control.
+ */
+ html: function (html, callback) {
+ var self = this, body = this.getEl().contentWindow.document.body;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Wait for iframe to initialize IE 10 takes time
- if (!body) {
- Delay.setTimeout(function() {
- self.html(html);
- });
- } else {
- body.innerHTML = html;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Wait for iframe to initialize IE 10 takes time
+ if (!body) {
+ Delay.setTimeout(function () {
+ self.html(html);
+ });
+ } else {
+ body.innerHTML = html;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (callback) {
- callback();
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (callback) {
+ callback();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- }
- });
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/InfoBox.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * InfoBox.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -46685,90 +51640,92 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.InfoBox
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Widget
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/InfoBox", [
- "tinymce/ui/Widget"
-], function(Widget) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.InfoBox',
+ [
+ "tinymce.core.ui.Widget"
+ ],
+ function (Widget) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Widget.extend({
- /**
- * Constructs a instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- * @setting {Boolean} multiline Multiline label.
- */
- init: function(settings) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Widget.extend({
+ /**
+ * Constructs a instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ * @setting {Boolean} multiline Multiline label.
+ */
+ init: function (settings) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super(settings);
- self.classes.add('widget').add('infobox');
- self.canFocus = false;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super(settings);
+ self.classes.add('widget').add('infobox');
+ self.canFocus = false;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- severity: function(level) {
- this.classes.remove('error');
- this.classes.remove('warning');
- this.classes.remove('success');
- this.classes.add(level);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ severity: function (level) {
+ this.classes.remove('error');
+ this.classes.remove('warning');
+ this.classes.remove('success');
+ this.classes.add(level);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- help: function(state) {
- this.state.set('help', state);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ help: function (state) {
+ this.state.set('help', state);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this, prefix = self.classPrefix;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this, prefix = self.classPrefix;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<div id="' + self._id + '" class="' + self.classes + '">' +
- '<div id="' + self._id + '-body">' +
- self.encode(self.state.get('text')) +
- '<button role="button" tabindex="-1">' +
- '<i class="' + prefix + 'ico ' + prefix + 'i-help"></i>' +
- '</button>' +
- '</div>' +
- '</div>'
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<div id="' + self._id + '" class="' + self.classes + '">' +
+ '<div id="' + self._id + '-body">' +
+ self.encode(self.state.get('text')) +
+ '<button role="button" tabindex="-1">' +
+ '<i class="' + prefix + 'ico ' + prefix + 'i-help"></i>' +
+ '</button>' +
+ '</div>' +
+ '</div>'
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bindStates: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bindStates: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:text', function(e) {
- self.getEl('body').firstChild.data = self.encode(e.value);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:text', function (e) {
+ self.getEl('body').firstChild.data = self.encode(e.value);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.state.get('rendered')) {
- self.updateLayoutRect();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.state.get('rendered')) {
+ self.updateLayoutRect();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:help', function(e) {
- self.classes.toggle('has-help', e.value);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:help', function (e) {
+ self.classes.toggle('has-help', e.value);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.state.get('rendered')) {
- self.updateLayoutRect();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.state.get('rendered')) {
+ self.updateLayoutRect();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- }
- });
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/Label.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Label.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -46782,140 +51739,143 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.Label
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Widget
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Label", [
- "tinymce/ui/Widget",
- "tinymce/ui/DomUtils"
-], function(Widget, DomUtils) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Label',
+ [
+ "tinymce.core.ui.Widget",
+ "tinymce.core.ui.DomUtils"
+ ],
+ function (Widget, DomUtils) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Widget.extend({
- /**
- * Constructs a instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- * @setting {Boolean} multiline Multiline label.
- */
- init: function(settings) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Widget.extend({
+ /**
+ * Constructs a instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ * @setting {Boolean} multiline Multiline label.
+ */
+ init: function (settings) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super(settings);
- self.classes.add('widget').add('label');
- self.canFocus = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super(settings);
+ self.classes.add('widget').add('label');
+ self.canFocus = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.multiline) {
- self.classes.add('autoscroll');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.multiline) {
+ self.classes.add('autoscroll');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.strong) {
- self.classes.add('strong');
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.strong) {
+ self.classes.add('strong');
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Initializes the current controls layout rect.
- * This will be executed by the layout managers to determine the
- * default minWidth/minHeight etc.
- *
- * @method initLayoutRect
- * @return {Object} Layout rect instance.
- */
- initLayoutRect: function() {
- var self = this, layoutRect = self._super();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Initializes the current controls layout rect.
+ * This will be executed by the layout managers to determine the
+ * default minWidth/minHeight etc.
+ *
+ * @method initLayoutRect
+ * @return {Object} Layout rect instance.
+ */
+ initLayoutRect: function () {
+ var self = this, layoutRect = self._super();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.settings.multiline) {
- var size = DomUtils.getSize(self.getEl());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.settings.multiline) {
+ var size = DomUtils.getSize(self.getEl());
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Check if the text fits within maxW if not then try word wrapping it
- if (size.width > layoutRect.maxW) {
- layoutRect.minW = layoutRect.maxW;
- self.classes.add('multiline');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Check if the text fits within maxW if not then try word wrapping it
+ if (size.width > layoutRect.maxW) {
+ layoutRect.minW = layoutRect.maxW;
+ self.classes.add('multiline');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.getEl().style.width = layoutRect.minW + 'px';
- layoutRect.startMinH = layoutRect.h = layoutRect.minH = Math.min(layoutRect.maxH, DomUtils.getSize(self.getEl()).height);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.getEl().style.width = layoutRect.minW + 'px';
+ layoutRect.startMinH = layoutRect.h = layoutRect.minH = Math.min(layoutRect.maxH, DomUtils.getSize(self.getEl()).height);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return layoutRect;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return layoutRect;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Repaints the control after a layout operation.
- *
- * @method repaint
- */
- repaint: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Repaints the control after a layout operation.
+ *
+ * @method repaint
+ */
+ repaint: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.settings.multiline) {
- self.getEl().style.lineHeight = self.layoutRect().h + 'px';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.settings.multiline) {
+ self.getEl().style.lineHeight = self.layoutRect().h + 'px';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- severity: function(level) {
- this.classes.remove('error');
- this.classes.remove('warning');
- this.classes.remove('success');
- this.classes.add(level);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ severity: function (level) {
+ this.classes.remove('error');
+ this.classes.remove('warning');
+ this.classes.remove('success');
+ this.classes.add(level);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this, targetCtrl, forName, forId = self.settings.forId;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this, targetCtrl, forName, forId = self.settings.forId;
+ var text = self.settings.html ? self.settings.html : self.encode(self.state.get('text'));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!forId && (forName = self.settings.forName)) {
- targetCtrl = self.getRoot().find('#' + forName)[0];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!forId && (forName = self.settings.forName)) {
+ targetCtrl = self.getRoot().find('#' + forName)[0];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (targetCtrl) {
- forId = targetCtrl._id;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (targetCtrl) {
+ forId = targetCtrl._id;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (forId) {
- return (
- '<label id="' + self._id + '" class="' + self.classes + '"' + (forId ? ' for="' + forId + '"' : '') + '>' +
- self.encode(self.state.get('text')) +
- '</label>'
- );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (forId) {
+ return (
+ '<label id="' + self._id + '" class="' + self.classes + '"' + (forId ? ' for="' + forId + '"' : '') + '>' +
+ text +
+ '</label>'
+ );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<span id="' + self._id + '" class="' + self.classes + '">' +
- self.encode(self.state.get('text')) +
- '</span>'
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<span id="' + self._id + '" class="' + self.classes + '">' +
+ text +
+ '</span>'
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bindStates: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bindStates: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:text', function(e) {
- self.innerHtml(self.encode(e.value));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:text', function (e) {
+ self.innerHtml(self.encode(e.value));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.state.get('rendered')) {
- self.updateLayoutRect();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.state.get('rendered')) {
+ self.updateLayoutRect();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- }
- });
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/Toolbar.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Toolbar.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -46927,54 +51887,55 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.Toolbar
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Container
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Toolbar", [
- "tinymce/ui/Container"
-], function(Container) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Toolbar',
+ [
+ "tinymce.core.ui.Container"
+ ],
+ function (Container) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Container.extend({
- Defaults: {
- role: 'toolbar',
- layout: 'flow'
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Container.extend({
+ Defaults: {
+ role: 'toolbar',
+ layout: 'flow'
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- */
- init: function(settings) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ */
+ init: function (settings) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super(settings);
- self.classes.add('toolbar');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super(settings);
+ self.classes.add('toolbar');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Called after the control has been rendered.
- *
- * @method postRender
- */
- postRender: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Called after the control has been rendered.
+ *
+ * @method postRender
+ */
+ postRender: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.items().each(function(ctrl) {
- ctrl.classes.add('toolbar-item');
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.items().each(function (ctrl) {
+ ctrl.classes.add('toolbar-item');
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/MenuBar.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * MenuBar.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -46987,30 +51948,31 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.MenuBar
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Container
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/MenuBar", [
- "tinymce/ui/Toolbar"
-], function(Toolbar) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.MenuBar',
+ [
+ "tinymce.core.ui.Toolbar"
+ ],
+ function (Toolbar) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Toolbar.extend({
- Defaults: {
- role: 'menubar',
- containerCls: 'menubar',
- ariaRoot: true,
- defaults: {
- type: 'menubutton'
- }
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/MenuButton.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Toolbar.extend({
+ Defaults: {
+ role: 'menubar',
+ containerCls: 'menubar',
+ ariaRoot: true,
+ defaults: {
+ type: 'menubutton'
+ }
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * MenuButton.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -47023,267 +51985,269 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.MenuButton
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Button
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/MenuButton", [
- "tinymce/ui/Button",
- "tinymce/ui/Factory",
- "tinymce/ui/MenuBar"
-], function(Button, Factory, MenuBar) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.MenuButton',
+ [
+ "tinymce.core.ui.Button",
+ "tinymce.core.ui.Factory",
+ "tinymce.core.ui.MenuBar"
+ ],
+ function (Button, Factory, MenuBar) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // TODO: Maybe add as some global function
- function isChildOf(node, parent) {
- while (node) {
- if (parent === node) {
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // TODO: Maybe add as some global function
+ function isChildOf(node, parent) {
+ while (node) {
+ if (parent === node) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.parentNode;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node.parentNode;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var MenuButton = Button.extend({
- /**
- * Constructs a instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- */
- init: function(settings) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var MenuButton = Button.extend({
+ /**
+ * Constructs a instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ */
+ init: function (settings) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._renderOpen = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._renderOpen = true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super(settings);
- settings = self.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super(settings);
+ settings = self.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.classes.add('menubtn');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.classes.add('menubtn');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.fixedWidth) {
- self.classes.add('fixed-width');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.fixedWidth) {
+ self.classes.add('fixed-width');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.aria('haspopup', true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.aria('haspopup', true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.set('menu', settings.menu || self.render());
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.set('menu', settings.menu || self.render());
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Shows the menu for the button.
- *
- * @method showMenu
- */
- showMenu: function(toggle) {
- var self = this, menu;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Shows the menu for the button.
+ *
+ * @method showMenu
+ */
+ showMenu: function (toggle) {
+ var self = this, menu;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.menu && self.menu.visible() && toggle !== false) {
- return self.hideMenu();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.menu && self.menu.visible() && toggle !== false) {
+ return self.hideMenu();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.menu) {
- menu = self.state.get('menu') || [];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.menu) {
+ menu = self.state.get('menu') || [];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Is menu array then auto constuct menu control
- if (menu.length) {
- menu = {
- type: 'menu',
- items: menu
- };
- } else {
- menu.type = menu.type || 'menu';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Is menu array then auto constuct menu control
+ if (menu.length) {
+ menu = {
+ type: 'menu',
+ items: menu
+ };
+ } else {
+ menu.type = menu.type || 'menu';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!menu.renderTo) {
- self.menu = Factory.create(menu).parent(self).renderTo();
- } else {
- self.menu = menu.parent(self).show().renderTo();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!menu.renderTo) {
+ self.menu = Factory.create(menu).parent(self).renderTo();
+ } else {
+ self.menu = menu.parent(self).show().renderTo();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.fire('createmenu');
- self.menu.reflow();
- self.menu.on('cancel', function(e) {
- if (e.control.parent() === self.menu) {
- e.stopPropagation();
- self.focus();
- self.hideMenu();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.fire('createmenu');
+ self.menu.reflow();
+ self.menu.on('cancel', function (e) {
+ if (e.control.parent() === self.menu) {
+ e.stopPropagation();
+ self.focus();
+ self.hideMenu();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move focus to button when a menu item is selected/clicked
- self.menu.on('select', function() {
- self.focus();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move focus to button when a menu item is selected/clicked
+ self.menu.on('select', function () {
+ self.focus();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.menu.on('show hide', function(e) {
- if (e.control == self.menu) {
- self.activeMenu(e.type == 'show');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.menu.on('show hide', function (e) {
+ if (e.control == self.menu) {
+ self.activeMenu(e.type == 'show');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.aria('expanded', e.type == 'show');
- }).fire('show');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.aria('expanded', e.type == 'show');
+ }).fire('show');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.menu.show();
- self.menu.layoutRect({w: self.layoutRect().w});
- self.menu.moveRel(self.getEl(), self.isRtl() ? ['br-tr', 'tr-br'] : ['bl-tl', 'tl-bl']);
- self.fire('showmenu');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.menu.show();
+ self.menu.layoutRect({ w: self.layoutRect().w });
+ self.menu.moveRel(self.getEl(), self.isRtl() ? ['br-tr', 'tr-br'] : ['bl-tl', 'tl-bl']);
+ self.fire('showmenu');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Hides the menu for the button.
- *
- * @method hideMenu
- */
- hideMenu: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Hides the menu for the button.
+ *
+ * @method hideMenu
+ */
+ hideMenu: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.menu) {
- self.menu.items().each(function(item) {
- if (item.hideMenu) {
- item.hideMenu();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.menu) {
+ self.menu.items().each(function (item) {
+ if (item.hideMenu) {
+ item.hideMenu();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.menu.hide();
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.menu.hide();
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets the active menu state.
- *
- * @private
- */
- activeMenu: function(state) {
- this.classes.toggle('active', state);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets the active menu state.
+ *
+ * @private
+ */
+ activeMenu: function (state) {
+ this.classes.toggle('active', state);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this, id = self._id, prefix = self.classPrefix;
- var icon = self.settings.icon, image, text = self.state.get('text'),
- textHtml = '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this, id = self._id, prefix = self.classPrefix;
+ var icon = self.settings.icon, image, text = self.state.get('text'),
+ textHtml = '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- image = self.settings.image;
- if (image) {
- icon = 'none';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ image = self.settings.image;
+ if (image) {
+ icon = 'none';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Support for [high dpi, low dpi] image sources
- if (typeof image != "string") {
- image = window.getSelection ? image[0] : image[1];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Support for [high dpi, low dpi] image sources
+ if (typeof image != "string") {
+ image = window.getSelection ? image[0] : image[1];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- image = ' style="background-image: url(\'' + image + '\')"';
- } else {
- image = '';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ image = ' style="background-image: url(\'' + image + '\')"';
+ } else {
+ image = '';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (text) {
- self.classes.add('btn-has-text');
- textHtml = '<span class="' + prefix + 'txt">' + self.encode(text) + '</span>';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (text) {
+ self.classes.add('btn-has-text');
+ textHtml = '<span class="' + prefix + 'txt">' + self.encode(text) + '</span>';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- icon = self.settings.icon ? prefix + 'ico ' + prefix + 'i-' + icon : '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ icon = self.settings.icon ? prefix + 'ico ' + prefix + 'i-' + icon : '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.aria('role', self.parent() instanceof MenuBar ? 'menuitem' : 'button');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.aria('role', self.parent() instanceof MenuBar ? 'menuitem' : 'button');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<div id="' + id + '" class="' + self.classes + '" tabindex="-1" aria-labelledby="' + id + '">' +
- '<button id="' + id + '-open" role="presentation" type="button" tabindex="-1">' +
- (icon ? '<i class="' + icon + '"' + image + '></i>' : '') +
- textHtml +
- ' <i class="' + prefix + 'caret"></i>' +
- '</button>' +
- '</div>'
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<div id="' + id + '" class="' + self.classes + '" tabindex="-1" aria-labelledby="' + id + '">' +
+ '<button id="' + id + '-open" role="presentation" type="button" tabindex="-1">' +
+ (icon ? '<i class="' + icon + '"' + image + '></i>' : '') +
+ textHtml +
+ ' <i class="' + prefix + 'caret"></i>' +
+ '</button>' +
+ '</div>'
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Gets invoked after the control has been rendered.
- *
- * @method postRender
- */
- postRender: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Gets invoked after the control has been rendered.
+ *
+ * @method postRender
+ */
+ postRender: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('click', function(e) {
- if (e.control === self && isChildOf(e.target, self.getEl())) {
- self.focus();
- self.showMenu(!e.aria);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('click', function (e) {
+ if (e.control === self && isChildOf(e.target, self.getEl())) {
+ self.focus();
+ self.showMenu(!e.aria);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.aria) {
- self.menu.items().filter(':visible')[0].focus();
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.aria) {
+ self.menu.items().filter(':visible')[0].focus();
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('mouseenter', function(e) {
- var overCtrl = e.control, parent = self.parent(), hasVisibleSiblingMenu;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('mouseenter', function (e) {
+ var overCtrl = e.control, parent = self.parent(), hasVisibleSiblingMenu;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (overCtrl && parent && overCtrl instanceof MenuButton && overCtrl.parent() == parent) {
- parent.items().filter('MenuButton').each(function(ctrl) {
- if (ctrl.hideMenu && ctrl != overCtrl) {
- if (ctrl.menu && ctrl.menu.visible()) {
- hasVisibleSiblingMenu = true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (overCtrl && parent && overCtrl instanceof MenuButton && overCtrl.parent() == parent) {
+ parent.items().filter('MenuButton').each(function (ctrl) {
+ if (ctrl.hideMenu && ctrl != overCtrl) {
+ if (ctrl.menu && ctrl.menu.visible()) {
+ hasVisibleSiblingMenu = true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ctrl.hideMenu();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ctrl.hideMenu();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (hasVisibleSiblingMenu) {
- overCtrl.focus(); // Fix for: #5887
- overCtrl.showMenu();
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (hasVisibleSiblingMenu) {
+ overCtrl.focus(); // Fix for: #5887
+ overCtrl.showMenu();
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bindStates: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bindStates: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:menu', function() {
- if (self.menu) {
- self.menu.remove();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:menu', function () {
+ if (self.menu) {
+ self.menu.remove();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.menu = null;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.menu = null;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes the control and it's menus.
- *
- * @method remove
- */
- remove: function() {
- this._super();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes the control and it's menus.
+ *
+ * @method remove
+ */
+ remove: function () {
+ this._super();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.menu) {
- this.menu.remove();
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.menu) {
+ this.menu.remove();
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return MenuButton;
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return MenuButton;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/MenuItem.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * MenuItem.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -47296,359 +52260,361 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.MenuItem
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Control
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/MenuItem", [
- "tinymce/ui/Widget",
- "tinymce/ui/Factory",
- "tinymce/Env",
- "tinymce/util/Delay"
-], function(Widget, Factory, Env, Delay) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.MenuItem',
+ [
+ "tinymce.core.ui.Widget",
+ "tinymce.core.ui.Factory",
+ "tinymce.core.Env",
+ "tinymce.core.util.Delay"
+ ],
+ function (Widget, Factory, Env, Delay) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Widget.extend({
- Defaults: {
- border: 0,
- role: 'menuitem'
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Widget.extend({
+ Defaults: {
+ border: 0,
+ role: 'menuitem'
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- * @setting {Boolean} selectable Selectable menu.
- * @setting {Array} menu Submenu array with items.
- * @setting {String} shortcut Shortcut to display for menu item. Example: Ctrl+X
- */
- init: function(settings) {
- var self = this, text;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ * @setting {Boolean} selectable Selectable menu.
+ * @setting {Array} menu Submenu array with items.
+ * @setting {String} shortcut Shortcut to display for menu item. Example: Ctrl+X
+ */
+ init: function (settings) {
+ var self = this, text;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super(settings);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super(settings);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- settings = self.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ settings = self.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.classes.add('menu-item');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.classes.add('menu-item');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.menu) {
- self.classes.add('menu-item-expand');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.menu) {
+ self.classes.add('menu-item-expand');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.preview) {
- self.classes.add('menu-item-preview');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.preview) {
+ self.classes.add('menu-item-preview');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- text = self.state.get('text');
- if (text === '-' || text === '|') {
- self.classes.add('menu-item-sep');
- self.aria('role', 'separator');
- self.state.set('text', '-');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ text = self.state.get('text');
+ if (text === '-' || text === '|') {
+ self.classes.add('menu-item-sep');
+ self.aria('role', 'separator');
+ self.state.set('text', '-');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.selectable) {
- self.aria('role', 'menuitemcheckbox');
- self.classes.add('menu-item-checkbox');
- settings.icon = 'selected';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.selectable) {
+ self.aria('role', 'menuitemcheckbox');
+ self.classes.add('menu-item-checkbox');
+ settings.icon = 'selected';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!settings.preview && !settings.selectable) {
- self.classes.add('menu-item-normal');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!settings.preview && !settings.selectable) {
+ self.classes.add('menu-item-normal');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('mousedown', function(e) {
- e.preventDefault();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('mousedown', function (e) {
+ e.preventDefault();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.menu && !settings.ariaHideMenu) {
- self.aria('haspopup', true);
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.menu && !settings.ariaHideMenu) {
+ self.aria('haspopup', true);
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Returns true/false if the menuitem has sub menu.
- *
- * @method hasMenus
- * @return {Boolean} True/false state if it has submenu.
- */
- hasMenus: function() {
- return !!this.settings.menu;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Returns true/false if the menuitem has sub menu.
+ *
+ * @method hasMenus
+ * @return {Boolean} True/false state if it has submenu.
+ */
+ hasMenus: function () {
+ return !!this.settings.menu;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Shows the menu for the menu item.
- *
- * @method showMenu
- */
- showMenu: function() {
- var self = this, settings = self.settings, menu, parent = self.parent();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Shows the menu for the menu item.
+ *
+ * @method showMenu
+ */
+ showMenu: function () {
+ var self = this, settings = self.settings, menu, parent = self.parent();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- parent.items().each(function(ctrl) {
- if (ctrl !== self) {
- ctrl.hideMenu();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parent.items().each(function (ctrl) {
+ if (ctrl !== self) {
+ ctrl.hideMenu();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.menu) {
- menu = self.menu;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.menu) {
+ menu = self.menu;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!menu) {
- menu = settings.menu;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!menu) {
+ menu = settings.menu;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Is menu array then auto constuct menu control
- if (menu.length) {
- menu = {
- type: 'menu',
- items: menu
- };
- } else {
- menu.type = menu.type || 'menu';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Is menu array then auto constuct menu control
+ if (menu.length) {
+ menu = {
+ type: 'menu',
+ items: menu
+ };
+ } else {
+ menu.type = menu.type || 'menu';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (parent.settings.itemDefaults) {
- menu.itemDefaults = parent.settings.itemDefaults;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (parent.settings.itemDefaults) {
+ menu.itemDefaults = parent.settings.itemDefaults;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- menu = self.menu = Factory.create(menu).parent(self).renderTo();
- menu.reflow();
- menu.on('cancel', function(e) {
- e.stopPropagation();
- self.focus();
- menu.hide();
- });
- menu.on('show hide', function(e) {
- if (e.control.items) {
- e.control.items().each(function(ctrl) {
- ctrl.active(ctrl.settings.selected);
- });
- }
- }).fire('show');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ menu = self.menu = Factory.create(menu).parent(self).renderTo();
+ menu.reflow();
+ menu.on('cancel', function (e) {
+ e.stopPropagation();
+ self.focus();
+ menu.hide();
+ });
+ menu.on('show hide', function (e) {
+ if (e.control.items) {
+ e.control.items().each(function (ctrl) {
+ ctrl.active(ctrl.settings.selected);
+ });
+ }
+ }).fire('show');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- menu.on('hide', function(e) {
- if (e.control === menu) {
- self.classes.remove('selected');
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ menu.on('hide', function (e) {
+ if (e.control === menu) {
+ self.classes.remove('selected');
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- menu.submenu = true;
- } else {
- menu.show();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ menu.submenu = true;
+ } else {
+ menu.show();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- menu._parentMenu = parent;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ menu._parentMenu = parent;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- menu.classes.add('menu-sub');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ menu.classes.add('menu-sub');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var rel = menu.testMoveRel(
- self.getEl(),
- self.isRtl() ? ['tl-tr', 'bl-br', 'tr-tl', 'br-bl'] : ['tr-tl', 'br-bl', 'tl-tr', 'bl-br']
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var rel = menu.testMoveRel(
+ self.getEl(),
+ self.isRtl() ? ['tl-tr', 'bl-br', 'tr-tl', 'br-bl'] : ['tr-tl', 'br-bl', 'tl-tr', 'bl-br']
+ );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- menu.moveRel(self.getEl(), rel);
- menu.rel = rel;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ menu.moveRel(self.getEl(), rel);
+ menu.rel = rel;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rel = 'menu-sub-' + rel;
- menu.classes.remove(menu._lastRel).add(rel);
- menu._lastRel = rel;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rel = 'menu-sub-' + rel;
+ menu.classes.remove(menu._lastRel).add(rel);
+ menu._lastRel = rel;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.classes.add('selected');
- self.aria('expanded', true);
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.classes.add('selected');
+ self.aria('expanded', true);
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Hides the menu for the menu item.
- *
- * @method hideMenu
- */
- hideMenu: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Hides the menu for the menu item.
+ *
+ * @method hideMenu
+ */
+ hideMenu: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.menu) {
- self.menu.items().each(function(item) {
- if (item.hideMenu) {
- item.hideMenu();
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.menu) {
+ self.menu.items().each(function (item) {
+ if (item.hideMenu) {
+ item.hideMenu();
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.menu.hide();
- self.aria('expanded', false);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.menu.hide();
+ self.aria('expanded', false);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this, id = self._id, settings = self.settings, prefix = self.classPrefix, text = self.state.get('text');
- var icon = self.settings.icon, image = '', shortcut = settings.shortcut;
- var url = self.encode(settings.url), iconHtml = '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this, id = self._id, settings = self.settings, prefix = self.classPrefix, text = self.state.get('text');
+ var icon = self.settings.icon, image = '', shortcut = settings.shortcut;
+ var url = self.encode(settings.url), iconHtml = '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Converts shortcut format to Mac/PC variants
- function convertShortcut(shortcut) {
- var i, value, replace = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Converts shortcut format to Mac/PC variants
+ function convertShortcut(shortcut) {
+ var i, value, replace = {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (Env.mac) {
- replace = {
- alt: '⌥',
- ctrl: '⌘',
- shift: '⇧',
- meta: '⌘'
- };
- } else {
- replace = {
- meta: 'Ctrl'
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (Env.mac) {
+ replace = {
+ alt: '⌥',
+ ctrl: '⌘',
+ shift: '⇧',
+ meta: '⌘'
+ };
+ } else {
+ replace = {
+ meta: 'Ctrl'
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- shortcut = shortcut.split('+');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ shortcut = shortcut.split('+');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i = 0; i < shortcut.length; i++) {
- value = replace[shortcut[i].toLowerCase()];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0; i < shortcut.length; i++) {
+ value = replace[shortcut[i].toLowerCase()];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value) {
- shortcut[i] = value;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value) {
+ shortcut[i] = value;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return shortcut.join('+');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return shortcut.join('+');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function escapeRegExp(str) {
- return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function escapeRegExp(str) {
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function markMatches(text) {
- var match = settings.match || '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function markMatches(text) {
+ var match = settings.match || '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return match ? text.replace(new RegExp(escapeRegExp(match), 'gi'), function (match) {
- return '!mce~match[' + match + ']mce~match!';
- }) : text;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return match ? text.replace(new RegExp(escapeRegExp(match), 'gi'), function (match) {
+ return '!mce~match[' + match + ']mce~match!';
+ }) : text;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function boldMatches(text) {
- return text.
- replace(new RegExp(escapeRegExp('!mce~match['), 'g'), '<b>').
- replace(new RegExp(escapeRegExp(']mce~match!'), 'g'), '</b>');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function boldMatches(text) {
+ return text.
+ replace(new RegExp(escapeRegExp('!mce~match['), 'g'), '<b>').
+ replace(new RegExp(escapeRegExp(']mce~match!'), 'g'), '</b>');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (icon) {
- self.parent().classes.add('menu-has-icons');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (icon) {
+ self.parent().classes.add('menu-has-icons');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.image) {
- image = ' style="background-image: url(\'' + settings.image + '\')"';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.image) {
+ image = ' style="background-image: url(\'' + settings.image + '\')"';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (shortcut) {
- shortcut = convertShortcut(shortcut);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (shortcut) {
+ shortcut = convertShortcut(shortcut);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- icon = prefix + 'ico ' + prefix + 'i-' + (self.settings.icon || 'none');
- iconHtml = (text !== '-' ? '<i class="' + icon + '"' + image + '></i>\u00a0' : '');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ icon = prefix + 'ico ' + prefix + 'i-' + (self.settings.icon || 'none');
+ iconHtml = (text !== '-' ? '<i class="' + icon + '"' + image + '></i>\u00a0' : '');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- text = boldMatches(self.encode(markMatches(text)));
- url = boldMatches(self.encode(markMatches(url)));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ text = boldMatches(self.encode(markMatches(text)));
+ url = boldMatches(self.encode(markMatches(url)));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<div id="' + id + '" class="' + self.classes + '" tabindex="-1">' +
- iconHtml +
- (text !== '-' ? '<span id="' + id + '-text" class="' + prefix + 'text">' + text + '</span>' : '') +
- (shortcut ? '<div id="' + id + '-shortcut" class="' + prefix + 'menu-shortcut">' + shortcut + '</div>' : '') +
- (settings.menu ? '<div class="' + prefix + 'caret"></div>' : '') +
- (url ? '<div class="' + prefix + 'menu-item-link">' + url + '</div>' : '') +
- '</div>'
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<div id="' + id + '" class="' + self.classes + '" tabindex="-1">' +
+ iconHtml +
+ (text !== '-' ? '<span id="' + id + '-text" class="' + prefix + 'text">' + text + '</span>' : '') +
+ (shortcut ? '<div id="' + id + '-shortcut" class="' + prefix + 'menu-shortcut">' + shortcut + '</div>' : '') +
+ (settings.menu ? '<div class="' + prefix + 'caret"></div>' : '') +
+ (url ? '<div class="' + prefix + 'menu-item-link">' + url + '</div>' : '') +
+ '</div>'
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Gets invoked after the control has been rendered.
- *
- * @method postRender
- */
- postRender: function() {
- var self = this, settings = self.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Gets invoked after the control has been rendered.
+ *
+ * @method postRender
+ */
+ postRender: function () {
+ var self = this, settings = self.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var textStyle = settings.textStyle;
- if (typeof textStyle == "function") {
- textStyle = textStyle.call(this);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var textStyle = settings.textStyle;
+ if (typeof textStyle == "function") {
+ textStyle = textStyle.call(this);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (textStyle) {
- var textElm = self.getEl('text');
- if (textElm) {
- textElm.setAttribute('style', textStyle);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (textStyle) {
+ var textElm = self.getEl('text');
+ if (textElm) {
+ textElm.setAttribute('style', textStyle);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('mouseenter click', function(e) {
- if (e.control === self) {
- if (!settings.menu && e.type === 'click') {
- self.fire('select');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('mouseenter click', function (e) {
+ if (e.control === self) {
+ if (!settings.menu && e.type === 'click') {
+ self.fire('select');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Edge will crash if you stress it see #2660
- Delay.requestAnimationFrame(function() {
- self.parent().hideAll();
- });
- } else {
- self.showMenu();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Edge will crash if you stress it see #2660
+ Delay.requestAnimationFrame(function () {
+ self.parent().hideAll();
+ });
+ } else {
+ self.showMenu();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.aria) {
- self.menu.focus(true);
- }
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.aria) {
+ self.menu.focus(true);
+ }
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- hover: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ hover: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.parent().items().each(function(ctrl) {
- ctrl.classes.remove('selected');
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.parent().items().each(function (ctrl) {
+ ctrl.classes.remove('selected');
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.classes.toggle('selected', true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.classes.toggle('selected', true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- active: function(state) {
- if (typeof state != "undefined") {
- this.aria('checked', state);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ active: function (state) {
+ if (typeof state != "undefined") {
+ this.aria('checked', state);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this._super(state);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this._super(state);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Removes the control and it's menus.
- *
- * @method remove
- */
- remove: function() {
- this._super();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Removes the control and it's menus.
+ *
+ * @method remove
+ */
+ remove: function () {
+ this._super();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.menu) {
- this.menu.remove();
- }
- }
- });
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.menu) {
+ this.menu.remove();
+ }
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/Throbber.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Throbber.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -47660,86 +52626,88 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @-x-less Throbber.less
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.Throbber
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Throbber", [
- "tinymce/dom/DomQuery",
- "tinymce/ui/Control",
- "tinymce/util/Delay"
-], function($, Control, Delay) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Throbber',
+ [
+ "tinymce.core.dom.DomQuery",
+ "tinymce.core.ui.Control",
+ "tinymce.core.util.Delay"
+ ],
+ function ($, Control, Delay) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a new throbber.
- *
- * @constructor
- * @param {Element} elm DOM Html element to display throbber in.
- * @param {Boolean} inline Optional true/false state if the throbber should be appended to end of element for infinite scroll.
- */
- return function(elm, inline) {
- var self = this, state, classPrefix = Control.classPrefix, timer;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a new throbber.
+ *
+ * @constructor
+ * @param {Element} elm DOM Html element to display throbber in.
+ * @param {Boolean} inline Optional true/false state if the throbber should be appended to end of element for infinite scroll.
+ */
+ return function (elm, inline) {
+ var self = this, state, classPrefix = Control.classPrefix, timer;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Shows the throbber.
- *
- * @method show
- * @param {Number} [time] Time to wait before showing.
- * @param {function} [callback] Optional callback to execute when the throbber is shown.
- * @return {tinymce.ui.Throbber} Current throbber instance.
- */
- self.show = function(time, callback) {
- function render() {
- if (state) {
- $(elm).append(
- '<div class="' + classPrefix + 'throbber' + (inline ? ' ' + classPrefix + 'throbber-inline' : '') + '"></div>'
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Shows the throbber.
+ *
+ * @method show
+ * @param {Number} [time] Time to wait before showing.
+ * @param {function} [callback] Optional callback to execute when the throbber is shown.
+ * @return {tinymce.ui.Throbber} Current throbber instance.
+ */
+ self.show = function (time, callback) {
+ function render() {
+ if (state) {
+ $(elm).append(
+ '<div class="' + classPrefix + 'throbber' + (inline ? ' ' + classPrefix + 'throbber-inline' : '') + '"></div>'
+ );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (callback) {
- callback();
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (callback) {
+ callback();
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.hide();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.hide();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- state = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ state = true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (time) {
- timer = Delay.setTimeout(render, time);
- } else {
- render();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (time) {
+ timer = Delay.setTimeout(render, time);
+ } else {
+ render();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Hides the throbber.
- *
- * @method hide
- * @return {tinymce.ui.Throbber} Current throbber instance.
- */
- self.hide = function() {
- var child = elm.lastChild;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Hides the throbber.
+ *
+ * @method hide
+ * @return {tinymce.ui.Throbber} Current throbber instance.
+ */
+ self.hide = function () {
+ var child = elm.lastChild;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Delay.clearTimeout(timer);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Delay.clearTimeout(timer);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (child && child.className.indexOf('throbber') != -1) {
- child.parentNode.removeChild(child);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (child && child.className.indexOf('throbber') != -1) {
+ child.parentNode.removeChild(child);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- state = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ state = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- };
- };
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ };
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/Menu.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Menu.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -47752,192 +52720,194 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.Menu
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.FloatPanel
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Menu", [
- "tinymce/ui/FloatPanel",
- "tinymce/ui/MenuItem",
- "tinymce/ui/Throbber",
- "tinymce/util/Tools"
-], function(FloatPanel, MenuItem, Throbber, Tools) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Menu',
+ [
+ "tinymce.core.ui.FloatPanel",
+ "tinymce.core.ui.MenuItem",
+ "tinymce.core.ui.Throbber",
+ "tinymce.core.util.Tools"
+ ],
+ function (FloatPanel, MenuItem, Throbber, Tools) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return FloatPanel.extend({
- Defaults: {
- defaultType: 'menuitem',
- border: 1,
- layout: 'stack',
- role: 'application',
- bodyRole: 'menu',
- ariaRoot: true
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return FloatPanel.extend({
+ Defaults: {
+ defaultType: 'menuitem',
+ border: 1,
+ layout: 'stack',
+ role: 'application',
+ bodyRole: 'menu',
+ ariaRoot: true
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Constructs a instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- */
- init: function(settings) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Constructs a instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ */
+ init: function (settings) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- settings.autohide = true;
- settings.constrainToViewport = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ settings.autohide = true;
+ settings.constrainToViewport = true;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof settings.items === 'function') {
- settings.itemsFactory = settings.items;
- settings.items = [];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof settings.items === 'function') {
+ settings.itemsFactory = settings.items;
+ settings.items = [];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.itemDefaults) {
- var items = settings.items, i = items.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.itemDefaults) {
+ var items = settings.items, i = items.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- items[i] = Tools.extend({}, settings.itemDefaults, items[i]);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ items[i] = Tools.extend({}, settings.itemDefaults, items[i]);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super(settings);
- self.classes.add('menu');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super(settings);
+ self.classes.add('menu');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Repaints the control after a layout operation.
- *
- * @method repaint
- */
- repaint: function() {
- this.classes.toggle('menu-align', true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Repaints the control after a layout operation.
+ *
+ * @method repaint
+ */
+ repaint: function () {
+ this.classes.toggle('menu-align', true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this._super();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this._super();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.getEl().style.height = '';
- this.getEl('body').style.height = '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.getEl().style.height = '';
+ this.getEl('body').style.height = '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Hides/closes the menu.
- *
- * @method cancel
- */
- cancel: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Hides/closes the menu.
+ *
+ * @method cancel
+ */
+ cancel: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.hideAll();
- self.fire('select');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.hideAll();
+ self.fire('select');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Loads new items from the factory items function.
- *
- * @method load
- */
- load: function() {
- var self = this, time, factory;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Loads new items from the factory items function.
+ *
+ * @method load
+ */
+ load: function () {
+ var self = this, time, factory;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function hideThrobber() {
- if (self.throbber) {
- self.throbber.hide();
- self.throbber = null;
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function hideThrobber() {
+ if (self.throbber) {
+ self.throbber.hide();
+ self.throbber = null;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- factory = self.settings.itemsFactory;
- if (!factory) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ factory = self.settings.itemsFactory;
+ if (!factory) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!self.throbber) {
- self.throbber = new Throbber(self.getEl('body'), true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!self.throbber) {
+ self.throbber = new Throbber(self.getEl('body'), true);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.items().length === 0) {
- self.throbber.show();
- self.fire('loading');
- } else {
- self.throbber.show(100, function() {
- self.items().remove();
- self.fire('loading');
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.items().length === 0) {
+ self.throbber.show();
+ self.fire('loading');
+ } else {
+ self.throbber.show(100, function () {
+ self.items().remove();
+ self.fire('loading');
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('hide close', hideThrobber);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('hide close', hideThrobber);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.requestTime = time = new Date().getTime();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.requestTime = time = new Date().getTime();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.settings.itemsFactory(function(items) {
- if (items.length === 0) {
- self.hide();
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.settings.itemsFactory(function (items) {
+ if (items.length === 0) {
+ self.hide();
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.requestTime !== time) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.requestTime !== time) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.getEl().style.width = '';
- self.getEl('body').style.width = '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.getEl().style.width = '';
+ self.getEl('body').style.width = '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- hideThrobber();
- self.items().remove();
- self.getEl('body').innerHTML = '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ hideThrobber();
+ self.items().remove();
+ self.getEl('body').innerHTML = '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.add(items);
- self.renderNew();
- self.fire('loaded');
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.add(items);
+ self.renderNew();
+ self.fire('loaded');
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Hide menu and all sub menus.
- *
- * @method hideAll
- */
- hideAll: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Hide menu and all sub menus.
+ *
+ * @method hideAll
+ */
+ hideAll: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.find('menuitem').exec('hideMenu');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.find('menuitem').exec('hideMenu');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Invoked before the menu is rendered.
- *
- * @method preRender
- */
- preRender: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Invoked before the menu is rendered.
+ *
+ * @method preRender
+ */
+ preRender: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.items().each(function(ctrl) {
- var settings = ctrl.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.items().each(function (ctrl) {
+ var settings = ctrl.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.icon || settings.image || settings.selectable) {
- self._hasIcons = true;
- return false;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.icon || settings.image || settings.selectable) {
+ self._hasIcons = true;
+ return false;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.settings.itemsFactory) {
- self.on('postrender', function() {
- if (self.settings.itemsFactory) {
- self.load();
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.settings.itemsFactory) {
+ self.on('postrender', function () {
+ if (self.settings.itemsFactory) {
+ self.load();
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- }
- });
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/ListBox.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * ListBox.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -47950,149 +52920,151 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.ListBox
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.MenuButton
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/ListBox", [
- "tinymce/ui/MenuButton",
- "tinymce/ui/Menu"
-], function(MenuButton, Menu) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.ListBox',
+ [
+ "tinymce.core.ui.MenuButton",
+ "tinymce.core.ui.Menu"
+ ],
+ function (MenuButton, Menu) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return MenuButton.extend({
- /**
- * Constructs a instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- * @setting {Array} values Array with values to add to list box.
- */
- init: function(settings) {
- var self = this, values, selected, selectedText, lastItemCtrl;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return MenuButton.extend({
+ /**
+ * Constructs a instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ * @setting {Array} values Array with values to add to list box.
+ */
+ init: function (settings) {
+ var self = this, values, selected, selectedText, lastItemCtrl;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setSelected(menuValues) {
- // Try to find a selected value
- for (var i = 0; i < menuValues.length; i++) {
- selected = menuValues[i].selected || settings.value === menuValues[i].value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setSelected(menuValues) {
+ // Try to find a selected value
+ for (var i = 0; i < menuValues.length; i++) {
+ selected = menuValues[i].selected || settings.value === menuValues[i].value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (selected) {
- selectedText = selectedText || menuValues[i].text;
- self.state.set('value', menuValues[i].value);
- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (selected) {
+ selectedText = selectedText || menuValues[i].text;
+ self.state.set('value', menuValues[i].value);
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If the value has a submenu, try to find the selected values in that menu
- if (menuValues[i].menu) {
- if (setSelected(menuValues[i].menu)) {
- return true;
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If the value has a submenu, try to find the selected values in that menu
+ if (menuValues[i].menu) {
+ if (setSelected(menuValues[i].menu)) {
+ return true;
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super(settings);
- settings = self.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super(settings);
+ settings = self.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._values = values = settings.values;
- if (values) {
- if (typeof settings.value != "undefined") {
- setSelected(values);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._values = values = settings.values;
+ if (values) {
+ if (typeof settings.value != "undefined") {
+ setSelected(values);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Default with first item
- if (!selected && values.length > 0) {
- selectedText = values[0].text;
- self.state.set('value', values[0].value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Default with first item
+ if (!selected && values.length > 0) {
+ selectedText = values[0].text;
+ self.state.set('value', values[0].value);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.set('menu', values);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.set('menu', values);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.set('text', settings.text || selectedText);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.set('text', settings.text || selectedText);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.classes.add('listbox');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.classes.add('listbox');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('select', function(e) {
- var ctrl = e.control;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('select', function (e) {
+ var ctrl = e.control;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (lastItemCtrl) {
- e.lastControl = lastItemCtrl;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (lastItemCtrl) {
+ e.lastControl = lastItemCtrl;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.multiple) {
- ctrl.active(!ctrl.active());
- } else {
- self.value(e.control.value());
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.multiple) {
+ ctrl.active(!ctrl.active());
+ } else {
+ self.value(e.control.value());
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- lastItemCtrl = ctrl;
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ lastItemCtrl = ctrl;
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Getter/setter function for the control value.
- *
- * @method value
- * @param {String} [value] Value to be set.
- * @return {Boolean/tinymce.ui.ListBox} Value or self if it's a set operation.
- */
- bindStates: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Getter/setter function for the control value.
+ *
+ * @method value
+ * @param {String} [value] Value to be set.
+ * @return {Boolean/tinymce.ui.ListBox} Value or self if it's a set operation.
+ */
+ bindStates: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function activateMenuItemsByValue(menu, value) {
- if (menu instanceof Menu) {
- menu.items().each(function(ctrl) {
- if (!ctrl.hasMenus()) {
- ctrl.active(ctrl.value() === value);
- }
- });
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function activateMenuItemsByValue(menu, value) {
+ if (menu instanceof Menu) {
+ menu.items().each(function (ctrl) {
+ if (!ctrl.hasMenus()) {
+ ctrl.active(ctrl.value() === value);
+ }
+ });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function getSelectedItem(menuValues, value) {
- var selectedItem;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function getSelectedItem(menuValues, value) {
+ var selectedItem;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!menuValues) {
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!menuValues) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var i = 0; i < menuValues.length; i++) {
- if (menuValues[i].value === value) {
- return menuValues[i];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (var i = 0; i < menuValues.length; i++) {
+ if (menuValues[i].value === value) {
+ return menuValues[i];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (menuValues[i].menu) {
- selectedItem = getSelectedItem(menuValues[i].menu, value);
- if (selectedItem) {
- return selectedItem;
- }
- }
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (menuValues[i].menu) {
+ selectedItem = getSelectedItem(menuValues[i].menu, value);
+ if (selectedItem) {
+ return selectedItem;
+ }
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('show', function(e) {
- activateMenuItemsByValue(e.control, self.value());
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('show', function (e) {
+ activateMenuItemsByValue(e.control, self.value());
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:value', function(e) {
- var selectedItem = getSelectedItem(self.state.get('menu'), e.value);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:value', function (e) {
+ var selectedItem = getSelectedItem(self.state.get('menu'), e.value);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (selectedItem) {
- self.text(selectedItem.text);
- } else {
- self.text(self.settings.text);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (selectedItem) {
+ self.text(selectedItem.text);
+ } else {
+ self.text(self.settings.text);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- }
- });
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/Radio.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Radio.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -48105,26 +53077,27 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.Radio
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Checkbox
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Radio", [
- "tinymce/ui/Checkbox"
-], function(Checkbox) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Radio',
+ [
+ "tinymce.core.ui.Checkbox"
+ ],
+ function (Checkbox) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Checkbox.extend({
- Defaults: {
- classes: "radio",
- role: "radio"
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/ResizeHandle.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Checkbox.extend({
+ Defaults: {
+ classes: "radio",
+ role: "radio"
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * ResizeHandle.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -48137,83 +53110,85 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.ResizeHandle
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Widget
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/ResizeHandle", [
- "tinymce/ui/Widget",
- "tinymce/ui/DragHelper"
-], function(Widget, DragHelper) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.ResizeHandle',
+ [
+ "tinymce.core.ui.Widget",
+ "tinymce.core.ui.DragHelper"
+ ],
+ function (Widget, DragHelper) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Widget.extend({
- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this, prefix = self.classPrefix;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Widget.extend({
+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this, prefix = self.classPrefix;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.classes.add('resizehandle');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.classes.add('resizehandle');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.settings.direction == "both") {
- self.classes.add('resizehandle-both');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.settings.direction == "both") {
+ self.classes.add('resizehandle-both');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.canFocus = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.canFocus = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<div id="' + self._id + '" class="' + self.classes + '">' +
- '<i class="' + prefix + 'ico ' + prefix + 'i-resize"></i>' +
- '</div>'
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<div id="' + self._id + '" class="' + self.classes + '">' +
+ '<i class="' + prefix + 'ico ' + prefix + 'i-resize"></i>' +
+ '</div>'
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Called after the control has been rendered.
- *
- * @method postRender
- */
- postRender: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Called after the control has been rendered.
+ *
+ * @method postRender
+ */
+ postRender: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.resizeDragHelper = new DragHelper(this._id, {
- start: function() {
- self.fire('ResizeStart');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.resizeDragHelper = new DragHelper(this._id, {
+ start: function () {
+ self.fire('ResizeStart');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- drag: function(e) {
- if (self.settings.direction != "both") {
- e.deltaX = 0;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ drag: function (e) {
+ if (self.settings.direction != "both") {
+ e.deltaX = 0;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.fire('Resize', e);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.fire('Resize', e);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- stop: function() {
- self.fire('ResizeEnd');
- }
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ stop: function () {
+ self.fire('ResizeEnd');
+ }
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- remove: function() {
- if (this.resizeDragHelper) {
- this.resizeDragHelper.destroy();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ remove: function () {
+ if (this.resizeDragHelper) {
+ this.resizeDragHelper.destroy();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this._super();
- }
- });
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this._super();
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/SelectBox.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * SelectBox.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -48226,119 +53201,121 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.SelectBox
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Widget
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/SelectBox", [
- "tinymce/ui/Widget"
-], function(Widget) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.SelectBox',
+ [
+ "tinymce.core.ui.Widget"
+ ],
+ function (Widget) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function createOptions(options) {
- var strOptions = '';
- if (options) {
- for (var i = 0; i < options.length; i++) {
- strOptions += '<option value="' + options[i] + '">' + options[i] + '</option>';
- }
- }
- return strOptions;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function createOptions(options) {
+ var strOptions = '';
+ if (options) {
+ for (var i = 0; i < options.length; i++) {
+ strOptions += '<option value="' + options[i] + '">' + options[i] + '</option>';
+ }
+ }
+ return strOptions;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Widget.extend({
- Defaults: {
- classes: "selectbox",
- role: "selectbox",
- options: []
- },
- /**
- * Constructs a instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- * @setting {Array} options Array with options to add to the select box.
- */
- init: function(settings) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Widget.extend({
+ Defaults: {
+ classes: "selectbox",
+ role: "selectbox",
+ options: []
+ },
+ /**
+ * Constructs a instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ * @setting {Array} options Array with options to add to the select box.
+ */
+ init: function (settings) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super(settings);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super(settings);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.settings.size) {
- self.size = self.settings.size;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.settings.size) {
+ self.size = self.settings.size;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.settings.options) {
- self._options = self.settings.options;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.settings.options) {
+ self._options = self.settings.options;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('keydown', function(e) {
- var rootControl;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('keydown', function (e) {
+ var rootControl;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.keyCode == 13) {
- e.preventDefault();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.keyCode == 13) {
+ e.preventDefault();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Find root control that we can do toJSON on
- self.parents().reverse().each(function(ctrl) {
- if (ctrl.toJSON) {
- rootControl = ctrl;
- return false;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find root control that we can do toJSON on
+ self.parents().reverse().each(function (ctrl) {
+ if (ctrl.toJSON) {
+ rootControl = ctrl;
+ return false;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Fire event on current text box with the serialized data of the whole form
- self.fire('submit', {data: rootControl.toJSON()});
- }
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Fire event on current text box with the serialized data of the whole form
+ self.fire('submit', { data: rootControl.toJSON() });
+ }
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Getter/setter function for the options state.
- *
- * @method options
- * @param {Array} [state] State to be set.
- * @return {Array|tinymce.ui.SelectBox} Array of string options.
- */
- options: function(state) {
- if (!arguments.length) {
- return this.state.get('options');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Getter/setter function for the options state.
+ *
+ * @method options
+ * @param {Array} [state] State to be set.
+ * @return {Array|tinymce.ui.SelectBox} Array of string options.
+ */
+ options: function (state) {
+ if (!arguments.length) {
+ return this.state.get('options');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.state.set('options', state);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.state.set('options', state);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- renderHtml: function() {
- var self = this, options, size = '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ renderHtml: function () {
+ var self = this, options, size = '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- options = createOptions(self._options);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ options = createOptions(self._options);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.size) {
- size = ' size = "' + self.size + '"';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.size) {
+ size = ' size = "' + self.size + '"';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<select id="' + self._id + '" class="' + self.classes + '"' + size + '>' +
- options +
- '</select>'
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<select id="' + self._id + '" class="' + self.classes + '"' + size + '>' +
+ options +
+ '</select>'
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bindStates: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bindStates: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:options', function(e) {
- self.getEl().innerHTML = createOptions(e.value);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:options', function (e) {
+ self.getEl().innerHTML = createOptions(e.value);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- }
- });
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/Slider.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Slider.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -48351,212 +53328,213 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.Slider
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Widget
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Slider", [
- "tinymce/ui/Widget",
- "tinymce/ui/DragHelper",
- "tinymce/ui/DomUtils"
-], function(Widget, DragHelper, DomUtils) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Slider',
+ [
+ "tinymce.core.ui.Widget",
+ "tinymce.core.ui.DragHelper",
+ "tinymce.core.ui.DomUtils"
+ ],
+ function (Widget, DragHelper, DomUtils) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function constrain(value, minVal, maxVal) {
- if (value < minVal) {
- value = minVal;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function constrain(value, minVal, maxVal) {
+ if (value < minVal) {
+ value = minVal;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (value > maxVal) {
- value = maxVal;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (value > maxVal) {
+ value = maxVal;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return value;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return value;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function setAriaProp(el, name, value) {
- el.setAttribute('aria-' + name, value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function setAriaProp(el, name, value) {
+ el.setAttribute('aria-' + name, value);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function updateSliderHandle(ctrl, value) {
- var maxHandlePos, shortSizeName, sizeName, stylePosName, styleValue, handleEl;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function updateSliderHandle(ctrl, value) {
+ var maxHandlePos, shortSizeName, sizeName, stylePosName, styleValue, handleEl;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (ctrl.settings.orientation == "v") {
- stylePosName = "top";
- sizeName = "height";
- shortSizeName = "h";
- } else {
- stylePosName = "left";
- sizeName = "width";
- shortSizeName = "w";
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (ctrl.settings.orientation == "v") {
+ stylePosName = "top";
+ sizeName = "height";
+ shortSizeName = "h";
+ } else {
+ stylePosName = "left";
+ sizeName = "width";
+ shortSizeName = "w";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- handleEl = ctrl.getEl('handle');
- maxHandlePos = (ctrl.layoutRect()[shortSizeName] || 100) - DomUtils.getSize(handleEl)[sizeName];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ handleEl = ctrl.getEl('handle');
+ maxHandlePos = (ctrl.layoutRect()[shortSizeName] || 100) - DomUtils.getSize(handleEl)[sizeName];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- styleValue = (maxHandlePos * ((value - ctrl._minValue) / (ctrl._maxValue - ctrl._minValue))) + 'px';
- handleEl.style[stylePosName] = styleValue;
- handleEl.style.height = ctrl.layoutRect().h + 'px';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ styleValue = (maxHandlePos * ((value - ctrl._minValue) / (ctrl._maxValue - ctrl._minValue))) + 'px';
+ handleEl.style[stylePosName] = styleValue;
+ handleEl.style.height = ctrl.layoutRect().h + 'px';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- setAriaProp(handleEl, 'valuenow', value);
- setAriaProp(handleEl, 'valuetext', '' + ctrl.settings.previewFilter(value));
- setAriaProp(handleEl, 'valuemin', ctrl._minValue);
- setAriaProp(handleEl, 'valuemax', ctrl._maxValue);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ setAriaProp(handleEl, 'valuenow', value);
+ setAriaProp(handleEl, 'valuetext', '' + ctrl.settings.previewFilter(value));
+ setAriaProp(handleEl, 'valuemin', ctrl._minValue);
+ setAriaProp(handleEl, 'valuemax', ctrl._maxValue);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Widget.extend({
- init: function(settings) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Widget.extend({
+ init: function (settings) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!settings.previewFilter) {
- settings.previewFilter = function(value) {
- return Math.round(value * 100) / 100.0;
- };
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!settings.previewFilter) {
+ settings.previewFilter = function (value) {
+ return Math.round(value * 100) / 100.0;
+ };
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super(settings);
- self.classes.add('slider');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super(settings);
+ self.classes.add('slider');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.orientation == "v") {
- self.classes.add('vertical');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.orientation == "v") {
+ self.classes.add('vertical');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._minValue = settings.minValue || 0;
- self._maxValue = settings.maxValue || 100;
- self._initValue = self.state.get('value');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._minValue = settings.minValue || 0;
+ self._maxValue = settings.maxValue || 100;
+ self._initValue = self.state.get('value');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- renderHtml: function() {
- var self = this, id = self._id, prefix = self.classPrefix;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ renderHtml: function () {
+ var self = this, id = self._id, prefix = self.classPrefix;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<div id="' + id + '" class="' + self.classes + '">' +
- '<div id="' + id + '-handle" class="' + prefix + 'slider-handle" role="slider" tabindex="-1"></div>' +
- '</div>'
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<div id="' + id + '" class="' + self.classes + '">' +
+ '<div id="' + id + '-handle" class="' + prefix + 'slider-handle" role="slider" tabindex="-1"></div>' +
+ '</div>'
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- reset: function() {
- this.value(this._initValue).repaint();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ reset: function () {
+ this.value(this._initValue).repaint();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- postRender: function() {
- var self = this, minValue, maxValue, screenCordName,
- stylePosName, sizeName, shortSizeName;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ postRender: function () {
+ var self = this, minValue, maxValue, screenCordName,
+ stylePosName, sizeName, shortSizeName;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function toFraction(min, max, val) {
- return (val + min) / (max - min);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function toFraction(min, max, val) {
+ return (val + min) / (max - min);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function fromFraction(min, max, val) {
- return (val * (max - min)) - min;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function fromFraction(min, max, val) {
+ return (val * (max - min)) - min;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function handleKeyboard(minValue, maxValue) {
- function alter(delta) {
- var value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function handleKeyboard(minValue, maxValue) {
+ function alter(delta) {
+ var value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- value = self.value();
- value = fromFraction(minValue, maxValue, toFraction(minValue, maxValue, value) + (delta * 0.05));
- value = constrain(value, minValue, maxValue);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ value = self.value();
+ value = fromFraction(minValue, maxValue, toFraction(minValue, maxValue, value) + (delta * 0.05));
+ value = constrain(value, minValue, maxValue);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.value(value);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.value(value);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.fire('dragstart', {value: value});
- self.fire('drag', {value: value});
- self.fire('dragend', {value: value});
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.fire('dragstart', { value: value });
+ self.fire('drag', { value: value });
+ self.fire('dragend', { value: value });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('keydown', function(e) {
- switch (e.keyCode) {
- case 37:
- case 38:
- alter(-1);
- break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('keydown', function (e) {
+ switch (e.keyCode) {
+ case 37:
+ case 38:
+ alter(-1);
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- case 39:
- case 40:
- alter(1);
- break;
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case 39:
+ case 40:
+ alter(1);
+ break;
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function handleDrag(minValue, maxValue, handleEl) {
- var startPos, startHandlePos, maxHandlePos, handlePos, value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function handleDrag(minValue, maxValue, handleEl) {
+ var startPos, startHandlePos, maxHandlePos, handlePos, value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._dragHelper = new DragHelper(self._id, {
- handle: self._id + "-handle",
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._dragHelper = new DragHelper(self._id, {
+ handle: self._id + "-handle",
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- start: function(e) {
- startPos = e[screenCordName];
- startHandlePos = parseInt(self.getEl('handle').style[stylePosName], 10);
- maxHandlePos = (self.layoutRect()[shortSizeName] || 100) - DomUtils.getSize(handleEl)[sizeName];
- self.fire('dragstart', {value: value});
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ start: function (e) {
+ startPos = e[screenCordName];
+ startHandlePos = parseInt(self.getEl('handle').style[stylePosName], 10);
+ maxHandlePos = (self.layoutRect()[shortSizeName] || 100) - DomUtils.getSize(handleEl)[sizeName];
+ self.fire('dragstart', { value: value });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- drag: function(e) {
- var delta = e[screenCordName] - startPos;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ drag: function (e) {
+ var delta = e[screenCordName] - startPos;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- handlePos = constrain(startHandlePos + delta, 0, maxHandlePos);
- handleEl.style[stylePosName] = handlePos + 'px';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ handlePos = constrain(startHandlePos + delta, 0, maxHandlePos);
+ handleEl.style[stylePosName] = handlePos + 'px';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- value = minValue + (handlePos / maxHandlePos) * (maxValue - minValue);
- self.value(value);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ value = minValue + (handlePos / maxHandlePos) * (maxValue - minValue);
+ self.value(value);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.tooltip().text('' + self.settings.previewFilter(value)).show().moveRel(handleEl, 'bc tc');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.tooltip().text('' + self.settings.previewFilter(value)).show().moveRel(handleEl, 'bc tc');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.fire('drag', {value: value});
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.fire('drag', { value: value });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- stop: function() {
- self.tooltip().hide();
- self.fire('dragend', {value: value});
- }
- });
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ stop: function () {
+ self.tooltip().hide();
+ self.fire('dragend', { value: value });
+ }
+ });
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- minValue = self._minValue;
- maxValue = self._maxValue;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ minValue = self._minValue;
+ maxValue = self._maxValue;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.settings.orientation == "v") {
- screenCordName = "screenY";
- stylePosName = "top";
- sizeName = "height";
- shortSizeName = "h";
- } else {
- screenCordName = "screenX";
- stylePosName = "left";
- sizeName = "width";
- shortSizeName = "w";
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.settings.orientation == "v") {
+ screenCordName = "screenY";
+ stylePosName = "top";
+ sizeName = "height";
+ shortSizeName = "h";
+ } else {
+ screenCordName = "screenX";
+ stylePosName = "left";
+ sizeName = "width";
+ shortSizeName = "w";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- handleKeyboard(minValue, maxValue, self.getEl('handle'));
- handleDrag(minValue, maxValue, self.getEl('handle'));
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ handleKeyboard(minValue, maxValue, self.getEl('handle'));
+ handleDrag(minValue, maxValue, self.getEl('handle'));
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- repaint: function() {
- this._super();
- updateSliderHandle(this, this.value());
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ repaint: function () {
+ this._super();
+ updateSliderHandle(this, this.value());
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bindStates: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bindStates: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:value', function(e) {
- updateSliderHandle(self, e.value);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:value', function (e) {
+ updateSliderHandle(self, e.value);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/Spacer.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Spacer.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -48569,36 +53547,37 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.Spacer
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Widget
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/Spacer", [
- "tinymce/ui/Widget"
-], function(Widget) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Spacer',
+ [
+ "tinymce.core.ui.Widget"
+ ],
+ function (Widget) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Widget.extend({
- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Widget.extend({
+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.classes.add('spacer');
- self.canFocus = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.classes.add('spacer');
+ self.canFocus = false;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return '<div id="' + self._id + '" class="' + self.classes + '"></div>';
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/SplitButton.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return '<div id="' + self._id + '" class="' + self.classes + '"></div>';
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * SplitButton.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -48611,143 +53590,144 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.SplitButton
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Button
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/SplitButton", [
- "tinymce/ui/MenuButton",
- "tinymce/ui/DomUtils",
- "tinymce/dom/DomQuery"
-], function(MenuButton, DomUtils, $) {
- return MenuButton.extend({
- Defaults: {
- classes: "widget btn splitbtn",
- role: "button"
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.SplitButton',
+ [
+ "tinymce.core.ui.MenuButton",
+ "tinymce.core.ui.DomUtils",
+ "tinymce.core.dom.DomQuery"
+ ],
+ function (MenuButton, DomUtils, $) {
+ return MenuButton.extend({
+ Defaults: {
+ classes: "widget btn splitbtn",
+ role: "button"
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Repaints the control after a layout operation.
- *
- * @method repaint
- */
- repaint: function() {
- var self = this, elm = self.getEl(), rect = self.layoutRect(), mainButtonElm, menuButtonElm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Repaints the control after a layout operation.
+ *
+ * @method repaint
+ */
+ repaint: function () {
+ var self = this, elm = self.getEl(), rect = self.layoutRect(), mainButtonElm, menuButtonElm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- mainButtonElm = elm.firstChild;
- menuButtonElm = elm.lastChild;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ mainButtonElm = elm.firstChild;
+ menuButtonElm = elm.lastChild;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $(mainButtonElm).css({
- width: rect.w - DomUtils.getSize(menuButtonElm).width,
- height: rect.h - 2
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $(mainButtonElm).css({
+ width: rect.w - DomUtils.getSize(menuButtonElm).width,
+ height: rect.h - 2
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $(menuButtonElm).css({
- height: rect.h - 2
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $(menuButtonElm).css({
+ height: rect.h - 2
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Sets the active menu state.
- *
- * @private
- */
- activeMenu: function(state) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Sets the active menu state.
+ *
+ * @private
+ */
+ activeMenu: function (state) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $(self.getEl().lastChild).toggleClass(self.classPrefix + 'active', state);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $(self.getEl().lastChild).toggleClass(self.classPrefix + 'active', state);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this, id = self._id, prefix = self.classPrefix, image;
- var icon = self.state.get('icon'), text = self.state.get('text'),
- textHtml = '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this, id = self._id, prefix = self.classPrefix, image;
+ var icon = self.state.get('icon'), text = self.state.get('text'),
+ textHtml = '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- image = self.settings.image;
- if (image) {
- icon = 'none';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ image = self.settings.image;
+ if (image) {
+ icon = 'none';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Support for [high dpi, low dpi] image sources
- if (typeof image != "string") {
- image = window.getSelection ? image[0] : image[1];
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Support for [high dpi, low dpi] image sources
+ if (typeof image != "string") {
+ image = window.getSelection ? image[0] : image[1];
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- image = ' style="background-image: url(\'' + image + '\')"';
- } else {
- image = '';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ image = ' style="background-image: url(\'' + image + '\')"';
+ } else {
+ image = '';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- icon = self.settings.icon ? prefix + 'ico ' + prefix + 'i-' + icon : '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ icon = self.settings.icon ? prefix + 'ico ' + prefix + 'i-' + icon : '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (text) {
- self.classes.add('btn-has-text');
- textHtml = '<span class="' + prefix + 'txt">' + self.encode(text) + '</span>';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (text) {
+ self.classes.add('btn-has-text');
+ textHtml = '<span class="' + prefix + 'txt">' + self.encode(text) + '</span>';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<div id="' + id + '" class="' + self.classes + '" role="button" tabindex="-1">' +
- '<button type="button" hidefocus="1" tabindex="-1">' +
- (icon ? '<i class="' + icon + '"' + image + '></i>' : '') +
- textHtml +
- '</button>' +
- '<button type="button" class="' + prefix + 'open" hidefocus="1" tabindex="-1">' +
- //(icon ? '<i class="' + icon + '"></i>' : '') +
- (self._menuBtnText ? (icon ? '\u00a0' : '') + self._menuBtnText : '') +
- ' <i class="' + prefix + 'caret"></i>' +
- '</button>' +
- '</div>'
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<div id="' + id + '" class="' + self.classes + '" role="button" tabindex="-1">' +
+ '<button type="button" hidefocus="1" tabindex="-1">' +
+ (icon ? '<i class="' + icon + '"' + image + '></i>' : '') +
+ textHtml +
+ '</button>' +
+ '<button type="button" class="' + prefix + 'open" hidefocus="1" tabindex="-1">' +
+ //(icon ? '<i class="' + icon + '"></i>' : '') +
+ (self._menuBtnText ? (icon ? '\u00a0' : '') + self._menuBtnText : '') +
+ ' <i class="' + prefix + 'caret"></i>' +
+ '</button>' +
+ '</div>'
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Called after the control has been rendered.
- *
- * @method postRender
- */
- postRender: function() {
- var self = this, onClickHandler = self.settings.onclick;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Called after the control has been rendered.
+ *
+ * @method postRender
+ */
+ postRender: function () {
+ var self = this, onClickHandler = self.settings.onclick;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('click', function(e) {
- var node = e.target;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('click', function (e) {
+ var node = e.target;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.control == this) {
- // Find clicks that is on the main button
- while (node) {
- if ((e.aria && e.aria.key != 'down') || (node.nodeName == 'BUTTON' && node.className.indexOf('open') == -1)) {
- e.stopImmediatePropagation();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.control == this) {
+ // Find clicks that is on the main button
+ while (node) {
+ if ((e.aria && e.aria.key != 'down') || (node.nodeName == 'BUTTON' && node.className.indexOf('open') == -1)) {
+ e.stopImmediatePropagation();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (onClickHandler) {
- onClickHandler.call(this, e);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (onClickHandler) {
+ onClickHandler.call(this, e);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- node = node.parentNode;
- }
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ node = node.parentNode;
+ }
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- delete self.settings.onclick;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ delete self.settings.onclick;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/StackLayout.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * StackLayout.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -48760,31 +53740,32 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.StackLayout
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.FlowLayout
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/StackLayout", [
- "tinymce/ui/FlowLayout"
-], function(FlowLayout) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.StackLayout',
+ [
+ "tinymce.core.ui.FlowLayout"
+ ],
+ function (FlowLayout) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return FlowLayout.extend({
- Defaults: {
- containerClass: 'stack-layout',
- controlClass: 'stack-layout-item',
- endClass: 'break'
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return FlowLayout.extend({
+ Defaults: {
+ containerClass: 'stack-layout',
+ controlClass: 'stack-layout-item',
+ endClass: 'break'
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- isNative: function() {
- return true;
- }
- });
-});
-
-// Included from: js/tinymce/classes/ui/TabPanel.js
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ isNative: function () {
+ return true;
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * TabPanel.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -48799,173 +53780,175 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @setting {Number} activeTab Active tab index.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/TabPanel", [
- "tinymce/ui/Panel",
- "tinymce/dom/DomQuery",
- "tinymce/ui/DomUtils"
-], function(Panel, $, DomUtils) {
- "use strict";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.TabPanel',
+ [
+ "tinymce.core.ui.Panel",
+ "tinymce.core.dom.DomQuery",
+ "tinymce.core.ui.DomUtils"
+ ],
+ function (Panel, $, DomUtils) {
+ "use strict";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return Panel.extend({
- Defaults: {
- layout: 'absolute',
- defaults: {
- type: 'panel'
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return Panel.extend({
+ Defaults: {
+ layout: 'absolute',
+ defaults: {
+ type: 'panel'
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Activates the specified tab by index.
- *
- * @method activateTab
- * @param {Number} idx Index of the tab to activate.
- */
- activateTab: function(idx) {
- var activeTabElm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Activates the specified tab by index.
+ *
+ * @method activateTab
+ * @param {Number} idx Index of the tab to activate.
+ */
+ activateTab: function (idx) {
+ var activeTabElm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.activeTabId) {
- activeTabElm = this.getEl(this.activeTabId);
- $(activeTabElm).removeClass(this.classPrefix + 'active');
- activeTabElm.setAttribute('aria-selected', "false");
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.activeTabId) {
+ activeTabElm = this.getEl(this.activeTabId);
+ $(activeTabElm).removeClass(this.classPrefix + 'active');
+ activeTabElm.setAttribute('aria-selected', "false");
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.activeTabId = 't' + idx;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.activeTabId = 't' + idx;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- activeTabElm = this.getEl('t' + idx);
- activeTabElm.setAttribute('aria-selected', "true");
- $(activeTabElm).addClass(this.classPrefix + 'active');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ activeTabElm = this.getEl('t' + idx);
+ activeTabElm.setAttribute('aria-selected', "true");
+ $(activeTabElm).addClass(this.classPrefix + 'active');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.items()[idx].show().fire('showtab');
- this.reflow();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.items()[idx].show().fire('showtab');
+ this.reflow();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.items().each(function(item, i) {
- if (idx != i) {
- item.hide();
- }
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.items().each(function (item, i) {
+ if (idx != i) {
+ item.hide();
+ }
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this, layout = self._layout, tabsHtml = '', prefix = self.classPrefix;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this, layout = self._layout, tabsHtml = '', prefix = self.classPrefix;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.preRender();
- layout.preRender(self);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.preRender();
+ layout.preRender(self);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.items().each(function(ctrl, i) {
- var id = self._id + '-t' + i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.items().each(function (ctrl, i) {
+ var id = self._id + '-t' + i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ctrl.aria('role', 'tabpanel');
- ctrl.aria('labelledby', id);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ctrl.aria('role', 'tabpanel');
+ ctrl.aria('labelledby', id);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tabsHtml += (
- '<div id="' + id + '" class="' + prefix + 'tab" ' +
- 'unselectable="on" role="tab" aria-controls="' + ctrl._id + '" aria-selected="false" tabIndex="-1">' +
- self.encode(ctrl.settings.title) +
- '</div>'
- );
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ tabsHtml += (
+ '<div id="' + id + '" class="' + prefix + 'tab" ' +
+ 'unselectable="on" role="tab" aria-controls="' + ctrl._id + '" aria-selected="false" tabIndex="-1">' +
+ self.encode(ctrl.settings.title) +
+ '</div>'
+ );
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return (
- '<div id="' + self._id + '" class="' + self.classes + '" hidefocus="1" tabindex="-1">' +
- '<div id="' + self._id + '-head" class="' + prefix + 'tabs" role="tablist">' +
- tabsHtml +
- '</div>' +
- '<div id="' + self._id + '-body" class="' + self.bodyClasses + '">' +
- layout.renderHtml(self) +
- '</div>' +
- '</div>'
- );
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return (
+ '<div id="' + self._id + '" class="' + self.classes + '" hidefocus="1" tabindex="-1">' +
+ '<div id="' + self._id + '-head" class="' + prefix + 'tabs" role="tablist">' +
+ tabsHtml +
+ '</div>' +
+ '<div id="' + self._id + '-body" class="' + self.bodyClasses + '">' +
+ layout.renderHtml(self) +
+ '</div>' +
+ '</div>'
+ );
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Called after the control has been rendered.
- *
- * @method postRender
- */
- postRender: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Called after the control has been rendered.
+ *
+ * @method postRender
+ */
+ postRender: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.settings.activeTab = self.settings.activeTab || 0;
- self.activateTab(self.settings.activeTab);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.settings.activeTab = self.settings.activeTab || 0;
+ self.activateTab(self.settings.activeTab);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.on('click', function(e) {
- var targetParent = e.target.parentNode;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.on('click', function (e) {
+ var targetParent = e.target.parentNode;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (targetParent && targetParent.id == self._id + '-head') {
- var i = targetParent.childNodes.length;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (targetParent && targetParent.id == self._id + '-head') {
+ var i = targetParent.childNodes.length;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- while (i--) {
- if (targetParent.childNodes[i] == e.target) {
- self.activateTab(i);
- }
- }
- }
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ while (i--) {
+ if (targetParent.childNodes[i] == e.target) {
+ self.activateTab(i);
+ }
+ }
+ }
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Initializes the current controls layout rect.
- * This will be executed by the layout managers to determine the
- * default minWidth/minHeight etc.
- *
- * @method initLayoutRect
- * @return {Object} Layout rect instance.
- */
- initLayoutRect: function() {
- var self = this, rect, minW, minH;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Initializes the current controls layout rect.
+ * This will be executed by the layout managers to determine the
+ * default minWidth/minHeight etc.
+ *
+ * @method initLayoutRect
+ * @return {Object} Layout rect instance.
+ */
+ initLayoutRect: function () {
+ var self = this, rect, minW, minH;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- minW = DomUtils.getSize(self.getEl('head')).width;
- minW = minW < 0 ? 0 : minW;
- minH = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ minW = DomUtils.getSize(self.getEl('head')).width;
+ minW = minW < 0 ? 0 : minW;
+ minH = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.items().each(function(item) {
- minW = Math.max(minW, item.layoutRect().minW);
- minH = Math.max(minH, item.layoutRect().minH);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.items().each(function (item) {
+ minW = Math.max(minW, item.layoutRect().minW);
+ minH = Math.max(minH, item.layoutRect().minH);
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.items().each(function(ctrl) {
- ctrl.settings.x = 0;
- ctrl.settings.y = 0;
- ctrl.settings.w = minW;
- ctrl.settings.h = minH;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.items().each(function (ctrl) {
+ ctrl.settings.x = 0;
+ ctrl.settings.y = 0;
+ ctrl.settings.w = minW;
+ ctrl.settings.h = minH;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ctrl.layoutRect({
- x: 0,
- y: 0,
- w: minW,
- h: minH
- });
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ctrl.layoutRect({
+ x: 0,
+ y: 0,
+ w: minW,
+ h: minH
+ });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var headH = DomUtils.getSize(self.getEl('head')).height;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var headH = DomUtils.getSize(self.getEl('head')).height;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.settings.minWidth = minW;
- self.settings.minHeight = minH + headH;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.settings.minWidth = minW;
+ self.settings.minHeight = minH + headH;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- rect = self._super();
- rect.deltaH += headH;
- rect.innerH = rect.h - rect.deltaH;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ rect = self._super();
+ rect.deltaH += headH;
+ rect.innerH = rect.h - rect.deltaH;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return rect;
- }
- });
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return rect;
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/ui/TextBox.js
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * TextBox.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -48978,201 +53961,521 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.ui.TextBox
</span><span class="cx" style="display: block; padding: 0 10px"> * @extends tinymce.ui.Widget
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/ui/TextBox", [
- "tinymce/ui/Widget",
- "tinymce/util/Tools",
- "tinymce/ui/DomUtils"
-], function(Widget, Tools, DomUtils) {
- return Widget.extend({
- /**
- * Constructs a instance with the specified settings.
- *
- * @constructor
- * @param {Object} settings Name/value object with settings.
- * @setting {Boolean} multiline True if the textbox is a multiline control.
- * @setting {Number} maxLength Max length for the textbox.
- * @setting {Number} size Size of the textbox in characters.
- */
- init: function(settings) {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.TextBox',
+ [
+ "tinymce.core.ui.Widget",
+ "tinymce.core.util.Tools",
+ "tinymce.core.ui.DomUtils"
+ ],
+ function (Widget, Tools, DomUtils) {
+ return Widget.extend({
+ /**
+ * Constructs a instance with the specified settings.
+ *
+ * @constructor
+ * @param {Object} settings Name/value object with settings.
+ * @setting {Boolean} multiline True if the textbox is a multiline control.
+ * @setting {Number} maxLength Max length for the textbox.
+ * @setting {Number} size Size of the textbox in characters.
+ */
+ init: function (settings) {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._super(settings);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._super(settings);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.classes.add('textbox');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.classes.add('textbox');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.multiline) {
- self.classes.add('multiline');
- } else {
- self.on('keydown', function(e) {
- var rootControl;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.multiline) {
+ self.classes.add('multiline');
+ } else {
+ self.on('keydown', function (e) {
+ var rootControl;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.keyCode == 13) {
- e.preventDefault();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.keyCode == 13) {
+ e.preventDefault();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Find root control that we can do toJSON on
- self.parents().reverse().each(function(ctrl) {
- if (ctrl.toJSON) {
- rootControl = ctrl;
- return false;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Find root control that we can do toJSON on
+ self.parents().reverse().each(function (ctrl) {
+ if (ctrl.toJSON) {
+ rootControl = ctrl;
+ return false;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Fire event on current text box with the serialized data of the whole form
- self.fire('submit', {data: rootControl.toJSON()});
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Fire event on current text box with the serialized data of the whole form
+ self.fire('submit', { data: rootControl.toJSON() });
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.on('keyup', function(e) {
- self.state.set('value', e.target.value);
- });
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.on('keyup', function (e) {
+ self.state.set('value', e.target.value);
+ });
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Repaints the control after a layout operation.
- *
- * @method repaint
- */
- repaint: function() {
- var self = this, style, rect, borderBox, borderW, borderH = 0, lastRepaintRect;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Repaints the control after a layout operation.
+ *
+ * @method repaint
+ */
+ repaint: function () {
+ var self = this, style, rect, borderBox, borderW, borderH = 0, lastRepaintRect;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- style = self.getEl().style;
- rect = self._layoutRect;
- lastRepaintRect = self._lastRepaintRect || {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ style = self.getEl().style;
+ rect = self._layoutRect;
+ lastRepaintRect = self._lastRepaintRect || {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Detect old IE 7+8 add lineHeight to align caret vertically in the middle
- var doc = document;
- if (!self.settings.multiline && doc.all && (!doc.documentMode || doc.documentMode <= 8)) {
- style.lineHeight = (rect.h - borderH) + 'px';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Detect old IE 7+8 add lineHeight to align caret vertically in the middle
+ var doc = document;
+ if (!self.settings.multiline && doc.all && (!doc.documentMode || doc.documentMode <= 8)) {
+ style.lineHeight = (rect.h - borderH) + 'px';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- borderBox = self.borderBox;
- borderW = borderBox.left + borderBox.right + 8;
- borderH = borderBox.top + borderBox.bottom + (self.settings.multiline ? 8 : 0);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ borderBox = self.borderBox;
+ borderW = borderBox.left + borderBox.right + 8;
+ borderH = borderBox.top + borderBox.bottom + (self.settings.multiline ? 8 : 0);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rect.x !== lastRepaintRect.x) {
- style.left = rect.x + 'px';
- lastRepaintRect.x = rect.x;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rect.x !== lastRepaintRect.x) {
+ style.left = rect.x + 'px';
+ lastRepaintRect.x = rect.x;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rect.y !== lastRepaintRect.y) {
- style.top = rect.y + 'px';
- lastRepaintRect.y = rect.y;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rect.y !== lastRepaintRect.y) {
+ style.top = rect.y + 'px';
+ lastRepaintRect.y = rect.y;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rect.w !== lastRepaintRect.w) {
- style.width = (rect.w - borderW) + 'px';
- lastRepaintRect.w = rect.w;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rect.w !== lastRepaintRect.w) {
+ style.width = (rect.w - borderW) + 'px';
+ lastRepaintRect.w = rect.w;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (rect.h !== lastRepaintRect.h) {
- style.height = (rect.h - borderH) + 'px';
- lastRepaintRect.h = rect.h;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (rect.h !== lastRepaintRect.h) {
+ style.height = (rect.h - borderH) + 'px';
+ lastRepaintRect.h = rect.h;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self._lastRepaintRect = lastRepaintRect;
- self.fire('repaint', {}, false);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self._lastRepaintRect = lastRepaintRect;
+ self.fire('repaint', {}, false);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Renders the control as a HTML string.
- *
- * @method renderHtml
- * @return {String} HTML representing the control.
- */
- renderHtml: function() {
- var self = this, settings = self.settings, attrs, elm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Renders the control as a HTML string.
+ *
+ * @method renderHtml
+ * @return {String} HTML representing the control.
+ */
+ renderHtml: function () {
+ var self = this, settings = self.settings, attrs, elm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- attrs = {
- id: self._id,
- hidefocus: '1'
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ attrs = {
+ id: self._id,
+ hidefocus: '1'
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- Tools.each([
- 'rows', 'spellcheck', 'maxLength', 'size', 'readonly', 'min',
- 'max', 'step', 'list', 'pattern', 'placeholder', 'required', 'multiple'
- ], function(name) {
- attrs[name] = settings[name];
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ Tools.each([
+ 'rows', 'spellcheck', 'maxLength', 'size', 'readonly', 'min',
+ 'max', 'step', 'list', 'pattern', 'placeholder', 'required', 'multiple'
+ ], function (name) {
+ attrs[name] = settings[name];
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (self.disabled()) {
- attrs.disabled = 'disabled';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (self.disabled()) {
+ attrs.disabled = 'disabled';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (settings.subtype) {
- attrs.type = settings.subtype;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (settings.subtype) {
+ attrs.type = settings.subtype;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- elm = DomUtils.create(settings.multiline ? 'textarea' : 'input', attrs);
- elm.value = self.state.get('value');
- elm.className = self.classes;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ elm = DomUtils.create(settings.multiline ? 'textarea' : 'input', attrs);
+ elm.value = self.state.get('value');
+ elm.className = self.classes;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return elm.outerHTML;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return elm.outerHTML;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- value: function(value) {
- if (arguments.length) {
- this.state.set('value', value);
- return this;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ value: function (value) {
+ if (arguments.length) {
+ this.state.set('value', value);
+ return this;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Make sure the real state is in sync
- if (this.state.get('rendered')) {
- this.state.set('value', this.getEl().value);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Make sure the real state is in sync
+ if (this.state.get('rendered')) {
+ this.state.set('value', this.getEl().value);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return this.state.get('value');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return this.state.get('value');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * Called after the control has been rendered.
- *
- * @method postRender
- */
- postRender: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Called after the control has been rendered.
+ *
+ * @method postRender
+ */
+ postRender: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.getEl().value = self.state.get('value');
- self._super();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.getEl().value = self.state.get('value');
+ self._super();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.$el.on('change', function(e) {
- self.state.set('value', e.target.value);
- self.fire('change', e);
- });
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.$el.on('change', function (e) {
+ self.state.set('value', e.target.value);
+ self.fire('change', e);
+ });
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- bindStates: function() {
- var self = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ bindStates: function () {
+ var self = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:value', function(e) {
- if (self.getEl().value != e.value) {
- self.getEl().value = e.value;
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:value', function (e) {
+ if (self.getEl().value != e.value) {
+ self.getEl().value = e.value;
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self.state.on('change:disabled', function(e) {
- self.getEl().disabled = e.value;
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self.state.on('change:disabled', function (e) {
+ self.getEl().disabled = e.value;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self._super();
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return self._super();
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- remove: function() {
- this.$el.off();
- this._super();
- }
- });
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ remove: function () {
+ this.$el.off();
+ this._super();
+ }
+ });
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Included from: js/tinymce/classes/Register.js
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Api.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.ui.Api',
+ [
+ 'tinymce.core.ui.Selector',
+ 'tinymce.core.ui.Collection',
+ 'tinymce.core.ui.ReflowQueue',
+ 'tinymce.core.ui.Control',
+ 'tinymce.core.ui.Factory',
+ 'tinymce.core.ui.KeyboardNavigation',
+ 'tinymce.core.ui.Container',
+ 'tinymce.core.ui.DragHelper',
+ 'tinymce.core.ui.Scrollable',
+ 'tinymce.core.ui.Panel',
+ 'tinymce.core.ui.Movable',
+ 'tinymce.core.ui.Resizable',
+ 'tinymce.core.ui.FloatPanel',
+ 'tinymce.core.ui.Window',
+ 'tinymce.core.ui.MessageBox',
+ 'tinymce.core.ui.Tooltip',
+ 'tinymce.core.ui.Widget',
+ 'tinymce.core.ui.Progress',
+ 'tinymce.core.ui.Notification',
+ 'tinymce.core.ui.Layout',
+ 'tinymce.core.ui.AbsoluteLayout',
+ 'tinymce.core.ui.Button',
+ 'tinymce.core.ui.ButtonGroup',
+ 'tinymce.core.ui.Checkbox',
+ 'tinymce.core.ui.ComboBox',
+ 'tinymce.core.ui.ColorBox',
+ 'tinymce.core.ui.PanelButton',
+ 'tinymce.core.ui.ColorButton',
+ 'tinymce.core.ui.ColorPicker',
+ 'tinymce.core.ui.Path',
+ 'tinymce.core.ui.ElementPath',
+ 'tinymce.core.ui.FormItem',
+ 'tinymce.core.ui.Form',
+ 'tinymce.core.ui.FieldSet',
+ 'tinymce.core.ui.FilePicker',
+ 'tinymce.core.ui.FitLayout',
+ 'tinymce.core.ui.FlexLayout',
+ 'tinymce.core.ui.FlowLayout',
+ 'tinymce.core.ui.FormatControls',
+ 'tinymce.core.ui.GridLayout',
+ 'tinymce.core.ui.Iframe',
+ 'tinymce.core.ui.InfoBox',
+ 'tinymce.core.ui.Label',
+ 'tinymce.core.ui.Toolbar',
+ 'tinymce.core.ui.MenuBar',
+ 'tinymce.core.ui.MenuButton',
+ 'tinymce.core.ui.MenuItem',
+ 'tinymce.core.ui.Throbber',
+ 'tinymce.core.ui.Menu',
+ 'tinymce.core.ui.ListBox',
+ 'tinymce.core.ui.Radio',
+ 'tinymce.core.ui.ResizeHandle',
+ 'tinymce.core.ui.SelectBox',
+ 'tinymce.core.ui.Slider',
+ 'tinymce.core.ui.Spacer',
+ 'tinymce.core.ui.SplitButton',
+ 'tinymce.core.ui.StackLayout',
+ 'tinymce.core.ui.TabPanel',
+ 'tinymce.core.ui.TextBox'
+ ],
+ function (
+ Selector, Collection, ReflowQueue, Control, Factory, KeyboardNavigation, Container, DragHelper, Scrollable, Panel, Movable,
+ Resizable, FloatPanel, Window, MessageBox, Tooltip, Widget, Progress, Notification, Layout, AbsoluteLayout, Button,
+ ButtonGroup, Checkbox, ComboBox, ColorBox, PanelButton, ColorButton, ColorPicker, Path, ElementPath, FormItem, Form,
+ FieldSet, FilePicker, FitLayout, FlexLayout, FlowLayout, FormatControls, GridLayout, Iframe, InfoBox, Label, Toolbar,
+ MenuBar, MenuButton, MenuItem, Throbber, Menu, ListBox, Radio, ResizeHandle, SelectBox, Slider, Spacer, SplitButton,
+ StackLayout, TabPanel, TextBox
+ ) {
+ "use strict";
+
+ var registerToFactory = function (id, ref) {
+ Factory.add(id.split('.').pop(), ref);
+ };
+
+ var expose = function (target, id, ref) {
+ var i, fragments;
+
+ fragments = id.split(/[.\/]/);
+ for (i = 0; i < fragments.length - 1; ++i) {
+ if (target[fragments[i]] === undefined) {
+ target[fragments[i]] = {};
+ }
+
+ target = target[fragments[i]];
+ }
+
+ target[fragments[fragments.length - 1]] = ref;
+
+ registerToFactory(id, ref);
+ };
+
+ var appendTo = function (target) {
+ expose(target, 'ui.Selector', Selector);
+ expose(target, 'ui.Collection', Collection);
+ expose(target, 'ui.ReflowQueue', ReflowQueue);
+ expose(target, 'ui.Control', Control);
+ expose(target, 'ui.Factory', Factory);
+ expose(target, 'ui.KeyboardNavigation', KeyboardNavigation);
+ expose(target, 'ui.Container', Container);
+ expose(target, 'ui.DragHelper', DragHelper);
+ expose(target, 'ui.Scrollable', Scrollable);
+ expose(target, 'ui.Panel', Panel);
+ expose(target, 'ui.Movable', Movable);
+ expose(target, 'ui.Resizable', Resizable);
+ expose(target, 'ui.FloatPanel', FloatPanel);
+ expose(target, 'ui.Window', Window);
+ expose(target, 'ui.MessageBox', MessageBox);
+ expose(target, 'ui.Tooltip', Tooltip);
+ expose(target, 'ui.Widget', Widget);
+ expose(target, 'ui.Progress', Progress);
+ expose(target, 'ui.Notification', Notification);
+ expose(target, 'ui.Layout', Layout);
+ expose(target, 'ui.AbsoluteLayout', AbsoluteLayout);
+ expose(target, 'ui.Button', Button);
+ expose(target, 'ui.ButtonGroup', ButtonGroup);
+ expose(target, 'ui.Checkbox', Checkbox);
+ expose(target, 'ui.ComboBox', ComboBox);
+ expose(target, 'ui.ColorBox', ColorBox);
+ expose(target, 'ui.PanelButton', PanelButton);
+ expose(target, 'ui.ColorButton', ColorButton);
+ expose(target, 'ui.ColorPicker', ColorPicker);
+ expose(target, 'ui.Path', Path);
+ expose(target, 'ui.ElementPath', ElementPath);
+ expose(target, 'ui.FormItem', FormItem);
+ expose(target, 'ui.Form', Form);
+ expose(target, 'ui.FieldSet', FieldSet);
+ expose(target, 'ui.FilePicker', FilePicker);
+ expose(target, 'ui.FitLayout', FitLayout);
+ expose(target, 'ui.FlexLayout', FlexLayout);
+ expose(target, 'ui.FlowLayout', FlowLayout);
+ expose(target, 'ui.FormatControls', FormatControls);
+ expose(target, 'ui.GridLayout', GridLayout);
+ expose(target, 'ui.Iframe', Iframe);
+ expose(target, 'ui.InfoBox', InfoBox);
+ expose(target, 'ui.Label', Label);
+ expose(target, 'ui.Toolbar', Toolbar);
+ expose(target, 'ui.MenuBar', MenuBar);
+ expose(target, 'ui.MenuButton', MenuButton);
+ expose(target, 'ui.MenuItem', MenuItem);
+ expose(target, 'ui.Throbber', Throbber);
+ expose(target, 'ui.Menu', Menu);
+ expose(target, 'ui.ListBox', ListBox);
+ expose(target, 'ui.Radio', Radio);
+ expose(target, 'ui.ResizeHandle', ResizeHandle);
+ expose(target, 'ui.SelectBox', SelectBox);
+ expose(target, 'ui.Slider', Slider);
+ expose(target, 'ui.Spacer', Spacer);
+ expose(target, 'ui.SplitButton', SplitButton);
+ expose(target, 'ui.StackLayout', StackLayout);
+ expose(target, 'ui.TabPanel', TabPanel);
+ expose(target, 'ui.TextBox', TextBox);
+ expose(target, 'ui.Api', Api);
+ };
+
+ var Api = {
+ appendTo: appendTo
+ };
+
+ return Api;
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Tinymce.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.core.api.Tinymce',
+ [
+ 'tinymce.core.geom.Rect',
+ 'tinymce.core.util.Promise',
+ 'tinymce.core.util.Delay',
+ 'tinymce.core.Env',
+ 'tinymce.core.dom.EventUtils',
+ 'tinymce.core.dom.Sizzle',
+ 'tinymce.core.util.Tools',
+ 'tinymce.core.dom.DomQuery',
+ 'tinymce.core.html.Styles',
+ 'tinymce.core.dom.TreeWalker',
+ 'tinymce.core.html.Entities',
+ 'tinymce.core.dom.DOMUtils',
+ 'tinymce.core.dom.ScriptLoader',
+ 'tinymce.core.AddOnManager',
+ 'tinymce.core.dom.RangeUtils',
+ 'tinymce.core.html.Node',
+ 'tinymce.core.html.Schema',
+ 'tinymce.core.html.SaxParser',
+ 'tinymce.core.html.DomParser',
+ 'tinymce.core.html.Writer',
+ 'tinymce.core.html.Serializer',
+ 'tinymce.core.dom.Serializer',
+ 'tinymce.core.util.VK',
+ 'tinymce.core.dom.ControlSelection',
+ 'tinymce.core.dom.BookmarkManager',
+ 'tinymce.core.dom.Selection',
+ 'tinymce.core.Formatter',
+ 'tinymce.core.UndoManager',
+ 'tinymce.core.EditorCommands',
+ 'tinymce.core.util.URI',
+ 'tinymce.core.util.Class',
+ 'tinymce.core.util.EventDispatcher',
+ 'tinymce.core.util.Observable',
+ 'tinymce.core.WindowManager',
+ 'tinymce.core.NotificationManager',
+ 'tinymce.core.EditorObservable',
+ 'tinymce.core.Shortcuts',
+ 'tinymce.core.Editor',
+ 'tinymce.core.util.I18n',
+ 'tinymce.core.FocusManager',
+ 'tinymce.core.EditorManager',
+ 'tinymce.core.util.XHR',
+ 'tinymce.core.util.JSON',
+ 'tinymce.core.util.JSONRequest',
+ 'tinymce.core.util.JSONP',
+ 'tinymce.core.util.LocalStorage',
+ 'tinymce.core.api.Compat',
+ 'tinymce.core.util.Color',
+ 'tinymce.core.ui.Api'
+ ],
+ function (
+ Rect, Promise, Delay, Env, EventUtils, Sizzle, Tools, DomQuery, Styles, TreeWalker, Entities, DOMUtils, ScriptLoader, AddOnManager,
+ RangeUtils, Node, Schema, SaxParser, DomParser, Writer, HtmlSerializer, DomSerializer, VK, ControlSelection, BookmarkManager, Selection,
+ Formatter, UndoManager, EditorCommands, URI, Class, EventDispatcher, Observable, WindowManager,
+ NotificationManager, EditorObservable, Shortcuts, Editor, I18n, FocusManager, EditorManager,
+ XHR, JSON, JSONRequest, JSONP, LocalStorage, Compat, Color, Api
+ ) {
+ var tinymce = EditorManager;
+
+ var expose = function (target, id, ref) {
+ var i, fragments;
+
+ fragments = id.split(/[.\/]/);
+ for (i = 0; i < fragments.length - 1; ++i) {
+ if (target[fragments[i]] === undefined) {
+ target[fragments[i]] = {};
+ }
+
+ target = target[fragments[i]];
+ }
+
+ target[fragments[fragments.length - 1]] = ref;
+ };
+
+ expose(tinymce, 'geom.Rect', Rect);
+ expose(tinymce, 'util.Promise', Promise);
+ expose(tinymce, 'util.Delay', Delay);
+ expose(tinymce, 'Env', Env);
+ expose(tinymce, 'dom.EventUtils', EventUtils);
+ expose(tinymce, 'dom.Sizzle', Sizzle);
+ expose(tinymce, 'util.Tools', Tools);
+ expose(tinymce, 'dom.DomQuery', DomQuery);
+ expose(tinymce, 'html.Styles', Styles);
+ expose(tinymce, 'dom.TreeWalker', TreeWalker);
+ expose(tinymce, 'html.Entities', Entities);
+ expose(tinymce, 'dom.DOMUtils', DOMUtils);
+ expose(tinymce, 'dom.ScriptLoader', ScriptLoader);
+ expose(tinymce, 'AddOnManager', AddOnManager);
+ expose(tinymce, 'dom.RangeUtils', RangeUtils);
+ expose(tinymce, 'html.Node', Node);
+ expose(tinymce, 'html.Schema', Schema);
+ expose(tinymce, 'html.SaxParser', SaxParser);
+ expose(tinymce, 'html.DomParser', DomParser);
+ expose(tinymce, 'html.Writer', Writer);
+ expose(tinymce, 'html.Serializer', HtmlSerializer);
+ expose(tinymce, 'dom.Serializer', DomSerializer);
+ expose(tinymce, 'util.VK', VK);
+ expose(tinymce, 'dom.ControlSelection', ControlSelection);
+ expose(tinymce, 'dom.BookmarkManager', BookmarkManager);
+ expose(tinymce, 'dom.Selection', Selection);
+ expose(tinymce, 'Formatter', Formatter);
+ expose(tinymce, 'UndoManager', UndoManager);
+ expose(tinymce, 'EditorCommands', EditorCommands);
+ expose(tinymce, 'util.URI', URI);
+ expose(tinymce, 'util.Class', Class);
+ expose(tinymce, 'util.EventDispatcher', EventDispatcher);
+ expose(tinymce, 'util.Observable', Observable);
+ expose(tinymce, 'WindowManager', WindowManager);
+ expose(tinymce, 'NotificationManager', NotificationManager);
+ expose(tinymce, 'EditorObservable', EditorObservable);
+ expose(tinymce, 'Shortcuts', Shortcuts);
+ expose(tinymce, 'Editor', Editor);
+ expose(tinymce, 'util.I18n', I18n);
+ expose(tinymce, 'FocusManager', FocusManager);
+ expose(tinymce, 'EditorManager', EditorManager);
+ expose(tinymce, 'util.XHR', XHR);
+ expose(tinymce, 'util.JSON', JSON);
+ expose(tinymce, 'util.JSONRequest', JSONRequest);
+ expose(tinymce, 'util.JSONP', JSONP);
+ expose(tinymce, 'util.LocalStorage', LocalStorage);
+ expose(tinymce, 'Compat', Compat);
+ expose(tinymce, 'util.Color', Color);
+
+ Api.appendTo(tinymce);
+
+ Compat.register(tinymce);
+
+ return tinymce;
+ }
+);
+
+/**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Register.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -49184,29 +54487,65 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @private
</span><span class="cx" style="display: block; padding: 0 10px"> * @class tinymce.Register
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-define("tinymce/Register", [
-], function() {
- /*eslint consistent-this: 0 */
- var context = this || window;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define(
+ 'tinymce.core.Register',
+ [
+ ],
+ function () {
+ /*eslint consistent-this: 0 */
+ var context = this || window;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var tinymce = function() {
- return context.tinymce;
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var exposeToModuleLoaders = function (tinymce) {
+ if (typeof context.define === "function") {
+ // Bolt
+ if (!context.define.amd) {
+ context.define("ephox/tinymce", [], function () {
+ return tinymce;
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof context.define === "function") {
- // Bolt
- if (!context.define.amd) {
- context.define("ephox/tinymce", [], tinymce);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ context.define("tinymce.core.EditorManager", [], function () {
+ return tinymce;
+ });
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof module === 'object') {
- /* global module */
- module.exports = window.tinymce;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof module === 'object') {
+ /* global module */
+ module.exports = tinymce;
+ }
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return {};
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return {
+ exposeToModuleLoaders: exposeToModuleLoaders
+ };
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-expose(["tinymce/geom/Rect","tinymce/util/Promise","tinymce/util/Delay","tinymce/Env","tinymce/dom/EventUtils","tinymce/dom/Sizzle","tinymce/util/Tools","tinymce/dom/DomQuery","tinymce/html/Styles","tinymce/dom/TreeWalker","tinymce/html/Entities","tinymce/dom/DOMUtils","tinymce/dom/ScriptLoader","tinymce/AddOnManager","tinymce/dom/RangeUtils","tinymce/html/Node","tinymce/html/Schema","tinymce/html/SaxParser","tinymce/html/DomParser","tinymce/html/Writer","tinymce/html/Serializer","tinymce/dom/Serializer","tinymce/util/VK","tinymce/dom/ControlSelection","tinymce/dom/BookmarkManager","tinymce/dom/Selection","tinymce/Formatter&quo
t;,"tinymce/UndoManager","tinymce/EditorCommands","tinymce/util/URI","tinymce/util/Class","tinymce/util/EventDispatcher","tinymce/util/Observable","tinymce/ui/Selector","tinymce/ui/Collection","tinymce/ui/ReflowQueue","tinymce/ui/Control","tinymce/ui/Factory","tinymce/ui/KeyboardNavigation","tinymce/ui/Container","tinymce/ui/DragHelper","tinymce/ui/Scrollable","tinymce/ui/Panel","tinymce/ui/Movable","tinymce/ui/Resizable","tinymce/ui/FloatPanel","tinymce/ui/Window","tinymce/ui/MessageBox","tinymce/WindowManager","tinymce/ui/Tooltip","tinymce/ui/Widget","tinymce/ui/Progress","tinymce/ui/Notification","tinymce/NotificationManager","tinymce/EditorObservable","tinymce/Shortcuts","tinymce/Editor&qu
ot;,"tinymce/util/I18n","tinymce/FocusManager","tinymce/EditorManager","tinymce/util/XHR","tinymce/util/JSON","tinymce/util/JSONRequest","tinymce/util/JSONP","tinymce/util/LocalStorage","tinymce/Compat","tinymce/ui/Layout","tinymce/ui/AbsoluteLayout","tinymce/ui/Button","tinymce/ui/ButtonGroup","tinymce/ui/Checkbox","tinymce/ui/ComboBox","tinymce/ui/ColorBox","tinymce/ui/PanelButton","tinymce/ui/ColorButton","tinymce/util/Color","tinymce/ui/ColorPicker","tinymce/ui/Path","tinymce/ui/ElementPath","tinymce/ui/FormItem","tinymce/ui/Form","tinymce/ui/FieldSet","tinymce/ui/FilePicker","tinymce/ui/FitLayout","tinymce/ui/FlexLayout","tinymce/ui/FlowLayout","tinymce/ui/FormatControls","tinym
ce/ui/GridLayout","tinymce/ui/Iframe","tinymce/ui/InfoBox","tinymce/ui/Label","tinymce/ui/Toolbar","tinymce/ui/MenuBar","tinymce/ui/MenuButton","tinymce/ui/MenuItem","tinymce/ui/Throbber","tinymce/ui/Menu","tinymce/ui/ListBox","tinymce/ui/Radio","tinymce/ui/ResizeHandle","tinymce/ui/SelectBox","tinymce/ui/Slider","tinymce/ui/Spacer","tinymce/ui/SplitButton","tinymce/ui/StackLayout","tinymce/ui/TabPanel","tinymce/ui/TextBox"]);
-})(window);
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Main.js
+ *
+ * Released under LGPL License.
+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+define(
+ 'tinymce.core.api.Main',
+ [
+ 'tinymce.core.api.Tinymce',
+ 'tinymce.core.Register'
+ ],
+ function (tinymce, Register) {
+ return function () {
+ window.tinymce = tinymce;
+ window.tinyMCE = tinymce;
+ Register.exposeToModuleLoaders(tinymce);
+ return tinymce;
+ };
+ }
+);
+
+dem('tinymce.core.api.Main')();
+})();
</ins></span></pre></div>
<a id="trunksrcwpincludesjstinymcetinymceminjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/tinymce.min.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/tinymce.min.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/tinymce.min.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,14 +1,15 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// 4.5.6 (2017-03-30)
-!function(e,t){"use strict";function n(e,t){for(var n,r=[],i=0;i<e.length;++i){if(n=s[e[i]]||o(e[i]),!n)throw"module definition dependecy not found: "+e[i];r.push(n)}t.apply(null,r)}function r(e,r,i){if("string"!=typeof e)throw"invalid module definition, module id must be defined and be a string";if(r===t)throw"invalid module definition, dependencies must be specified";if(i===t)throw"invalid module definition, definition function must be specified";n(r,function(){s[e]=i.apply(null,arguments)})}function i(e){return!!s[e]}function o(t){for(var n=e,r=t.split(/[.\/]/),i=0;i<r.length;++i){if(!n[r[i]])return;n=n[r[i]]}return n}function a(n){var r,i,o,a,l;for(r=0;r<n.length;r++){i=e,o=n[r],a=o.split(/[.\/]/);for(var u=0;u<a.length-1;++u)i[a[u]]===t&&(i[a[u]]={}),i=i[a[u]];i[a[a.length-1]]=s[o]}if(e.AMDLC_TESTS){l=e.privateModules||{};for(o in s)l[o]=s[o];for(r=0;r<n.length;r++)delete l[n[r]];e.privateModules
=l}}var s={},l="tinymce/geom/Rect",u="tinymce/util/Promise",c="tinymce/util/Delay",d="tinymce/Env",f="tinymce/dom/EventUtils",p="tinymce/dom/Sizzle",h="tinymce/util/Arr",m="tinymce/util/Tools",g="tinymce/dom/DomQuery",v="tinymce/html/Styles",y="tinymce/dom/TreeWalker",b="tinymce/dom/Range",C="tinymce/html/Entities",x="tinymce/dom/StyleSheetLoader",w="tinymce/dom/DOMUtils",E="tinymce/dom/ScriptLoader",N="tinymce/AddOnManager",_="tinymce/dom/NodeType",S="tinymce/text/Zwsp",k="tinymce/caret/CaretContainer",T="tinymce/dom/RangeUtils",R="tinymce/NodeChange",A="tinymce/html/Node",B="tinymce/html/Schema",D="tinymce/html/SaxParser",L="tinymce/html/DomParser",M="tinymce/html/Writer",P="tinymce/html/Serializer",O=&quo
t;tinymce/dom/Serializer",H="tinymce/dom/TridentSelection",I="tinymce/util/VK",F="tinymce/dom/ControlSelection",z="tinymce/util/Fun",U="tinymce/caret/CaretCandidate",W="tinymce/geom/ClientRect",V="tinymce/text/ExtendingChar",$="tinymce/caret/CaretPosition",q="tinymce/caret/CaretBookmark",j="tinymce/dom/BookmarkManager",Y="tinymce/dom/Selection",X="tinymce/dom/ElementUtils",K="tinymce/fmt/Preview",G="tinymce/fmt/Hooks",J="tinymce/Formatter",Q="tinymce/undo/Diff",Z="tinymce/undo/Fragments",ee="tinymce/undo/Levels",te="tinymce/UndoManager",ne="tinymce/EnterKey",re="tinymce/ForceBlocks",ie="tinymce/caret/CaretUtils",oe="tinymce/caret/CaretWalker",ae="tinymce/InsertList",se="tinymce/InsertContent",le="tinymce/EditorCommands",ue
="tinymce/util/URI",ce="tinymce/util/Class",de="tinymce/util/EventDispatcher",fe="tinymce/data/Binding",pe="tinymce/util/Observable",he="tinymce/data/ObservableObject",me="tinymce/ui/Selector",ge="tinymce/ui/Collection",ve="tinymce/ui/DomUtils",ye="tinymce/ui/BoxUtils",be="tinymce/ui/ClassList",Ce="tinymce/ui/ReflowQueue",xe="tinymce/ui/Control",we="tinymce/ui/Factory",Ee="tinymce/ui/KeyboardNavigation",Ne="tinymce/ui/Container",_e="tinymce/ui/DragHelper",Se="tinymce/ui/Scrollable",ke="tinymce/ui/Panel",Te="tinymce/ui/Movable",Re="tinymce/ui/Resizable",Ae="tinymce/ui/FloatPanel",Be="tinymce/ui/Window",De="tinymce/ui/MessageBox",Le="tinymce/WindowManager",Me="tinymce/ui/Tooltip",Pe="tinymce/ui/Widget",Oe="tinymce/
ui/Progress",He="tinymce/ui/Notification",Ie="tinymce/NotificationManager",Fe="tinymce/dom/NodePath",ze="tinymce/util/Quirks",Ue="tinymce/EditorObservable",We="tinymce/Mode",Ve="tinymce/Shortcuts",$e="tinymce/file/Uploader",qe="tinymce/file/Conversions",je="tinymce/file/ImageScanner",Ye="tinymce/file/BlobCache",Xe="tinymce/file/UploadStatus",Ke="tinymce/ErrorReporter",Ge="tinymce/EditorUpload",Je="tinymce/caret/FakeCaret",Qe="tinymce/dom/Dimensions",Ze="tinymce/caret/LineWalker",et="tinymce/caret/LineUtils",tt="tinymce/dom/MousePosition",nt="tinymce/DragDropOverrides",rt="tinymce/SelectionOverrides",it="tinymce/util/Uuid",ot="tinymce/ui/Sidebar",at="tinymce/Editor",st="tinymce/util/I18n",lt="tinymce/FocusManager",ut="
tinymce/EditorManager",ct="tinymce/LegacyInput",dt="tinymce/util/XHR",ft="tinymce/util/JSON",pt="tinymce/util/JSONRequest",ht="tinymce/util/JSONP",mt="tinymce/util/LocalStorage",gt="tinymce/Compat",vt="tinymce/ui/Layout",yt="tinymce/ui/AbsoluteLayout",bt="tinymce/ui/Button",Ct="tinymce/ui/ButtonGroup",xt="tinymce/ui/Checkbox",wt="tinymce/ui/ComboBox",Et="tinymce/ui/ColorBox",Nt="tinymce/ui/PanelButton",_t="tinymce/ui/ColorButton",St="tinymce/util/Color",kt="tinymce/ui/ColorPicker",Tt="tinymce/ui/Path",Rt="tinymce/ui/ElementPath",At="tinymce/ui/FormItem",Bt="tinymce/ui/Form",Dt="tinymce/ui/FieldSet",Lt="tinymce/content/LinkTargets",Mt="tinymce/ui/FilePicker",Pt="tinymce/ui/FitLayout",Ot="tinymce/ui/FlexLayout",Ht=
"tinymce/ui/FlowLayout",It="tinymce/fmt/FontInfo",Ft="tinymce/ui/FormatControls",zt="tinymce/ui/GridLayout",Ut="tinymce/ui/Iframe",Wt="tinymce/ui/InfoBox",Vt="tinymce/ui/Label",$t="tinymce/ui/Toolbar",qt="tinymce/ui/MenuBar",jt="tinymce/ui/MenuButton",Yt="tinymce/ui/MenuItem",Xt="tinymce/ui/Throbber",Kt="tinymce/ui/Menu",Gt="tinymce/ui/ListBox",Jt="tinymce/ui/Radio",Qt="tinymce/ui/ResizeHandle",Zt="tinymce/ui/SelectBox",en="tinymce/ui/Slider",tn="tinymce/ui/Spacer",nn="tinymce/ui/SplitButton",rn="tinymce/ui/StackLayout",on="tinymce/ui/TabPanel",an="tinymce/ui/TextBox",sn="tinymce/Register";r(l,[],function(){function e(e,t,n){var r,i,a,s,l,c;return r=t.x,i=t.y,a=e.w,s=e.h,l=t.w,c=t.h,n=(n||"").split(""),"b"===n[0]&
&(i+=c),"r"===n[1]&&(r+=l),"c"===n[0]&&(i+=u(c/2)),"c"===n[1]&&(r+=u(l/2)),"b"===n[3]&&(i-=s),"r"===n[4]&&(r-=a),"c"===n[3]&&(i-=u(s/2)),"c"===n[4]&&(r-=u(a/2)),o(r,i,a,s)}function t(t,n,r,i){var o,a;for(a=0;a<i.length;a++)if(o=e(t,n,i[a]),o.x>=r.x&&o.x+o.w<=r.w+r.x&&o.y>=r.y&&o.y+o.h<=r.h+r.y)return i[a];return null}function n(e,t,n){return o(e.x-t,e.y-n,e.w+2*t,e.h+2*n)}function r(e,t){var n,r,i,a;return n=l(e.x,t.x),r=l(e.y,t.y),i=s(e.x+e.w,t.x+t.w),a=s(e.y+e.h,t.y+t.h),i-n<0||a-r<0?null:o(n,r,i-n,a-r)}function i(e,t,n){var r,i,a,s,u,c,d,f,p,h;return u=e.x,c=e.y,d=e.x+e.w,f=e.y+e.h,p=t.x+t.w,h=t.y+t.h,r=l(0,t.x-u),i=l(0,t.y-c),a=l(0,d-p),s=l(0,f-h),u+=r,c+=i,n&&(d+=r,f+=i,u-=a,c-=s),d-=a,f-=s,o(u,c,d-u,f-c)}function o(e,t,n,r){return{x:e,y:t,w:n,h:r}}function a(e){return o(e.left,e.top,e.width,e.heig
ht)}var s=Math.min,l=Math.max,u=Math.round;return{inflate:n,relativePosition:e,findBestRelativePosition:t,intersect:r,clamp:i,create:o,fromClientRect:a}}),r(u,[],function(){function e(e,t){return function(){e.apply(t,arguments)}}function t(t){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof t)throw new TypeError("not a function");this._state=null,this._value=null,this._deferreds=[],s(t,e(r,this),e(i,this))}function n(e){var t=this;return null===this._state?void this._deferreds.push(e):void l(function(){var n=t._state?e.onFulfilled:e.onRejected;if(null===n)return void(t._state?e.resolve:e.reject)(t._value);var r;try{r=n(t._value)}catch(i){return void e.reject(i)}e.resolve(r)})}function r(t){try{if(t===this)throw new TypeError("A promise cannot be resolved with itself.");if(t&&("object"==typeof t||"function"==typeof t)){var n=t.then;if("function&
quot;==typeof n)return void s(e(n,t),e(r,this),e(i,this))}this._state=!0,this._value=t,o.call(this)}catch(a){i.call(this,a)}}function i(e){this._state=!1,this._value=e,o.call(this)}function o(){for(var e=0,t=this._deferreds.length;e<t;e++)n.call(this,this._deferreds[e]);this._deferreds=null}function a(e,t,n,r){this.onFulfilled="function"==typeof e?e:null,this.onRejected="function"==typeof t?t:null,this.resolve=n,this.reject=r}function s(e,t,n){var r=!1;try{e(function(e){r||(r=!0,t(e))},function(e){r||(r=!0,n(e))})}catch(i){if(r)return;r=!0,n(i)}}if(window.Promise)return window.Promise;var l=t.immediateFn||"function"==typeof setImmediate&&setImmediate||function(e){setTimeout(e,1)},u=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)};return t.prototype["catch"]=function(e){return this.then(null,e)},t.prototype.then=function(e,r){var i=this;return new t(function(t,o){n.call(i,new a(e,r,t,o)
)})},t.all=function(){var e=Array.prototype.slice.call(1===arguments.length&&u(arguments[0])?arguments[0]:arguments);return new t(function(t,n){function r(o,a){try{if(a&&("object"==typeof a||"function"==typeof a)){var s=a.then;if("function"==typeof s)return void s.call(a,function(e){r(o,e)},n)}e[o]=a,0===--i&&t(e)}catch(l){n(l)}}if(0===e.length)return t([]);for(var i=e.length,o=0;o<e.length;o++)r(o,e[o])})},t.resolve=function(e){return e&&"object"==typeof e&&e.constructor===t?e:new t(function(t){t(e)})},t.reject=function(e){return new t(function(t,n){n(e)})},t.race=function(e){return new t(function(t,n){for(var r=0,i=e.length;r<i;r++)e[r].then(t,n)})},t}),r(c,[u],function(e){function t(e,t){function n(e){window.setTimeout(e,0)}var r,i=window.requestAnimationFrame,o=["ms","moz","webkit"];for(r=0;r<o.length&&!i;r++)i=window[o[r]+"RequestAnimationFrame&quo
t;];i||(i=n),i(e,t)}function n(e,t){return"number"!=typeof t&&(t=0),setTimeout(e,t)}function r(e,t){return"number"!=typeof t&&(t=1),setInterval(e,t)}function i(e){return clearTimeout(e)}function o(e){return clearInterval(e)}function a(e,t){var r,i;return i=function(){var i=arguments;clearTimeout(r),r=n(function(){e.apply(this,i)},t)},i.stop=function(){clearTimeout(r)},i}var s;return{requestAnimationFrame:function(n,r){return s?void s.then(n):void(s=new e(function(e){r||(r=document.body),t(e,r)}).then(n))},setTimeout:n,setInterval:r,setEditorTimeout:function(e,t,r){return n(function(){e.removed||t()},r)},setEditorInterval:function(e,t,n){var i;return i=r(function(){e.removed?clearInterval(i):t()},n)},debounce:a,throttle:a,clearInterval:o,clearTimeout:i}}),r(d,[],function(){function e(e){return"matchMedia"in window&&matchMedia(e).matches}var t=navigator,n=t.userAgent,r,i,o,a,s,l,u,c,d,f,p,h,m;r=window.opera&&window.opera.bu
ildNumber,d=/Android/.test(n),i=/WebKit/.test(n),o=!i&&!r&&/MSIE/gi.test(n)&&/Explorer/gi.test(t.appName),o=o&&/MSIE (\w+)\./.exec(n)[1],a=n.indexOf("Trident/")!=-1&&(n.indexOf("rv:")!=-1||t.appName.indexOf("Netscape")!=-1)&&11,s=n.indexOf("Edge/")!=-1&&!o&&!a&&12,o=o||a||s,l=!i&&!a&&/Gecko/.test(n),u=n.indexOf("Mac")!=-1,c=/(iPad|iPhone)/.test(n),f="FormData"in window&&"FileReader"in window&&"URL"in window&&!!URL.createObjectURL,p=e("only screen and (max-device-width: 480px)")&&(d||c),h=e("only screen and (min-width: 800px)")&&(d||c),m=n.indexOf("Windows Phone")!=-1,s&&(i=!1);var g=!c||f||n.match(/AppleWebKit\/(\d*)/)[1]>=534;return{opera:r,webkit:i,ie:o,gecko:l,mac:u,iOS:c,android:d,contentEditable:g,transparentSrc:"data:image/gif;
base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",caretAfter:8!=o,range:window.getSelection&&"Range"in window,documentMode:o&&!s?document.documentMode||7:10,fileApi:f,ceFalse:o===!1||o>8,canHaveCSP:o===!1||o>11,desktop:!p&&!h,windowsPhone:m}}),r(f,[c,d],function(e,t){function n(e,t,n,r){e.addEventListener?e.addEventListener(t,n,r||!1):e.attachEvent&&e.attachEvent("on"+t,n)}function r(e,t,n,r){e.removeEventListener?e.removeEventListener(t,n,r||!1):e.detachEvent&&e.detachEvent("on"+t,n)}function i(e,t){var n,r=t;return n=e.path,n&&n.length>0&&(r=n[0]),e.deepPath&&(n=e.deepPath(),n&&n.length>0&&(r=n[0])),r}function o(e,n){function r(){return!1}function o(){return!0}var a,s=n||{},l;for(a in e)c[a]||(s[a]=e[a]);if(s.target||(s.target=s.srcElement||document),t.experimentalShadowDom&&(s.target=i(e,s.target)),e&&u.test(e.type)&&
;e.pageX===l&&e.clientX!==l){var d=s.target.ownerDocument||document,f=d.documentElement,p=d.body;s.pageX=e.clientX+(f&&f.scrollLeft||p&&p.scrollLeft||0)-(f&&f.clientLeft||p&&p.clientLeft||0),s.pageY=e.clientY+(f&&f.scrollTop||p&&p.scrollTop||0)-(f&&f.clientTop||p&&p.clientTop||0)}return s.preventDefault=function(){s.isDefaultPrevented=o,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},s.stopPropagation=function(){s.isPropagationStopped=o,e&&(e.stopPropagation?e.stopPropagation():e.cancelBubble=!0)},s.stopImmediatePropagation=function(){s.isImmediatePropagationStopped=o,s.stopPropagation()},s.isDefaultPrevented||(s.isDefaultPrevented=r,s.isPropagationStopped=r,s.isImmediatePropagationStopped=r),"undefined"==typeof s.metaKey&&(s.metaKey=!1),s}function a(t,i,o){function a(){o.domLoaded||(o.domLoaded=!0,i(c))}function s(){("complete"===u.readyState||"interac
tive"===u.readyState&&u.body)&&(r(u,"readystatechange",s),a())}function l(){try{u.documentElement.doScroll("left")}catch(t){return void e.setTimeout(l)}a()}var u=t.document,c={type:"ready"};return o.domLoaded?void i(c):(u.addEventListener?"complete"===u.readyState?a():n(t,"DOMContentLoaded",a):(n(u,"readystatechange",s),u.documentElement.doScroll&&t.self===t.top&&l()),void n(t,"load",a))}function s(){function e(e,t){var n,r,o,a,s=i[t];if(n=s&&s[e.type])for(r=0,o=n.length;r<o;r++)if(a=n[r],a&&a.func.call(a.scope,e)===!1&&e.preventDefault(),e.isImmediatePropagationStopped())return}var t=this,i={},s,u,c,d,f;u=l+(+new Date).toString(32),d="onmouseenter"in document.documentElement,c="onfocusin"in document.documentElement,f={mouseenter:"mouseover",mouseleave:"mouseout"},s=1,t.domLoaded=!1,t.events=i,t.bind=function(r,
l,p,h){function m(t){e(o(t||E.event),g)}var g,v,y,b,C,x,w,E=window;if(r&&3!==r.nodeType&&8!==r.nodeType){for(r[u]?g=r[u]:(g=s++,r[u]=g,i[g]={}),h=h||r,l=l.split(" "),y=l.length;y--;)b=l[y],x=m,C=w=!1,"DOMContentLoaded"===b&&(b="ready"),t.domLoaded&&"ready"===b&&"complete"==r.readyState?p.call(h,o({type:b})):(d||(C=f[b],C&&(x=function(t){var n,r;if(n=t.currentTarget,r=t.relatedTarget,r&&n.contains)r=n.contains(r);else for(;r&&r!==n;)r=r.parentNode;r||(t=o(t||E.event),t.type="mouseout"===t.type?"mouseleave":"mouseenter",t.target=n,e(t,g))})),c||"focusin"!==b&&"focusout"!==b||(w=!0,C="focusin"===b?"focus":"blur",x=function(t){t=o(t||E.event),t.type="focus"===t.type?"focusin":"focusout",e(t,g)}),v=i[g][b],v?"ready"===b&&t.domLoaded?p({type:b
}):v.push({func:p,scope:h}):(i[g][b]=v=[{func:p,scope:h}],v.fakeName=C,v.capture=w,v.nativeHandler=x,"ready"===b?a(r,x,t):n(r,C||b,x,w)));return r=v=0,p}},t.unbind=function(e,n,o){var a,s,l,c,d,f;if(!e||3===e.nodeType||8===e.nodeType)return t;if(a=e[u]){if(f=i[a],n){for(n=n.split(" "),l=n.length;l--;)if(d=n[l],s=f[d]){if(o)for(c=s.length;c--;)if(s[c].func===o){var p=s.nativeHandler,h=s.fakeName,m=s.capture;s=s.slice(0,c).concat(s.slice(c+1)),s.nativeHandler=p,s.fakeName=h,s.capture=m,f[d]=s}o&&0!==s.length||(delete f[d],r(e,s.fakeName||d,s.nativeHandler,s.capture))}}else{for(d in f)s=f[d],r(e,s.fakeName||d,s.nativeHandler,s.capture);f={}}for(d in f)return t;delete i[a];try{delete e[u]}catch(g){e[u]=null}}return t},t.fire=function(n,r,i){var a;if(!n||3===n.nodeType||8===n.nodeType)return t;i=o(null,i),i.type=r,i.target=n;do a=n[u],a&&e(i,a),n=n.parentNode||n.ownerDocument||n.defaultView||n.parentWindow;while(n&&!i.isPropagationStopped());re
turn t},t.clean=function(e){var n,r,i=t.unbind;if(!e||3===e.nodeType||8===e.nodeType)return t;if(e[u]&&i(e),e.getElementsByTagName||(e=e.document),e&&e.getElementsByTagName)for(i(e),r=e.getElementsByTagName("*"),n=r.length;n--;)e=r[n],e[u]&&i(e);return t},t.destroy=function(){i={}},t.cancel=function(e){return e&&(e.preventDefault(),e.stopImmediatePropagation()),!1}}var l="mce-data-",u=/^(?:mouse|contextmenu)|click/,c={keyLocation:1,layerX:1,layerY:1,returnValue:1,webkitMovementX:1,webkitMovementY:1,keyIdentifier:1};return s.Event=new s,s.Event.bind(window,"ready",function(){}),s}),r(p,[],function(){function e(e,t,n,r){var i,o,a,s,l,u,d,p,h,m;if((t?t.ownerDocument||t:z)!==D&&B(t),t=t||D,n=n||[],!e||"string"!=typeof e)return n;if(1!==(s=t.nodeType)&&9!==s)return[];if(M&&!r){if(i=ve.exec(e))if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode)return n;if(o.id===a)return n.push(o),
n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&I(t,o)&&o.id===a)return n.push(o),n}else{if(i[2])return Z.apply(n,t.getElementsByTagName(e)),n;if((a=i[3])&&x.getElementsByClassName)return Z.apply(n,t.getElementsByClassName(a)),n}if(x.qsa&&(!P||!P.test(e))){if(p=d=F,h=t,m=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){for(u=_(e),(d=t.getAttribute("id"))?p=d.replace(be,"\\$&"):t.setAttribute("id",p),p="[id='"+p+"'] ",l=u.length;l--;)u[l]=p+f(u[l]);h=ye.test(e)&&c(t.parentNode)||t,m=u.join(",")}if(m)try{return Z.apply(n,h.querySelectorAll(m)),n}catch(g){}finally{d||t.removeAttribute("id")}}}return k(e.replace(se,"$1"),t,n,r)}function n(){function e(n,r){return t.push(n+" ")>w.cacheLength&&delete e[t.shift()],e[n+" "]=r}var t=[];return e}function r(e){return e[F]=!0,e}function
i(e){var t=D.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function o(e,t){for(var n=e.split("|"),r=e.length;r--;)w.attrHandle[n[r]]=t}function a(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||X)-(~e.sourceIndex||X);if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function s(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function l(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function u(e){return r(function(t){return t=+t,r(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function c(e){return e&&typeof e.getElementsByTagName!==Y&&e}function d(){}function f(e){for(var t=0,n=e.length,r="";t<n;t++)
r+=e[t].value;return r}function p(e,t,n){var r=t.dir,i=n&&"parentNode"===r,o=W++;return t.first?function(t,n,o){for(;t=t[r];)if(1===t.nodeType||i)return e(t,n,o)}:function(t,n,a){var s,l,u=[U,o];if(a){for(;t=t[r];)if((1===t.nodeType||i)&&e(t,n,a))return!0}else for(;t=t[r];)if(1===t.nodeType||i){if(l=t[F]||(t[F]={}),(s=l[r])&&s[0]===U&&s[1]===o)return u[2]=s[2];if(l[r]=u,u[2]=e(t,n,a))return!0}}}function h(e){return e.length>1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function m(t,n,r){for(var i=0,o=n.length;i<o;i++)e(t,n[i],r);return r}function g(e,t,n,r,i){for(var o,a=[],s=0,l=e.length,u=null!=t;s<l;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),u&&t.push(s)));return a}function v(e,t,n,i,o,a){return i&&!i[F]&&(i=v(i)),o&&!o[F]&&(o=v(o,a)),r(function(r,a,s,l){var u,c,d,f=[],p=[],h=a.length,v=r||m(t||"*",s.nodeType?[s]:s,[]),y=!e||!r&
&t?v:g(v,f,e,s,l),b=n?o||(r?e:h||i)?[]:a:y;if(n&&n(y,b,s,l),i)for(u=g(b,p),i(u,[],s,l),c=u.length;c--;)(d=u[c])&&(b[p[c]]=!(y[p[c]]=d));if(r){if(o||e){if(o){for(u=[],c=b.length;c--;)(d=b[c])&&u.push(y[c]=d);o(null,b=[],u,l)}for(c=b.length;c--;)(d=b[c])&&(u=o?te.call(r,d):f[c])>-1&&(r[u]=!(a[u]=d))}}else b=g(b===a?b.splice(h,b.length):b),o?o(null,a,b,l):Z.apply(a,b)})}function y(e){for(var t,n,r,i=e.length,o=w.relative[e[0].type],a=o||w.relative[" "],s=o?1:0,l=p(function(e){return e===t},a,!0),u=p(function(e){return te.call(t,e)>-1},a,!0),c=[function(e,n,r){return!o&&(r||n!==T)||((t=n).nodeType?l(e,n,r):u(e,n,r))}];s<i;s++)if(n=w.relative[e[s].type])c=[p(h(c),n)];else{if(n=w.filter[e[s].type].apply(null,e[s].matches),n[F]){for(r=++s;r<i&&!w.relative[e[r].type];r++);return v(s>1&&h(c),s>1&&f(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).repla
ce(se,"$1"),n,s<r&&y(e.slice(s,r)),r<i&&y(e=e.slice(r)),r<i&&f(e))}c.push(n)}return h(c)}function b(t,n){var i=n.length>0,o=t.length>0,a=function(r,a,s,l,u){var c,d,f,p=0,h="0",m=r&&[],v=[],y=T,b=r||o&&w.find.TAG("*",u),C=U+=null==y?1:Math.random()||.1,x=b.length;for(u&&(T=a!==D&&a);h!==x&&null!=(c=b[h]);h++){if(o&&c){for(d=0;f=t[d++];)if(f(c,a,s)){l.push(c);break}u&&(U=C)}i&&((c=!f&&c)&&p--,r&&m.push(c))}if(p+=h,i&&h!==p){for(d=0;f=n[d++];)f(m,v,a,s);if(r){if(p>0)for(;h--;)m[h]||v[h]||(v[h]=J.call(l));v=g(v)}Z.apply(l,v),u&&!r&&v.length>0&&p+n.length>1&&e.uniqueSort(l)}return u&&(U=C,T=y),m};return i?r(a):a}var C,x,w,E,N,_,S,k,T,R,A,B,D,L,M,P,O,H,I,F="sizzle"+-new Date,z=window.document,U=0,W=0,V=n(),$=n(),q=n(),j=function(e,t){return e===t&&(A=!0),0},Y=
typeof t,X=1<<31,K={}.hasOwnProperty,G=[],J=G.pop,Q=G.push,Z=G.push,ee=G.slice,te=G.indexOf||function(e){for(var t=0,n=this.length;t<n;t++)if(this[t]===e)return t;return-1},ne="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",re="[\\x20\\t\\r\\n\\f]",ie="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",oe="\\["+re+"*("+ie+")(?:"+re+"*([*^$|!~]?=)"+re+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+ie+"))|)"+re+"*\\]",ae=":("+ie+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+oe+")*)|.*)\\)|)",se=new RegExp("^"+re+"+|((?:^|[^\\\\])(?:\\\\.)*)"+re+"+$","g"),le=new RegExp("^"+re+"*,"+re+"*"),ue=new RegExp("^"+re+"*([>+~]|&qu
ot;+re+")"+re+"*"),ce=new RegExp("="+re+"*([^\\]'\"]*?)"+re+"*\\]","g"),de=new RegExp(ae),fe=new RegExp("^"+ie+"$"),pe={ID:new RegExp("^#("+ie+")"),CLASS:new RegExp("^\\.("+ie+")"),TAG:new RegExp("^("+ie+"|[*])"),ATTR:new RegExp("^"+oe),PSEUDO:new RegExp("^"+ae),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+re+"*(even|odd|(([+-]|)(\\d*)n|)"+re+"*(?:([+-]|)"+re+"*(\\d+)|))"+re+"*\\)|)","i"),bool:new RegExp("^(?:"+ne+")$","i"),needsContext:new RegExp("^"+re+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+re+"*((?:-\\d)?\\d*)"+re+"*\\)|)(?=[^-]|$)","i")},he=/^(?:input|select|textarea|button)$/i,me=/^h\d$/i,ge=/^[^{]+\{\s*\[native \w/,ve=/^(?:#([\w-]+)|(
\w+)|\.([\w-]+))$/,ye=/[+~]/,be=/'|\\/g,Ce=new RegExp("\\\\([\\da-f]{1,6}"+re+"?|("+re+")|.)","ig"),xe=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)};try{Z.apply(G=ee.call(z.childNodes),z.childNodes),G[z.childNodes.length].nodeType}catch(we){Z={apply:G.length?function(e,t){Q.apply(e,ee.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}x=e.support={},N=e.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},B=e.setDocument=function(e){function t(e){try{return e.top}catch(t){}return null}var n,r=e?e.ownerDocument||e:z,o=r.defaultView;return r!==D&&9===r.nodeType&&r.documentElement?(D=r,L=r.documentElement,M=!N(r),o&&o!==t(o)&&(o.addEventListener?o.addEventListener("unload",function(){B()},!1):o.attachEv
ent&&o.attachEvent("onunload",function(){B()})),x.attributes=i(function(e){return e.className="i",!e.getAttribute("className")}),x.getElementsByTagName=i(function(e){return e.appendChild(r.createComment("")),!e.getElementsByTagName("*").length}),x.getElementsByClassName=ge.test(r.getElementsByClassName),x.getById=i(function(e){return L.appendChild(e).id=F,!r.getElementsByName||!r.getElementsByName(F).length}),x.getById?(w.find.ID=function(e,t){if(typeof t.getElementById!==Y&&M){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},w.filter.ID=function(e){var t=e.replace(Ce,xe);return function(e){return e.getAttribute("id")===t}}):(delete w.find.ID,w.filter.ID=function(e){var t=e.replace(Ce,xe);return function(e){var n=typeof e.getAttributeNode!==Y&&e.getAttributeNode("id");return n&&n.value===t}}),w.find.TAG=x.getElementsByTagName?function(e,t){if(typeof t.getElementsByT
agName!==Y)return t.getElementsByTagName(e)}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},w.find.CLASS=x.getElementsByClassName&&function(e,t){if(M)return t.getElementsByClassName(e)},O=[],P=[],(x.qsa=ge.test(r.querySelectorAll))&&(i(function(e){e.innerHTML="<select msallowcapture=''><option selected=''></option></select>",e.querySelectorAll("[msallowcapture^='']").length&&P.push("[*^$]="+re+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||P.push("\\["+re+"*(?:value|"+ne+")"),e.querySelectorAll(":checked").length||P.push(":checked")}),i(function(e){var t=r.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll(
"[name=d]").length&&P.push("name"+re+"*[*^$|!~]?="),e.querySelectorAll(":enabled").length||P.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),P.push(",.*:")})),(x.matchesSelector=ge.test(H=L.matches||L.webkitMatchesSelector||L.mozMatchesSelector||L.oMatchesSelector||L.msMatchesSelector))&&i(function(e){x.disconnectedMatch=H.call(e,"div"),H.call(e,"[s!='']:x"),O.push("!=",ae)}),P=P.length&&new RegExp(P.join("|")),O=O.length&&new RegExp(O.join("|")),n=ge.test(L.compareDocumentPosition),I=n||ge.test(L.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},j=n?function(e,t){if(e===t)r
eturn A=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n?n:(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&n||!x.sortDetached&&t.compareDocumentPosition(e)===n?e===r||e.ownerDocument===z&&I(z,e)?-1:t===r||t.ownerDocument===z&&I(z,t)?1:R?te.call(R,e)-te.call(R,t):0:4&n?-1:1)}:function(e,t){if(e===t)return A=!0,0;var n,i=0,o=e.parentNode,s=t.parentNode,l=[e],u=[t];if(!o||!s)return e===r?-1:t===r?1:o?-1:s?1:R?te.call(R,e)-te.call(R,t):0;if(o===s)return a(e,t);for(n=e;n=n.parentNode;)l.unshift(n);for(n=t;n=n.parentNode;)u.unshift(n);for(;l[i]===u[i];)i++;return i?a(l[i],u[i]):l[i]===z?-1:u[i]===z?1:0},r):D},e.matches=function(t,n){return e(t,null,null,n)},e.matchesSelector=function(t,n){if((t.ownerDocument||t)!==D&&B(t),n=n.replace(ce,"='$1']"),x.matchesSelector&&M&&(!O||!O.test(n))&&(!P||!P.test(n)))try{var r=H.call(t,n);if(r||x.disconnectedMatch||t.documen
t&&11!==t.document.nodeType)return r}catch(i){}return e(n,D,null,[t]).length>0},e.contains=function(e,t){return(e.ownerDocument||e)!==D&&B(e),I(e,t)},e.attr=function(e,n){(e.ownerDocument||e)!==D&&B(e);var r=w.attrHandle[n.toLowerCase()],i=r&&K.call(w.attrHandle,n.toLowerCase())?r(e,n,!M):t;return i!==t?i:x.attributes||!M?e.getAttribute(n):(i=e.getAttributeNode(n))&&i.specified?i.value:null},e.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},e.uniqueSort=function(e){var t,n=[],r=0,i=0;if(A=!x.detectDuplicates,R=!x.sortStable&&e.slice(0),e.sort(j),A){for(;t=e[i++];)t===e[i]&&(r=n.push(i));for(;r--;)e.splice(n[r],1)}return R=null,e},E=e.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=E(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r
++];)n+=E(t);return n},w=e.selectors={cacheLength:50,createPseudo:r,match:pe,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(Ce,xe),e[3]=(e[3]||e[4]||e[5]||"").replace(Ce,xe),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(t){return t[1]=t[1].toLowerCase(),"nth"===t[1].slice(0,3)?(t[3]||e.error(t[0]),t[4]=+(t[4]?t[5]+(t[6]||1):2*("even"===t[3]||"odd"===t[3])),t[5]=+(t[7]+t[8]||"odd"===t[3])):t[3]&&e.error(t[0]),t},PSEUDO:function(e){var t,n=!e[6]&&e[2];return pe.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&de.test(n)&&(t=_(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[
0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(Ce,xe).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=V[e+" "];return t||(t=new RegExp("(^|"+re+")"+e+"("+re+"|$)"))&&V(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==Y&&e.getAttribute("class")||"")})},ATTR:function(t,n,r){return function(i){var o=e.attr(i,t);return null==o?"!="===n:!n||(o+="","="===n?o===r:"!="===n?o!==r:"^="===n?r&&0===o.indexOf(r):"*="===n?r&&o.indexOf(r)>-1:"$="===n?r&&o.slice(-r.length)===r:"~="===n?(" "+o+" ").indexOf(r)>-1:"|="===n&&(o===r||o.slice(0,r.length+1)===r+&q
uot;-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,d,f,p,h,m=o!==a?"nextSibling":"previousSibling",g=t.parentNode,v=s&&t.nodeName.toLowerCase(),y=!l&&!s;if(g){if(o){for(;m;){for(d=t;d=d[m];)if(s?d.nodeName.toLowerCase()===v:1===d.nodeType)return!1;h=m="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?g.firstChild:g.lastChild],a&&y){for(c=g[F]||(g[F]={}),u=c[e]||[],p=u[0]===U&&u[1],f=u[0]===U&&u[2],d=p&&g.childNodes[p];d=++p&&d&&d[m]||(f=p=0)||h.pop();)if(1===d.nodeType&&++f&&d===t){c[e]=[U,p,f];break}}else if(y&&(u=(t[F]||(t[F]={}))[e])&&u[0]===U)f=u[1];else for(;(d=++p&&d&&d[m]||(f=p=0)||h.pop())&&((s?d.nodeName.toLowerCase()!==v:1!==d.nodeTy
pe)||!++f||(y&&((d[F]||(d[F]={}))[e]=[U,f]),d!==t)););return f-=i,f===r||f%r===0&&f/r>=0}}},PSEUDO:function(t,n){var i,o=w.pseudos[t]||w.setFilters[t.toLowerCase()]||e.error("unsupported pseudo: "+t);return o[F]?o(n):o.length>1?(i=[t,t,"",n],w.setFilters.hasOwnProperty(t.toLowerCase())?r(function(e,t){for(var r,i=o(e,n),a=i.length;a--;)r=te.call(e,i[a]),e[r]=!(t[r]=i[a])}):function(e){return o(e,0,i)}):o}},pseudos:{not:r(function(e){var t=[],n=[],i=S(e.replace(se,"$1"));return i[F]?r(function(e,t,n,r){for(var o,a=i(e,null,r,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,r,o){return t[0]=e,i(t,null,o,n),!n.pop()}}),has:r(function(t){return function(n){return e(t,n).length>0}}),contains:r(function(e){return e=e.replace(Ce,xe),function(t){return(t.textContent||t.innerText||E(t)).indexOf(e)>-1}}),lang:r(function(t){return fe.test(t||"")||e.error("unsupported lang: "+t),t=t.replace(Ce,xe).t
oLowerCase(),function(e){var n;do if(n=M?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return n=n.toLowerCase(),n===t||0===n.indexOf(t+"-");while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var t=window.location&&window.location.hash;return t&&t.slice(1)===e.id},root:function(e){return e===L},focus:function(e){return e===D.activeElement&&(!D.hasFocus||D.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!w.pseudos.empty(e)},header:function(e){retu
rn me.test(e.nodeName)},input:function(e){return he.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:u(function(){return[0]}),last:u(function(e,t){return[t-1]}),eq:u(function(e,t,n){return[n<0?n+t:n]}),even:u(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:u(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:u(function(e,t,n){for(var r=n<0?n+t:n;--r>=0;)e.push(r);return e}),gt:u(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}},w.pseudos.nth=w.pseudos.eq;for(C in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})w.pseudos[C]=s(C);for(C in{submit:!0,reset:!0})w.pseudos[C]=l(C);return d.prototype=w.filters=w.pseudos,w.
setFilters=new d,_=e.tokenize=function(t,n){var r,i,o,a,s,l,u,c=$[t+" "];if(c)return n?0:c.slice(0);for(s=t,l=[],u=w.preFilter;s;){r&&!(i=le.exec(s))||(i&&(s=s.slice(i[0].length)||s),l.push(o=[])),r=!1,(i=ue.exec(s))&&(r=i.shift(),o.push({value:r,type:i[0].replace(se," ")}),s=s.slice(r.length));for(a in w.filter)!(i=pe[a].exec(s))||u[a]&&!(i=u[a](i))||(r=i.shift(),o.push({value:r,type:a,matches:i}),s=s.slice(r.length));if(!r)break}return n?s.length:s?e.error(t):$(t,l).slice(0)},S=e.compile=function(e,t){var n,r=[],i=[],o=q[e+" "];if(!o){for(t||(t=_(e)),n=t.length;n--;)o=y(t[n]),o[F]?r.push(o):i.push(o);o=q(e,b(i,r)),o.selector=e}return o},k=e.select=function(e,t,n,r){var i,o,a,s,l,u="function"==typeof e&&e,d=!r&&_(e=u.selector||e);
-if(n=n||[],1===d.length){if(o=d[0]=d[0].slice(0),o.length>2&&"ID"===(a=o[0]).type&&x.getById&&9===t.nodeType&&M&&w.relative[o[1].type]){if(t=(w.find.ID(a.matches[0].replace(Ce,xe),t)||[])[0],!t)return n;u&&(t=t.parentNode),e=e.slice(o.shift().value.length)}for(i=pe.needsContext.test(e)?0:o.length;i--&&(a=o[i],!w.relative[s=a.type]);)if((l=w.find[s])&&(r=l(a.matches[0].replace(Ce,xe),ye.test(o[0].type)&&c(t.parentNode)||t))){if(o.splice(i,1),e=r.length&&f(o),!e)return Z.apply(n,r),n;break}}return(u||S(e,d))(r,t,!M,n,ye.test(e)&&c(t.parentNode)||t),n},x.sortStable=F.split("").sort(j).join("")===F,x.detectDuplicates=!!A,B(),x.sortDetached=i(function(e){return 1&e.compareDocumentPosition(D.createElement("div"))}),i(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||o(&quo
t;type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),x.attributes&&i(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||o("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),i(function(e){return null==e.getAttribute("disabled")})||o(ne,function(e,t,n){var r;if(!n)return e[t]===!0?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),e}),r(h,[],function(){function e(e){var t=e,n,r;if(!c(e))for(t=[],n=0,r=e.length;n<r;n++)t[n]=e[n];return t}function n(e,n,r){var i,o;if(!e)return 0;if(r=r||e,e.length!==t){for(i=0,o=e.length;i<o;i++)if(n.call(r,e[i],i,e)===!1)return 0}else for(i in e)if(e.hasOwnProperty(i)&&n.call(r,e[i],i,e)===!1)return 0;return 1}function r(e,t){var r=[];ret
urn n(e,function(n,i){r.push(t(n,i,e))}),r}function i(e,t){var r=[];return n(e,function(n,i){t&&!t(n,i,e)||r.push(n)}),r}function o(e,t){var n,r;if(e)for(n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1}function a(e,t,n,r){var i=0;for(arguments.length<3&&(n=e[0]);i<e.length;i++)n=t.call(r,n,e[i],i);return n}function s(e,t,n){var r,i;for(r=0,i=e.length;r<i;r++)if(t.call(n,e[r],r,e))return r;return-1}function l(e,n,r){var i=s(e,n,r);return i!==-1?e[i]:t}function u(e){return e[e.length-1]}var c=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)};return{isArray:c,toArray:e,each:n,map:r,filter:i,indexOf:o,reduce:a,findIndex:s,find:l,last:u}}),r(m,[d,h],function(e,n){function r(e){return null===e||e===t?"":(""+e).replace(h,"")}function i(e,r){return r?!("array"!=r||!n.isArray(e))||typeof e==r:e!==t}function o(e,t,n){var r;for(e=e||[],t=t||",","string"==t
ypeof e&&(e=e.split(t)),n=n||{},r=e.length;r--;)n[e[r]]={};return n}function a(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function s(e,t,n){var r=this,i,o,a,s,l,u=0;if(e=/^((static) )?([\w.]+)(:([\w.]+))?/.exec(e),a=e[3].match(/(^|\.)(\w+)$/i)[2],o=r.createNS(e[3].replace(/\.\w+$/,""),n),!o[a]){if("static"==e[2])return o[a]=t,void(this.onCreate&&this.onCreate(e[2],e[3],o[a]));t[a]||(t[a]=function(){},u=1),o[a]=t[a],r.extend(o[a].prototype,t),e[5]&&(i=r.resolve(e[5]).prototype,s=e[5].match(/\.(\w+)$/i)[1],l=o[a],u?o[a]=function(){return i[s].apply(this,arguments)}:o[a]=function(){return this.parent=i[s],l.apply(this,arguments)},o[a].prototype[a]=o[a],r.each(i,function(e,t){o[a].prototype[t]=i[t]}),r.each(t,function(e,t){i[t]?o[a].prototype[t]=function(){return this.parent=i[t],e.apply(this,arguments)}:t!=a&&(o[a].prototype[t]=e)})),r.each(t["static"],function(e,t){o[a][t]=e})}}function l(e,n){var r,i,o,a=argumen
ts,s;for(r=1,i=a.length;r<i;r++){n=a[r];for(o in n)n.hasOwnProperty(o)&&(s=n[o],s!==t&&(e[o]=s))}return e}function u(e,t,r,i){i=i||this,e&&(r&&(e=e[r]),n.each(e,function(e,n){return t.call(i,e,n,r)!==!1&&void u(e,t,r,i)}))}function c(e,t){var n,r;for(t=t||window,e=e.split("."),n=0;n<e.length;n++)r=e[n],t[r]||(t[r]={}),t=t[r];return t}function d(e,t){var n,r;for(t=t||window,e=e.split("."),n=0,r=e.length;n<r&&(t=t[e[n]],t);n++);return t}function f(e,t){return!e||i(e,"array")?e:n.map(e.split(t||","),r)}function p(t){var n=e.cacheSuffix;return n&&(t+=(t.indexOf("?")===-1?"?":"&")+n),t}var h=/^\s*|\s*$/g;return{trim:r,isArray:n.isArray,is:i,toArray:n.toArray,makeMap:o,each:n.each,map:n.map,grep:n.filter,inArray:n.indexOf,hasOwn:a,extend:l,create:s,walk:u,createNS:c,resolve:d,explode:f,_addCacheSuffix:p}}),r(g,[f,p,m,d],function(e,n,r,i){function o(e){
return"undefined"!=typeof e}function a(e){return"string"==typeof e}function s(e){return e&&e==e.window}function l(e,t){var n,r,i;for(t=t||w,i=t.createElement("div"),n=t.createDocumentFragment(),i.innerHTML=e;r=i.firstChild;)n.appendChild(r);return n}function u(e,t,n,r){var i;if(a(t))t=l(t,v(e[0]));else if(t.length&&!t.nodeType){if(t=f.makeArray(t),r)for(i=t.length-1;i>=0;i--)u(e,t[i],n,r);else for(i=0;i<t.length;i++)u(e,t[i],n,r);return e}if(t.nodeType)for(i=e.length;i--;)n.call(e[i],t);return e}function c(e,t){return e&&t&&(" "+e.className+" ").indexOf(" "+t+" ")!==-1}function d(e,t,n){var r,i;return t=f(t)[0],e.each(function(){var e=this;n&&r==e.parentNode?i.appendChild(e):(r=e.parentNode,i=t.cloneNode(!1),e.parentNode.insertBefore(i,e),i.appendChild(e))}),e}function f(e,t){return new f.fn.init(e,t)}function p(e,t){var n;if(t.indexOf)return t.indexOf(e);for(n=t.lengt
h;n--;)if(t[n]===e)return n;return-1}function h(e){return null===e||e===k?"":(""+e).replace(P,"")}function m(e,t){var n,r,i,o,a;if(e)if(n=e.length,n===o){for(r in e)if(e.hasOwnProperty(r)&&(a=e[r],t.call(a,r,a)===!1))break}else for(i=0;i<n&&(a=e[i],t.call(a,i,a)!==!1);i++);return e}function g(e,t){var n=[];return m(e,function(e,r){t(r,e)&&n.push(r)}),n}function v(e){return e?9==e.nodeType?e:e.ownerDocument:w}function y(e,n,r){var i=[],o=e[n];for("string"!=typeof r&&r instanceof f&&(r=r[0]);o&&9!==o.nodeType;){if(r!==t){if(o===r)break;if("string"==typeof r&&f(o).is(r))break}1===o.nodeType&&i.push(o),o=o[n]}return i}function b(e,n,r,i){var o=[];for(i instanceof f&&(i=i[0]);e;e=e[n])if(!r||e.nodeType===r){if(i!==t){if(e===i)break;if("string"==typeof i&&f(e).is(i))break}o.push(e)}return o}function C(e,t,n){for(e=e[t];e;e=e[t])if(e.nodeType==n)ret
urn e;return null}function x(e,t,n){m(n,function(n,r){e[n]=e[n]||{},e[n][t]=r})}var w=document,E=Array.prototype.push,N=Array.prototype.slice,_=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,S=e.Event,k,T=r.makeMap("children,contents,next,prev"),R=r.makeMap("fillOpacity fontWeight lineHeight opacity orphans widows zIndex zoom"," "),A=r.makeMap("checked compact declare defer disabled ismap multiple nohref noshade nowrap readonly selected"," "),B={"for":"htmlFor","class":"className",readonly:"readOnly"},D={"float":"cssFloat"},L={},M={},P=/^\s*|\s*$/g;return f.fn=f.prototype={constructor:f,selector:"",context:null,length:0,init:function(e,t){var n=this,r,i;if(!e)return n;if(e.nodeType)return n.context=n[0]=e,n.length=1,n;if(t&&t.nodeType)n.context=t;else{if(t)return f(e).attr(t);n.context=t=document}if(a(e)){if(n.selector=e,r="<"
===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:_.exec(e),!r)return f(t).find(e);if(r[1])for(i=l(e,v(t)).firstChild;i;)E.call(n,i),i=i.nextSibling;else{if(i=v(t).getElementById(r[2]),!i)return n;if(i.id!==r[2])return n.find(e);n.length=1,n[0]=i}}else this.add(e,!1);return n},toArray:function(){return r.toArray(this)},add:function(e,t){var n=this,r,i;if(a(e))return n.add(f(e));if(t!==!1)for(r=f.unique(n.toArray().concat(f.makeArray(e))),n.length=r.length,i=0;i<r.length;i++)n[i]=r[i];else E.apply(n,f.makeArray(e));return n},attr:function(e,t){var n=this,r;if("object"==typeof e)m(e,function(e,t){n.attr(e,t)});else{if(!o(t)){if(n[0]&&1===n[0].nodeType){if(r=L[e],r&&r.get)return r.get(n[0],e);if(A[e])return n.prop(e)?e:k;t=n[0].getAttribute(e,2),null===t&&(t=k)}return t}this.each(function(){var n;if(1===this.nodeType){if(n=L[e],n&&n.set)return void n.set(this,t);null===t?this.removeAttribut
e(e,2):this.setAttribute(e,t,2)}})}return n},removeAttr:function(e){return this.attr(e,null)},prop:function(e,t){var n=this;if(e=B[e]||e,"object"==typeof e)m(e,function(e,t){n.prop(e,t)});else{if(!o(t))return n[0]&&n[0].nodeType&&e in n[0]?n[0][e]:t;this.each(function(){1==this.nodeType&&(this[e]=t)})}return n},css:function(e,t){function n(e){return e.replace(/-(\D)/g,function(e,t){return t.toUpperCase()})}function r(e){return e.replace(/[A-Z]/g,function(e){return"-"+e})}var i=this,a,s;if("object"==typeof e)m(e,function(e,t){i.css(e,t)});else if(o(t))e=n(e),"number"!=typeof t||R[e]||(t+="px"),i.each(function(){var n=this.style;if(s=M[e],s&&s.set)return void s.set(this,t);try{this.style[D[e]||e]=t}catch(i){}null!==t&&""!==t||(n.removeProperty?n.removeProperty(r(e)):n.removeAttribute(e))});else{if(a=i[0],s=M[e],s&&s.get)return s.get(a);if(a.ownerDocument.defaultView)try{return a
.ownerDocument.defaultView.getComputedStyle(a,null).getPropertyValue(r(e))}catch(l){return k}else if(a.currentStyle)return a.currentStyle[n(e)]}return i},remove:function(){for(var e=this,t,n=this.length;n--;)t=e[n],S.clean(t),t.parentNode&&t.parentNode.removeChild(t);return this},empty:function(){for(var e=this,t,n=this.length;n--;)for(t=e[n];t.firstChild;)t.removeChild(t.firstChild);return this},html:function(e){var t=this,n;if(o(e)){n=t.length;try{for(;n--;)t[n].innerHTML=e}catch(r){f(t[n]).empty().append(e)}return t}return t[0]?t[0].innerHTML:""},text:function(e){var t=this,n;if(o(e)){for(n=t.length;n--;)"innerText"in t[n]?t[n].innerText=e:t[0].textContent=e;return t}return t[0]?t[0].innerText||t[0].textContent:""},append:function(){return u(this,arguments,function(e){(1===this.nodeType||this.host&&1===this.host.nodeType)&&this.appendChild(e)})},prepend:function(){return u(this,arguments,function(e){(1===this.nodeType||this.ho
st&&1===this.host.nodeType)&&this.insertBefore(e,this.firstChild)},!0)},before:function(){var e=this;return e[0]&&e[0].parentNode?u(e,arguments,function(e){this.parentNode.insertBefore(e,this)}):e},after:function(){var e=this;return e[0]&&e[0].parentNode?u(e,arguments,function(e){this.parentNode.insertBefore(e,this.nextSibling)},!0):e},appendTo:function(e){return f(e).append(this),this},prependTo:function(e){return f(e).prepend(this),this},replaceWith:function(e){return this.before(e).remove()},wrap:function(e){return d(this,e)},wrapAll:function(e){return d(this,e,!0)},wrapInner:function(e){return this.each(function(){f(this).contents().wrapAll(e)}),this},unwrap:function(){return this.parent().each(function(){f(this).replaceWith(this.childNodes)})},clone:function(){var e=[];return this.each(function(){e.push(this.cloneNode(!0))}),f(e)},addClass:function(e){return this.toggleClass(e,!0)},removeClass:function(e){return this.toggleClass(e,!1)},toggleClas
s:function(e,t){var n=this;return"string"!=typeof e?n:(e.indexOf(" ")!==-1?m(e.split(" "),function(){n.toggleClass(this,t)}):n.each(function(n,r){var i,o;o=c(r,e),o!==t&&(i=r.className,o?r.className=h((" "+i+" ").replace(" "+e+" "," ")):r.className+=i?" "+e:e)}),n)},hasClass:function(e){return c(this[0],e)},each:function(e){return m(this,e)},on:function(e,t){return this.each(function(){S.bind(this,e,t)})},off:function(e,t){return this.each(function(){S.unbind(this,e,t)})},trigger:function(e){return this.each(function(){"object"==typeof e?S.fire(this,e.type,e):S.fire(this,e)})},show:function(){return this.css("display","")},hide:function(){return this.css("display","none")},slice:function(){return new f(N.apply(this,arguments))},eq:function(e){return e===-1?this.slice(e):this.slice(e,+e+1)},first:function(){return this.eq(0)},last:functio
n(){return this.eq(-1)},find:function(e){var t,n,r=[];for(t=0,n=this.length;t<n;t++)f.find(e,this[t],r);return f(r)},filter:function(e){return f("function"==typeof e?g(this.toArray(),function(t,n){return e(n,t)}):f.filter(e,this.toArray()))},closest:function(e){var t=[];return e instanceof f&&(e=e[0]),this.each(function(n,r){for(;r;){if("string"==typeof e&&f(r).is(e)){t.push(r);break}if(r==e){t.push(r);break}r=r.parentNode}}),f(t)},offset:function(e){var t,n,r,i=0,o=0,a;return e?this.css(e):(t=this[0],t&&(n=t.ownerDocument,r=n.documentElement,t.getBoundingClientRect&&(a=t.getBoundingClientRect(),i=a.left+(r.scrollLeft||n.body.scrollLeft)-r.clientLeft,o=a.top+(r.scrollTop||n.body.scrollTop)-r.clientTop)),{left:i,top:o})},push:E,sort:[].sort,splice:[].splice},r.extend(f,{extend:r.extend,makeArray:function(e){return s(e)||e.nodeType?[e]:r.toArray(e)},inArray:p,isArray:r.isArray,each:m,trim:h,grep:g,find:n,expr:n.selectors,unique:n.
uniqueSort,text:n.getText,contains:n.contains,filter:function(e,t,n){var r=t.length;for(n&&(e=":not("+e+")");r--;)1!=t[r].nodeType&&t.splice(r,1);return t=1===t.length?f.find.matchesSelector(t[0],e)?[t[0]]:[]:f.find.matches(e,t)}}),m({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return y(e,"parentNode")},next:function(e){return C(e,"nextSibling",1)},prev:function(e){return C(e,"previousSibling",1)},children:function(e){return b(e.firstChild,"nextSibling",1)},contents:function(e){return r.toArray(("iframe"===e.nodeName?e.contentDocument||e.contentWindow.document:e).childNodes)}},function(e,t){f.fn[e]=function(n){var r=this,i=[];return r.each(function(){var e=t.call(i,this,n,i);e&&(f.isArray(e)?i.push.apply(i,e):i.push(e))}),this.length>1&&(T[e]||(i=f.unique(i)),0===e.indexOf("parents")&&(i=i.reverse())),i=f(i
),n?i.filter(n):i}}),m({parentsUntil:function(e,t){return y(e,"parentNode",t)},nextUntil:function(e,t){return b(e,"nextSibling",1,t).slice(1)},prevUntil:function(e,t){return b(e,"previousSibling",1,t).slice(1)}},function(e,t){f.fn[e]=function(n,r){var i=this,o=[];return i.each(function(){var e=t.call(o,this,n,o);e&&(f.isArray(e)?o.push.apply(o,e):o.push(e))}),this.length>1&&(o=f.unique(o),0!==e.indexOf("parents")&&"prevUntil"!==e||(o=o.reverse())),o=f(o),r?o.filter(r):o}}),f.fn.is=function(e){return!!e&&this.filter(e).length>0},f.fn.init.prototype=f.fn,f.overrideDefaults=function(e){function t(r,i){return n=n||e(),0===arguments.length&&(r=n.element),i||(i=n.context),new t.fn.init(r,i)}var n;return f.extend(t,this),t},i.ie&&i.ie<8&&(x(L,"get",{maxlength:function(e){var t=e.maxLength;return 2147483647===t?k:t},size:function(e){var t=e.size;return 20===t?k:t},&qu
ot;class":function(e){return e.className},style:function(e){var t=e.style.cssText;return 0===t.length?k:t}}),x(L,"set",{"class":function(e,t){e.className=t},style:function(e,t){e.style.cssText=t}})),i.ie&&i.ie<9&&(D["float"]="styleFloat",x(M,"set",{opacity:function(e,t){var n=e.style;null===t||""===t?n.removeAttribute("filter"):(n.zoom=1,n.filter="alpha(opacity="+100*t+")")}})),f.attrHooks=L,f.cssHooks=M,f}),r(v,[],function(){return function(e,t){function n(e,t,n,r){function i(e){return e=parseInt(e,10).toString(16),e.length>1?e:"0"+e}return"#"+i(t)+i(n)+i(r)}var r=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi,i=/(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,o=/\s*([^:]+):\s*([^;]+);?/g,a=/\s+$/,s,l={},u,c,d,f="\ufeff"
;;for(e=e||{},t&&(c=t.getValidStyles(),d=t.getInvalidStyles()),u=("\\\" \\' \\; \\: ; : "+f).split(" "),s=0;s<u.length;s++)l[u[s]]=f+s,l[f+s]=u[s];return{toHex:function(e){return e.replace(r,n)},parse:function(t){function u(e,t,n){var r,i,o,a;if(r=y[e+"-top"+t],r&&(i=y[e+"-right"+t],i&&(o=y[e+"-bottom"+t],o&&(a=y[e+"-left"+t])))){var l=[r,i,o,a];for(s=l.length-1;s--&&l[s]===l[s+1];);s>-1&&n||(y[e+t]=s==-1?l[0]:l.join(" "),delete y[e+"-top"+t],delete y[e+"-right"+t],delete y[e+"-bottom"+t],delete y[e+"-left"+t])}}function c(e){var t=y[e],n;if(t){for(t=t.split(" "),n=t.length;n--;)if(t[n]!==t[0])return!1;return y[e]=t[0],!0}}function d(e,t,n,r){c(t)&&c(n)&&c(r)&&(y[e]=y[t]+" "+y[n]+" "+y[r],delete y[t],delete y[n],delete y[r])}function p(e){return w=!0,l[e]}function
h(e,t){return w&&(e=e.replace(/\uFEFF[0-9]/g,function(e){return l[e]})),t||(e=e.replace(/\\([\'\";:])/g,"$1")),e}function m(e){return String.fromCharCode(parseInt(e.slice(1),16))}function g(e){return e.replace(/\\[0-9a-f]+/gi,m)}function v(t,n,r,i,o,a){if(o=o||a)return o=h(o),"'"+o.replace(/\'/g,"\\'")+"'";if(n=h(n||r||i),!e.allow_script_urls){var s=n.replace(/[\s\r\n]+/g,"");if(/(java|vb)script:/i.test(s))return"";if(!e.allow_svg_data_urls&&/^data:image\/svg/i.test(s))return""}return E&&(n=E.call(N,n,"style")),"url('"+n.replace(/\'/g,"\\'")+"')"}var y={},b,C,x,w,E=e.url_converter,N=e.url_converter_scope||this;if(t){for(t=t.replace(/[\u0000-\u001F]/g,""),t=t.replace(/\\[\"\';:\uFEFF]/g,p).replace(/\"[^\"]+\"|\'[^\']+\'/g,function(e){return e.replace(/[;:]/g,p)});b=o.exec(t);)if(o.lastIndex=b.index+b[0].length,C=b[1]
.replace(a,"").toLowerCase(),x=b[2].replace(a,""),C&&x){if(C=g(C),x=g(x),C.indexOf(f)!==-1||C.indexOf('"')!==-1)continue;if(!e.allow_script_urls&&("behavior"==C||/expression\s*\(|\/\*|\*\//.test(x)))continue;"font-weight"===C&&"700"===x?x="bold":"color"!==C&&"background-color"!==C||(x=x.toLowerCase()),x=x.replace(r,n),x=x.replace(i,v),y[C]=w?h(x,!0):x}u("border","",!0),u("border","-width"),u("border","-color"),u("border","-style"),u("padding",""),u("margin",""),d("border","border-width","border-style","border-color"),"medium none"===y.border&&delete y.border,"none"===y["border-image"]&&delete y["border-image"]}return y},serialize:function(e,t){function n(t
){var n,r,o,a;if(n=c[t])for(r=0,o=n.length;r<o;r++)t=n[r],a=e[t],a&&(i+=(i.length>0?" ":"")+t+": "+a+";")}function r(e,t){var n;return n=d["*"],(!n||!n[e])&&(n=d[t],!n||!n[e])}var i="",o,a;if(t&&c)n("*"),n(t);else for(o in e)a=e[o],!a||d&&!r(o,t)||(i+=(i.length>0?" ":"")+o+": "+a+";");return i}}}}),r(y,[],function(){return function(e,t){function n(e,n,r,i){var o,a;if(e){if(!i&&e[n])return e[n];if(e!=t){if(o=e[r])return o;for(a=e.parentNode;a&&a!=t;a=a.parentNode)if(o=a[r])return o}}}function r(e,n,r,i){var o,a,s;if(e){if(o=e[r],t&&o===t)return;if(o){if(!i)for(s=o[n];s;s=s[n])if(!s[n])return s;return o}if(a=e.parentNode,a&&a!==t)return a}}var i=e;this.current=function(){return i},this.next=function(e){return i=n(i,"firstChild","nextSibling",e)},this.prev=function(e){return i=n(i,"
;lastChild","previousSibling",e)},this.prev2=function(e){return i=r(i,"lastChild","previousSibling",e)}}}),r(b,[m],function(e){function t(n){function r(){return P.createDocumentFragment()}function i(e,t){E(F,e,t)}function o(e,t){E(z,e,t)}function a(e){i(e.parentNode,j(e))}function s(e){i(e.parentNode,j(e)+1)}function l(e){o(e.parentNode,j(e))}function u(e){o(e.parentNode,j(e)+1)}function c(e){e?(M[V]=M[W],M[$]=M[U]):(M[W]=M[V],M[U]=M[$]),M.collapsed=F}function d(e){a(e),u(e)}function f(e){i(e,0),o(e,1===e.nodeType?e.childNodes.length:e.nodeValue.length)}function p(e,t){var n=M[W],r=M[U],i=M[V],o=M[$],a=t.startContainer,s=t.startOffset,l=t.endContainer,u=t.endOffset;return 0===e?w(n,r,a,s):1===e?w(i,o,a,s):2===e?w(i,o,l,u):3===e?w(n,r,l,u):void 0}function h(){N(I)}function m(){return N(O)}function g(){return N(H)}function v(e){var t=this[W],r=this[U],i,o;3!==t.nodeType&&4!==t.nodeType||!t.nodeValue?(t.childNodes.length>0&&(o=t.chi
ldNodes[r]),o?t.insertBefore(e,o):3==t.nodeType?n.insertAfter(e,t):t.appendChild(e)):r?r>=t.nodeValue.length?n.insertAfter(e,t):(i=t.splitText(r),t.parentNode.insertBefore(e,i)):t.parentNode.insertBefore(e,t)}function y(e){var t=M.extractContents();M.insertNode(e),e.appendChild(t),M.selectNode(e)}function b(){return q(new t(n),{startContainer:M[W],startOffset:M[U],endContainer:M[V],endOffset:M[$],collapsed:M.collapsed,commonAncestorContainer:M.commonAncestorContainer})}function C(e,t){var n;if(3==e.nodeType)return e;if(t<0)return e;for(n=e.firstChild;n&&t>0;)--t,n=n.nextSibling;return n?n:e}function x(){return M[W]==M[V]&&M[U]==M[$]}function w(e,t,r,i){var o,a,s,l,u,c;if(e==r)return t==i?0:t<i?-1:1;for(o=r;o&&o.parentNode!=e;)o=o.parentNode;if(o){for(a=0,s=e.firstChild;s!=o&&a<t;)a++,s=s.nextSibling;return t<=a?-1:1}for(o=e;o&&o.parentNode!=r;)o=o.parentNode;if(o){for(a=0,s=r.firstChild;s!=o&&a<i;)a++,s=s.nextSibli
ng;return a<i?-1:1}for(l=n.findCommonAncestor(e,r),u=e;u&&u.parentNode!=l;)u=u.parentNode;for(u||(u=l),c=r;c&&c.parentNode!=l;)c=c.parentNode;if(c||(c=l),u==c)return 0;for(s=l.firstChild;s;){if(s==u)return-1;if(s==c)return 1;s=s.nextSibling}}function E(e,t,r){var i,o;for(e?(M[W]=t,M[U]=r):(M[V]=t,M[$]=r),i=M[V];i.parentNode;)i=i.parentNode;for(o=M[W];o.parentNode;)o=o.parentNode;o==i?w(M[W],M[U],M[V],M[$])>0&&M.collapse(e):M.collapse(e),M.collapsed=x(),M.commonAncestorContainer=n.findCommonAncestor(M[W],M[V])}function N(e){var t,n=0,r=0,i,o,a,s,l,u;if(M[W]==M[V])return _(e);for(t=M[V],i=t.parentNode;i;t=i,i=i.parentNode){if(i==M[W])return S(t,e);++n}for(t=M[W],i=t.parentNode;i;t=i,i=i.parentNode){if(i==M[V])return k(t,e);++r}for(o=r-n,a=M[W];o>0;)a=a.parentNode,o--;for(s=M[V];o<0;)s=s.parentNode,o++;for(l=a.parentNode,u=s.parentNode;l!=u;l=l.parentNode,u=u.parentNode)a=l,s=u;return T(a,s,e)}function _(e){var t,n,i,o,a,s,l,u,c;if(e!=I&&(t=r
()),M[U]==M[$])return t;if(3==M[W].nodeType){if(n=M[W].nodeValue,i=n.substring(M[U],M[$]),e!=H&&(o=M[W],u=M[U],c=M[$]-M[U],0===u&&c>=o.nodeValue.length-1?o.parentNode.removeChild(o):o.deleteData(u,c),M.collapse(F)),e==I)return;return i.length>0&&t.appendChild(P.createTextNode(i)),t}for(o=C(M[W],M[U]),a=M[$]-M[U];o&&a>0;)s=o.nextSibling,l=D(o,e),t&&t.appendChild(l),--a,o=s;return e!=H&&M.collapse(F),t}function S(e,t){var n,i,o,a,s,l;if(t!=I&&(n=r()),i=R(e,t),n&&n.appendChild(i),o=j(e),a=o-M[U],a<=0)return t!=H&&(M.setEndBefore(e),M.collapse(z)),n;for(i=e.previousSibling;a>0;)s=i.previousSibling,l=D(i,t),n&&n.insertBefore(l,n.firstChild),--a,i=s;return t!=H&&(M.setEndBefore(e),M.collapse(z)),n}function k(e,t){var n,i,o,a,s,l;for(t!=I&&(n=r()),o=A(e,t),n&&n.appendChild(o),i=j(e),++i,a=M[$]-i,o=e.nextSibling;o&&a>0;)s=o.nextSibling,l=D(o,t),n&&n.appen
dChild(l),--a,o=s;return t!=H&&(M.setStartAfter(e),M.collapse(F)),n}function T(e,t,n){var i,o,a,s,l,u,c;for(n!=I&&(o=r()),i=A(e,n),o&&o.appendChild(i),a=j(e),s=j(t),++a,l=s-a,u=e.nextSibling;l>0;)c=u.nextSibling,i=D(u,n),o&&o.appendChild(i),u=c,--l;return i=R(t,n),o&&o.appendChild(i),n!=H&&(M.setStartAfter(e),M.collapse(F)),o}function R(e,t){var n=C(M[V],M[$]-1),r,i,o,a,s,l=n!=M[V];if(n==e)return B(n,l,z,t);for(r=n.parentNode,i=B(r,z,z,t);r;){for(;n;)o=n.previousSibling,a=B(n,l,z,t),t!=I&&i.insertBefore(a,i.firstChild),l=F,n=o;if(r==e)return i;n=r.previousSibling,r=r.parentNode,s=B(r,z,z,t),t!=I&&s.appendChild(i),i=s}}function A(e,t){var n=C(M[W],M[U]),r=n!=M[W],i,o,a,s,l;if(n==e)return B(n,r,F,t);for(i=n.parentNode,o=B(i,z,F,t);i;){for(;n;)a=n.nextSibling,s=B(n,r,F,t),t!=I&&o.appendChild(s),r=F,n=a;if(i==e)return o;n=i.nextSibling,i=i.parentNode,l=B(i,z,F,t),t!=I&&l.appendChild(o),o=l}}function B(e,t
,r,i){var o,a,s,l,u;if(t)return D(e,i);if(3==e.nodeType){if(o=e.nodeValue,r?(l=M[U],a=o.substring(l),s=o.substring(0,l)):(l=M[$],a=o.substring(0,l),s=o.substring(l)),i!=H&&(e.nodeValue=s),i==I)return;return u=n.clone(e,z),u.nodeValue=a,u}if(i!=I)return n.clone(e,z)}function D(e,t){return t!=I?t==H?n.clone(e,F):e:void e.parentNode.removeChild(e)}function L(){return n.create("body",null,g()).outerText}var M=this,P=n.doc,O=0,H=1,I=2,F=!0,z=!1,U="startOffset",W="startContainer",V="endContainer",$="endOffset",q=e.extend,j=n.nodeIndex;return q(M,{startContainer:P,startOffset:0,endContainer:P,endOffset:0,collapsed:F,commonAncestorContainer:P,START_TO_START:0,START_TO_END:1,END_TO_END:2,END_TO_START:3,setStart:i,setEnd:o,setStartBefore:a,setStartAfter:s,setEndBefore:l,setEndAfter:u,collapse:c,selectNode:d,selectNodeContents:f,compareBoundaryPoints:p,deleteContents:h,extractContents:m,cloneContents:g,insertNode:v,surroundContents:y,cl
oneRange:b,toStringIE:L}),M}return t.prototype.toString=function(){return this.toStringIE()},t}),r(C,[m],function(e){function t(e){var t;return t=document.createElement("div"),t.innerHTML=e,t.textContent||t.innerText||e}function n(e,t){var n,r,i,a={};if(e){for(e=e.split(","),t=t||10,n=0;n<e.length;n+=2)r=String.fromCharCode(parseInt(e[n],t)),o[r]||(i="&"+e[n+1]+";",a[r]=i,a[i]=r);return a}}var r=e.makeMap,i,o,a,s=/[&<>\"\u0060\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,l=/[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,u=/[<>&\"\']/g,c=/&#([a-z0-9]+);?|&([a-z0-9]+);/gi,d={128:"\u20ac",130:"\u201a",131:"\u0192",132:"\u201e",133:"\u2026",134:"\u2020",135:"\u2021",136:"\u02c6",137:"\u2030",138:"\u0160",139:"\u2039",140:"\u0152",142:"\u0
17d",145:"\u2018",146:"\u2019",147:"\u201c",148:"\u201d",149:"\u2022",150:"\u2013",151:"\u2014",152:"\u02dc",153:"\u2122",154:"\u0161",155:"\u203a",156:"\u0153",158:"\u017e",159:"\u0178"};o={'"':""","'":"'","<":"<",">":">","&":"&","`":"`"},a={"<":"<",">":">","&":"&",""":'"',"'":"'"},i=n("50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac1
4,5t,frac12,5u,frac34,5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,t9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,u5
,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,eur
o",32);var f={encodeRaw:function(e,t){return e.replace(t?s:l,function(e){return o[e]||e})},encodeAllRaw:function(e){return(""+e).replace(u,function(e){return o[e]||e})},encodeNumeric:function(e,t){return e.replace(t?s:l,function(e){return e.length>1?"&#"+(1024*(e.charCodeAt(0)-55296)+(e.charCodeAt(1)-56320)+65536)+";":o[e]||"&#"+e.charCodeAt(0)+";"})},encodeNamed:function(e,t,n){return n=n||i,e.replace(t?s:l,function(e){return o[e]||n[e]||e})},getEncodeFunc:function(e,t){function a(e,n){return e.replace(n?s:l,function(e){return o[e]||t[e]||"&#"+e.charCodeAt(0)+";"||e})}function u(e,n){return f.encodeNamed(e,n,t)}return t=n(t)||i,e=r(e.replace(/\+/g,",")),e.named&&e.numeric?a:e.named?t?u:f.encodeNamed:e.numeric?f.encodeNumeric:f.encodeRaw},decode:function(e){return e.replace(c,function(e,n){return n?(n="x"===n.charAt(0).toLowerCase()?parseInt(n.substr(1),16):parseInt(
n,10),n>65535?(n-=65536,String.fromCharCode(55296+(n>>10),56320+(1023&n))):d[n]||String.fromCharCode(n)):a[e]||i[e]||t(e)})}};return f}),r(x,[m,c],function(e,t){return function(n,r){function i(e){n.getElementsByTagName("head")[0].appendChild(e)}function o(r,o,u){function c(){for(var e=b.passed,t=e.length;t--;)e[t]();b.status=2,b.passed=[],b.failed=[]}function d(){for(var e=b.failed,t=e.length;t--;)e[t]();b.status=3,b.passed=[],b.failed=[]}function f(){var e=navigator.userAgent.match(/WebKit\/(\d*)/);return!!(e&&e[1]<536)}function p(e,n){e()||((new Date).getTime()-y<l?t.setTimeout(n):d())}function h(){p(function(){for(var e=n.styleSheets,t,r=e.length,i;r--;)if(t=e[r],i=t.ownerNode?t.ownerNode:t.owningElement,i&&i.id===g.id)return c(),!0},h)}function m(){p(function(){try{var e=v.sheet.cssRules;return c(),!!e}catch(t){}},m)}var g,v,y,b;if(r=e._addCacheSuffix(r),s[r]?b=s[r]:(b={passed:[],failed:[]},s[r]=b),o&&b.passed.push(o),u&&a
mp;b.failed.push(u),1!=b.status){if(2==b.status)return void c();if(3==b.status)return void d();if(b.status=1,g=n.createElement("link"),g.rel="stylesheet",g.type="text/css",g.id="u"+a++,g.async=!1,g.defer=!1,y=(new Date).getTime(),"onload"in g&&!f())g.onload=h,g.onerror=d;else{if(navigator.userAgent.indexOf("Firefox")>0)return v=n.createElement("style"),v.textContent='@import "'+r+'"',m(),void i(v);h()}i(g),g.href=r}}var a=0,s={},l;r=r||{},l=r.maxLoadTime||5e3,this.load=o}}),r(w,[p,g,v,f,y,b,C,d,m,x],function(e,n,r,i,o,a,s,l,u,c){function d(e,t){var n={},r=t.keep_values,i;return i={set:function(n,r,i){t.url_converter&&(r=t.url_converter.call(t.url_converter_scope||e,r,i,n[0])),n.attr("data-mce-"+i,r).attr(i,r)},get:function(e,t){return e.attr("data-mce-"+t)||e.attr(t)}},n={style:{set:function(e,t){return null!==t&&"object"==typeof t?void e.css(t):(r
&&e.attr("data-mce-style",t),void e.attr("style",t))},get:function(t){var n=t.attr("data-mce-style")||t.attr("style");return n=e.serializeStyle(e.parseStyle(n),t[0].nodeName)}}},r&&(n.href=n.src=i),n}function f(e,t){var n=t.attr("style");n=e.serializeStyle(e.parseStyle(n),t[0].nodeName),n||(n=null),t.attr("data-mce-style",n)}function p(e,t){var n=0,r,i;if(e)for(r=e.nodeType,e=e.previousSibling;e;e=e.previousSibling)i=e.nodeType,(!t||3!=i||i!=r&&e.nodeValue.length)&&(n++,r=i);return n}function h(e,t){var o=this,a;o.doc=e,o.win=window,o.files={},o.counter=0,o.stdMode=!b||e.documentMode>=8,o.boxModel=!b||"CSS1Compat"==e.compatMode||o.stdMode,o.styleSheetLoader=new c(e),o.boundEvents=[],o.settings=t=t||{},o.schema=t.schema,o.styles=new r({url_converter:t.url_converter,url_converter_scope:t.url_converter_scope},t.schema),o.fixDoc(e),o.events=t.ownEvents?new i(t.proxy):i.Event,o.attrHo
oks=d(o,t),a=t.schema?t.schema.getBlockElements():{},o.$=n.overrideDefaults(function(){return{context:e,element:o.getRoot()}}),o.isBlock=function(e){if(!e)return!1;var t=e.nodeType;return t?!(1!==t||!a[e.nodeName]):!!a[e]}}var m=u.each,g=u.is,v=u.grep,y=u.trim,b=l.ie,C=/^([a-z0-9],?)+$/i,x=/^[ \t\r\n]*$/;return h.prototype={$$:function(e){return"string"==typeof e&&(e=this.get(e)),this.$(e)},root:null,fixDoc:function(e){var t=this.settings,n;if(b&&t.schema){"abbr article aside audio canvas details figcaption figure footer header hgroup mark menu meter nav output progress section summary time video".replace(/\w+/g,function(t){e.createElement(t)});for(n in t.schema.getCustomElements())e.createElement(n)}},clone:function(e,t){var n=this,r,i;return!b||1!==e.nodeType||t?e.cloneNode(t):(i=n.doc,t?r.firstChild:(r=i.createElement(e.nodeName),m(n.getAttribs(e),function(t){n.setAttrib(r,t.nodeName,n.getAttrib(e,t.nodeName))}),r))},getRoot:function(){var e=th
is;return e.settings.root_element||e.doc.body},getViewPort:function(e){var t,n;return e=e?e:this.win,t=e.document,n=this.boxModel?t.documentElement:t.body,{x:e.pageXOffset||n.scrollLeft,y:e.pageYOffset||n.scrollTop,w:e.innerWidth||n.clientWidth,h:e.innerHeight||n.clientHeight}},getRect:function(e){var t=this,n,r;return e=t.get(e),n=t.getPos(e),r=t.getSize(e),{x:n.x,y:n.y,w:r.w,h:r.h}},getSize:function(e){var t=this,n,r;return e=t.get(e),n=t.getStyle(e,"width"),r=t.getStyle(e,"height"),n.indexOf("px")===-1&&(n=0),r.indexOf("px")===-1&&(r=0),
-{w:parseInt(n,10)||e.offsetWidth||e.clientWidth,h:parseInt(r,10)||e.offsetHeight||e.clientHeight}},getParent:function(e,t,n){return this.getParents(e,t,n,!1)},getParents:function(e,n,r,i){var o=this,a,s=[];for(e=o.get(e),i=i===t,r=r||("BODY"!=o.getRoot().nodeName?o.getRoot().parentNode:null),g(n,"string")&&(a=n,n="*"===n?function(e){return 1==e.nodeType}:function(e){return o.is(e,a)});e&&e!=r&&e.nodeType&&9!==e.nodeType;){if(!n||n(e)){if(!i)return e;s.push(e)}e=e.parentNode}return i?s:null},get:function(e){var t;return e&&this.doc&&"string"==typeof e&&(t=e,e=this.doc.getElementById(e),e&&e.id!==t)?this.doc.getElementsByName(t)[1]:e},getNext:function(e,t){return this._findSib(e,t,"nextSibling")},getPrev:function(e,t){return this._findSib(e,t,"previousSibling")},select:function(t,n){var r=this;return e(t,r.get(n)||r.settings.root_element||r.doc,[])},is:function(n
,r){var i;if(n.length===t){if("*"===r)return 1==n.nodeType;if(C.test(r)){for(r=r.toLowerCase().split(/,/),n=n.nodeName.toLowerCase(),i=r.length-1;i>=0;i--)if(r[i]==n)return!0;return!1}}if(n.nodeType&&1!=n.nodeType)return!1;var o=n.nodeType?[n]:n;return e(r,o[0].ownerDocument||o[0],null,o).length>0},add:function(e,t,n,r,i){var o=this;return this.run(e,function(e){var a;return a=g(t,"string")?o.doc.createElement(t):t,o.setAttribs(a,n),r&&(r.nodeType?a.appendChild(r):o.setHTML(a,r)),i?a:e.appendChild(a)})},create:function(e,t,n){return this.add(this.doc.createElement(e),e,t,n,1)},createHTML:function(e,t,n){var r="",i;r+="<"+e;for(i in t)t.hasOwnProperty(i)&&null!==t[i]&&"undefined"!=typeof t[i]&&(r+=" "+i+'="'+this.encode(t[i])+'"');return"undefined"!=typeof n?r+">"+n+"</"+e+">":r+" />"},createFragment:funct
ion(e){var t,n,r=this.doc,i;for(i=r.createElement("div"),t=r.createDocumentFragment(),e&&(i.innerHTML=e);n=i.firstChild;)t.appendChild(n);return t},remove:function(e,t){return e=this.$$(e),t?e.each(function(){for(var e;e=this.firstChild;)3==e.nodeType&&0===e.data.length?this.removeChild(e):this.parentNode.insertBefore(e,this)}).remove():e.remove(),e.length>1?e.toArray():e[0]},setStyle:function(e,t,n){e=this.$$(e).css(t,n),this.settings.update_styles&&f(this,e)},getStyle:function(e,n,r){return e=this.$$(e),r?e.css(n):(n=n.replace(/-(\D)/g,function(e,t){return t.toUpperCase()}),"float"==n&&(n=l.ie&&l.ie<12?"styleFloat":"cssFloat"),e[0]&&e[0].style?e[0].style[n]:t)},setStyles:function(e,t){e=this.$$(e).css(t),this.settings.update_styles&&f(this,e)},removeAllAttribs:function(e){return this.run(e,function(e){var t,n=e.attributes;for(t=n.length-1;t>=0;t--)e.removeAttributeNode(n.item(t
))})},setAttrib:function(e,t,n){var r=this,i,o,a=r.settings;""===n&&(n=null),e=r.$$(e),i=e.attr(t),e.length&&(o=r.attrHooks[t],o&&o.set?o.set(e,n,t):e.attr(t,n),i!=n&&a.onSetAttrib&&a.onSetAttrib({attrElm:e,attrName:t,attrValue:n}))},setAttribs:function(e,t){var n=this;n.$$(e).each(function(e,r){m(t,function(e,t){n.setAttrib(r,t,e)})})},getAttrib:function(e,t,n){var r=this,i,o;return e=r.$$(e),e.length&&(i=r.attrHooks[t],o=i&&i.get?i.get(e,t):e.attr(t)),"undefined"==typeof o&&(o=n||""),o},getPos:function(e,t){var r=this,i=0,o=0,a,s=r.doc,l=s.body,u;if(e=r.get(e),t=t||l,e){if(t===l&&e.getBoundingClientRect&&"static"===n(l).css("position"))return u=e.getBoundingClientRect(),t=r.boxModel?s.documentElement:l,i=u.left+(s.documentElement.scrollLeft||l.scrollLeft)-t.clientLeft,o=u.top+(s.documentElement.scrollTop||l.scrollTop)-t.clientTop,{x:i,y:o};for(a=e;a&
;&a!=t&&a.nodeType;)i+=a.offsetLeft||0,o+=a.offsetTop||0,a=a.offsetParent;for(a=e.parentNode;a&&a!=t&&a.nodeType;)i-=a.scrollLeft||0,o-=a.scrollTop||0,a=a.parentNode}return{x:i,y:o}},parseStyle:function(e){return this.styles.parse(e)},serializeStyle:function(e,t){return this.styles.serialize(e,t)},addStyle:function(e){var t=this,n=t.doc,r,i;if(t!==h.DOM&&n===document){var o=h.DOM.addedStyles;if(o=o||[],o[e])return;o[e]=!0,h.DOM.addedStyles=o}i=n.getElementById("mceDefaultStyles"),i||(i=n.createElement("style"),i.id="mceDefaultStyles",i.type="text/css",r=n.getElementsByTagName("head")[0],r.firstChild?r.insertBefore(i,r.firstChild):r.appendChild(i)),i.styleSheet?i.styleSheet.cssText+=e:i.appendChild(n.createTextNode(e))},loadCSS:function(e){var t=this,n=t.doc,r;return t!==h.DOM&&n===document?void h.DOM.loadCSS(e):(e||(e=""),r=n.getElementsByTagName("head")[0],void m(e.spli
t(","),function(e){var i;e=u._addCacheSuffix(e),t.files[e]||(t.files[e]=!0,i=t.create("link",{rel:"stylesheet",href:e}),b&&n.documentMode&&n.recalc&&(i.onload=function(){n.recalc&&n.recalc(),i.onload=null}),r.appendChild(i))}))},addClass:function(e,t){this.$$(e).addClass(t)},removeClass:function(e,t){this.toggleClass(e,t,!1)},hasClass:function(e,t){return this.$$(e).hasClass(t)},toggleClass:function(e,t,r){this.$$(e).toggleClass(t,r).each(function(){""===this.className&&n(this).attr("class",null)})},show:function(e){this.$$(e).show()},hide:function(e){this.$$(e).hide()},isHidden:function(e){return"none"==this.$$(e).css("display")},uniqueId:function(e){return(e?e:"mce_")+this.counter++},setHTML:function(e,t){e=this.$$(e),b?e.each(function(e,r){if(r.canHaveHTML!==!1){for(;r.firstChild;)r.removeChild(r.firstChild);try{r.innerHTML="<br>"+t,r.removeChild
(r.firstChild)}catch(i){n("<div></div>").html("<br>"+t).contents().slice(1).appendTo(r)}return t}}):e.html(t)},getOuterHTML:function(e){return e=this.get(e),1==e.nodeType&&"outerHTML"in e?e.outerHTML:n("<div></div>").append(n(e).clone()).html()},setOuterHTML:function(e,t){var r=this;r.$$(e).each(function(){try{if("outerHTML"in this)return void(this.outerHTML=t)}catch(e){}r.remove(n(this).html(t),!0)})},decode:s.decode,encode:s.encodeAllRaw,insertAfter:function(e,t){return t=this.get(t),this.run(e,function(e){var n,r;return n=t.parentNode,r=t.nextSibling,r?n.insertBefore(e,r):n.appendChild(e),e})},replace:function(e,t,n){var r=this;return r.run(t,function(t){return g(t,"array")&&(e=e.cloneNode(!0)),n&&m(v(t.childNodes),function(t){e.appendChild(t)}),t.parentNode.replaceChild(e,t)})},rename:function(e,t){var n=this,r;return e.nodeName!=t.toUpperCase()&&(r=n.create(
t),m(n.getAttribs(e),function(t){n.setAttrib(r,t.nodeName,n.getAttrib(e,t.nodeName))}),n.replace(r,e,1)),r||e},findCommonAncestor:function(e,t){for(var n=e,r;n;){for(r=t;r&&n!=r;)r=r.parentNode;if(n==r)break;n=n.parentNode}return!n&&e.ownerDocument?e.ownerDocument.documentElement:n},toHex:function(e){return this.styles.toHex(u.trim(e))},run:function(e,t,n){var r=this,i;return"string"==typeof e&&(e=r.get(e)),!!e&&(n=n||this,e.nodeType||!e.length&&0!==e.length?t.call(n,e):(i=[],m(e,function(e,o){e&&("string"==typeof e&&(e=r.get(e)),i.push(t.call(n,e,o)))}),i))},getAttribs:function(e){var t;if(e=this.get(e),!e)return[];if(b){if(t=[],"OBJECT"==e.nodeName)return e.attributes;"OPTION"===e.nodeName&&this.getAttrib(e,"selected")&&t.push({specified:1,nodeName:"selected"});var n=/<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi;return e
.cloneNode(!1).outerHTML.replace(n,"").replace(/[\w:\-]+/gi,function(e){t.push({specified:1,nodeName:e})}),t}return e.attributes},isEmpty:function(e,t){var n=this,r,i,a,s,l,u,c=0;if(e=e.firstChild){l=new o(e,e.parentNode),t=t||(n.schema?n.schema.getNonEmptyElements():null),s=n.schema?n.schema.getWhiteSpaceElements():{};do{if(a=e.nodeType,1===a){var d=e.getAttribute("data-mce-bogus");if(d){e=l.next("all"===d);continue}if(u=e.nodeName.toLowerCase(),t&&t[u]){if("br"===u){c++,e=l.next();continue}return!1}for(i=n.getAttribs(e),r=i.length;r--;)if(u=i[r].nodeName,"name"===u||"data-mce-bookmark"===u)return!1}if(8==a)return!1;if(3===a&&!x.test(e.nodeValue))return!1;if(3===a&&e.parentNode&&s[e.parentNode.nodeName]&&x.test(e.nodeValue))return!1;e=l.next()}while(e)}return c<=1},createRng:function(){var e=this.doc;return e.createRange?e.createRange():new a(this)},nodeIndex:p,split:function(e,t,
n){function r(e){function t(e){var t=e.previousSibling&&"SPAN"==e.previousSibling.nodeName,n=e.nextSibling&&"SPAN"==e.nextSibling.nodeName;return t&&n}var n,o=e.childNodes,a=e.nodeType;if(1!=a||"bookmark"!=e.getAttribute("data-mce-type")){for(n=o.length-1;n>=0;n--)r(o[n]);if(9!=a){if(3==a&&e.nodeValue.length>0){var s=y(e.nodeValue).length;if(!i.isBlock(e.parentNode)||s>0||0===s&&t(e))return}else if(1==a&&(o=e.childNodes,1==o.length&&o[0]&&1==o[0].nodeType&&"bookmark"==o[0].getAttribute("data-mce-type")&&e.parentNode.insertBefore(o[0],e),o.length||/^(br|hr|input|img)$/i.test(e.nodeName)))return;i.remove(e)}return e}}var i=this,o=i.createRng(),a,s,l;if(e&&t)return o.setStart(e.parentNode,i.nodeIndex(e)),o.setEnd(t.parentNode,i.nodeIndex(t)),a=o.extractContents(),o=i.createRng(),o.setStart(t.parentNode,i.nodeIndex(t)+1),o.setEnd(e.
parentNode,i.nodeIndex(e)+1),s=o.extractContents(),l=e.parentNode,l.insertBefore(r(a),e),n?l.insertBefore(n,e):l.insertBefore(t,e),l.insertBefore(r(s),e),i.remove(e),n||t},bind:function(e,t,n,r){var i=this;if(u.isArray(e)){for(var o=e.length;o--;)e[o]=i.bind(e[o],t,n,r);return e}return!i.settings.collect||e!==i.doc&&e!==i.win||i.boundEvents.push([e,t,n,r]),i.events.bind(e,t,n,r||i)},unbind:function(e,t,n){var r=this,i;if(u.isArray(e)){for(i=e.length;i--;)e[i]=r.unbind(e[i],t,n);return e}if(r.boundEvents&&(e===r.doc||e===r.win))for(i=r.boundEvents.length;i--;){var o=r.boundEvents[i];e!=o[0]||t&&t!=o[1]||n&&n!=o[2]||this.events.unbind(o[0],o[1],o[2])}return this.events.unbind(e,t,n)},fire:function(e,t,n){return this.events.fire(e,t,n)},getContentEditable:function(e){var t;return e&&1==e.nodeType?(t=e.getAttribute("data-mce-contenteditable"),t&&"inherit"!==t?t:"inherit"!==e.contentEditable?e.contentEditable:n
ull):null},getContentEditableParent:function(e){for(var t=this.getRoot(),n=null;e&&e!==t&&(n=this.getContentEditable(e),null===n);e=e.parentNode);return n},destroy:function(){var t=this;if(t.boundEvents){for(var n=t.boundEvents.length;n--;){var r=t.boundEvents[n];this.events.unbind(r[0],r[1],r[2])}t.boundEvents=null}e.setDocument&&e.setDocument(),t.win=t.doc=t.root=t.events=t.frag=null},isChildOf:function(e,t){for(;e;){if(t===e)return!0;e=e.parentNode}return!1},dumpRng:function(e){return"startContainer: "+e.startContainer.nodeName+", startOffset: "+e.startOffset+", endContainer: "+e.endContainer.nodeName+", endOffset: "+e.endOffset},_findSib:function(e,t,n){var r=this,i=t;if(e)for("string"==typeof i&&(i=function(e){return r.is(e,t)}),e=e[n];e;e=e[n])if(i(e))return e;return null}},h.DOM=new h(document),h.nodeIndex=p,h}),r(E,[w,m],function(e,t){function n(){function e(e,n,i){function o(){l.remove(c),u&am
p;&(u.onreadystatechange=u.onload=u=null),n()}function s(){a(i)?i():"undefined"!=typeof console&&console.log&&console.log("Failed to load script: "+e)}var l=r,u,c;c=l.uniqueId(),u=document.createElement("script"),u.id=c,u.type="text/javascript",u.src=t._addCacheSuffix(e),"onreadystatechange"in u?u.onreadystatechange=function(){/loaded|complete/.test(u.readyState)&&o()}:u.onload=o,u.onerror=s,(document.getElementsByTagName("head")[0]||document.body).appendChild(u)}var n=0,s=1,l=2,u=3,c={},d=[],f={},p=[],h=0,m;this.isDone=function(e){return c[e]==l},this.markDone=function(e){c[e]=l},this.add=this.load=function(e,t,r,i){var o=c[e];o==m&&(d.push(e),c[e]=n),t&&(f[e]||(f[e]=[]),f[e].push({success:t,failure:i,scope:r||this}))},this.remove=function(e){delete c[e],delete f[e]},this.loadQueue=function(e,t,n){this.loadScripts(d,e,t,n)},this.loadScripts=function(t,n,r,d){function g(e,t){i(f[t
],function(t){a(t[e])&&t[e].call(t.scope)}),f[t]=m}var v,y=[];p.push({success:n,failure:d,scope:r||this}),(v=function(){var n=o(t);t.length=0,i(n,function(t){return c[t]===l?void g("success",t):c[t]===u?void g("failure",t):void(c[t]!==s&&(c[t]=s,h++,e(t,function(){c[t]=l,h--,g("success",t),v()},function(){c[t]=u,h--,y.push(t),g("failure",t),v()})))}),h||(i(p,function(e){0===y.length?a(e.success)&&e.success.call(e.scope):a(e.failure)&&e.failure.call(e.scope,y)}),p.length=0)})()}}var r=e.DOM,i=t.each,o=t.grep,a=function(e){return"function"==typeof e};return n.ScriptLoader=new n,n}),r(N,[E,m],function(e,n){function r(){var e=this;e.items=[],e.urls={},e.lookup={}}var i=n.each;return r.prototype={get:function(e){return this.lookup[e]?this.lookup[e].instance:t},dependencies:function(e){var t;return this.lookup[e]&&(t=this.lookup[e].dependencies),t||[]},requireLangPack:function(t,n){var i=r.language;i
f(i&&r.languageLoad!==!1){if(n)if(n=","+n+",",n.indexOf(","+i.substr(0,2)+",")!=-1)i=i.substr(0,2);else if(n.indexOf(","+i+",")==-1)return;e.ScriptLoader.add(this.urls[t]+"/langs/"+i+".js")}},add:function(e,t,n){return this.items.push(t),this.lookup[e]={instance:t,dependencies:n},t},remove:function(e){delete this.urls[e],delete this.lookup[e]},createUrl:function(e,t){return"object"==typeof t?t:{prefix:e.prefix,resource:t,suffix:e.suffix}},addComponents:function(t,n){var r=this.urls[t];i(n,function(t){e.ScriptLoader.add(r+"/"+t)})},load:function(n,o,a,s,l){function u(){var r=c.dependencies(n);i(r,function(e){var n=c.createUrl(o,e);c.load(n.resource,n,t,t)}),a&&(s?a.call(s):a.call(e))}var c=this,d=o;c.urls[n]||("object"==typeof o&&(d=o.prefix+o.resource+o.suffix),0!==d.indexOf("/")&&d.indexOf("://")==-1&&(d=r.baseURL+
"/"+d),c.urls[n]=d.substring(0,d.lastIndexOf("/")),c.lookup[n]?u():e.ScriptLoader.add(d,u,s,l))}},r.PluginManager=new r,r.ThemeManager=new r,r}),r(_,[],function(){function e(e){return function(t){return!!t&&t.nodeType==e}}function t(e){return e=e.toLowerCase().split(" "),function(t){var n,r;if(t&&t.nodeType)for(r=t.nodeName.toLowerCase(),n=0;n<e.length;n++)if(r===e[n])return!0;return!1}}function n(e,t){return t=t.toLowerCase().split(" "),function(n){var r,i;if(s(n))for(r=0;r<t.length;r++)if(i=getComputedStyle(n,null).getPropertyValue(e),i===t[r])return!0;return!1}}function r(e,t){return function(n){return s(n)&&n[e]===t}}function i(e,t){return function(n){return s(n)&&n.getAttribute(e)===t}}function o(e){return s(e)&&e.hasAttribute("data-mce-bogus")}function a(e){return function(t){if(s(t)){if(t.contentEditable===e)return!0;if(t.getAttribute("data-mce-contenteditable")===e)retur
n!0}return!1}}var s=e(1);return{isText:e(3),isElement:s,isComment:e(8),isBr:t("br"),isContentEditableTrue:a("true"),isContentEditableFalse:a("false"),matchNodeNames:t,hasPropValue:r,hasAttributeValue:i,matchStyleValues:n,isBogus:o}}),r(S,[],function(){function e(e){return e==n}function t(e){return e.replace(new RegExp(n,"g"),"")}var n="\ufeff";return{isZwsp:e,ZWSP:n,trim:t}}),r(k,[_,S],function(e,t){function n(e){return y(e)&&(e=e.parentNode),v(e)&&e.hasAttribute("data-mce-caret")}function r(e){return y(e)&&t.isZwsp(e.data)}function i(e){return n(e)||r(e)}function o(e){var t=e.parentNode;t&&t.removeChild(e)}function a(e){try{return e.nodeValue}catch(t){return""}}function s(e,t){0===t.length?o(e):e.nodeValue=t}function l(e,n){var r,o,a,s;if(r=e.ownerDocument,a=r.createTextNode(t.ZWSP),s=e.parentNode,n){if(o=e.previousSibling,y(o)){if(i(o))return o;if(h(o))return o.splitText
(o.data.length-1)}s.insertBefore(a,e)}else{if(o=e.nextSibling,y(o)){if(i(o))return o;if(p(o))return o.splitText(1),o}e.nextSibling?s.insertBefore(a,e.nextSibling):s.appendChild(a)}return a}function u(){var e=document.createElement("br");return e.setAttribute("data-mce-bogus","1"),e}function c(e,t,n){var r,i,o;return r=t.ownerDocument,i=r.createElement(e),i.setAttribute("data-mce-caret",n?"before":"after"),i.setAttribute("data-mce-bogus","all"),i.appendChild(u()),o=t.parentNode,n?o.insertBefore(i,t):t.nextSibling?o.insertBefore(i,t.nextSibling):o.appendChild(i),i}function d(t){return t.firstChild!==t.lastChild||!e.isBr(t.firstChild)}function f(e){if(v(e)&&i(e)&&(d(e)?e.removeAttribute("data-mce-caret"):o(e)),y(e)){var n=t.trim(a(e));s(e,n)}}function p(e){return y(e)&&e.data[0]==t.ZWSP}function h(e){return y(e)&&e.data[e.data.length-1]==t.ZWSP}function m(t){var n=t
.getElementsByTagName("br"),r=n[n.length-1];e.isBogus(r)&&r.parentNode.removeChild(r)}function g(e){return e&&e.hasAttribute("data-mce-caret")?(m(e),e.removeAttribute("data-mce-caret"),e.removeAttribute("data-mce-bogus"),e.removeAttribute("style"),e.removeAttribute("_moz_abspos"),e):null}var v=e.isElement,y=e.isText;return{isCaretContainer:i,isCaretContainerBlock:n,isCaretContainerInline:r,showCaretContainerBlock:g,insertInline:l,insertBlock:c,hasContent:d,remove:f,startsWithCaretContainer:p,endsWithCaretContainer:h}}),r(T,[m,y,_,b,k],function(e,t,n,r,i){function o(e){return m(e)||g(e)}function a(e,t){var n=e.childNodes;return t--,t>n.length-1?t=n.length-1:t<0&&(t=0),n[t]||e}function s(e,t,n){for(;e&&e!==t;){if(n(e))return e;e=e.parentNode}return null}function l(e,t,n){return null!==s(e,t,n)}function u(e){return"_mce_caret"===e.id}function c(e,t){return v(e)&&l(e,t,u)=
==!1}function d(e){this.walk=function(t,n){function r(e){var t;return t=e[0],3===t.nodeType&&t===l&&u>=t.nodeValue.length&&e.splice(0,1),t=e[e.length-1],0===d&&e.length>0&&t===c&&3===t.nodeType&&e.splice(e.length-1,1),e}function i(e,t,n){for(var r=[];e&&e!=n;e=e[t])r.push(e);return r}function o(e,t){do{if(e.parentNode==t)return e;e=e.parentNode}while(e)}function s(e,t,o){var a=o?"nextSibling":"previousSibling";for(g=e,v=g.parentNode;g&&g!=t;g=v)v=g.parentNode,y=i(g==e?g:g[a],a),y.length&&(o||y.reverse(),n(r(y)))}var l=t.startContainer,u=t.startOffset,c=t.endContainer,d=t.endOffset,f,p,m,g,v,y,b;if(b=e.select("td[data-mce-selected],th[data-mce-selected]"),b.length>0)return void h(b,function(e){n([e])});if(1==l.nodeType&&l.hasChildNodes()&&(l=l.childNodes[u]),1==c.nodeType&&c.hasChildNodes()&&(c=a(c,d)),l==c)return n(r([l]));for(f=e.fin
dCommonAncestor(l,c),g=l;g;g=g.parentNode){if(g===c)return s(l,f,!0);if(g===f)break}for(g=c;g;g=g.parentNode){if(g===l)return s(c,f);if(g===f)break}p=o(l,f)||l,m=o(c,f)||c,s(l,p,!0),y=i(p==l?p:p.nextSibling,"nextSibling",m==c?m.nextSibling:m),y.length&&n(r(y)),s(c,m)},this.split=function(e){function t(e,t){return e.splitText(t)}var n=e.startContainer,r=e.startOffset,i=e.endContainer,o=e.endOffset;return n==i&&3==n.nodeType?r>0&&r<n.nodeValue.length&&(i=t(n,r),n=i.previousSibling,o>r?(o-=r,n=i=t(i,o).previousSibling,o=i.nodeValue.length,r=0):o=0):(3==n.nodeType&&r>0&&r<n.nodeValue.length&&(n=t(n,r),r=0),3==i.nodeType&&o>0&&o<i.nodeValue.length&&(i=t(i,o).previousSibling,o=i.nodeValue.length)),{startContainer:n,startOffset:r,endContainer:i,endOffset:o}},this.normalize=function(n){function r(r){function a(e){return e&&/^(TD|TH|CAPTION)$/.test(e.nodeName)}function s(n,r
){for(var i=new t(n,e.getParent(n.parentNode,e.isBlock)||m);n=i[r?"prev":"next"]();)if("BR"===n.nodeName)return!0}function l(e){for(;e&&e!=m;){if(g(e))return!0;e=e.parentNode}return!1}function u(e,t){return e.previousSibling&&e.previousSibling.nodeName==t}function d(n,r){var a,s,l;if(r=r||f,l=e.getParent(r.parentNode,e.isBlock)||m,n&&"BR"==r.nodeName&&x&&e.isEmpty(l))return f=r.parentNode,p=e.nodeIndex(r),void(i=!0);for(a=new t(r,l);y=a[n?"prev":"next"]();){if("false"===e.getContentEditableParent(y)||c(y,e.getRoot()))return;if(3===y.nodeType&&y.nodeValue.length>0)return f=y,p=n?y.nodeValue.length:0,void(i=!0);if(e.isBlock(y)||b[y.nodeName.toLowerCase()])return;s=y}o&&s&&(f=s,i=!0,p=0)}var f,p,h,m=e.getRoot(),y,b,C,x;if(f=n[(r?"start":"end")+"Container"],p=n[(r?"start":"end")+"Offset"],x=1=
=f.nodeType&&p===f.childNodes.length,b=e.schema.getNonEmptyElements(),C=r,!v(f)){if(1==f.nodeType&&p>f.childNodes.length-1&&(C=!1),9===f.nodeType&&(f=e.getRoot(),p=0),f===m){if(C&&(y=f.childNodes[p>0?p-1:0])){if(v(y))return;if(b[y.nodeName]||"TABLE"==y.nodeName)return}if(f.hasChildNodes()){if(p=Math.min(!C&&p>0?p-1:p,f.childNodes.length-1),f=f.childNodes[p],p=0,!o&&f===m.lastChild&&"TABLE"===f.nodeName)return;if(l(f)||v(f))return;if(f.hasChildNodes()&&!/TABLE/.test(f.nodeName)){y=f,h=new t(f,m);do{if(g(y)||v(y)){i=!1;break}if(3===y.nodeType&&y.nodeValue.length>0){p=C?0:y.nodeValue.length,f=y,i=!0;break}if(b[y.nodeName.toLowerCase()]&&!a(y)){p=e.nodeIndex(y),f=y.parentNode,"IMG"!=y.nodeName||C||p++,i=!0;break}}while(y=C?h.next():h.prev())}}}o&&(3===f.nodeType&&0===p&&d(!0),1===f.nodeType&&(y=f.childNodes[p],y||(y=f.childNode
s[p-1]),!y||"BR"!==y.nodeName||u(y,"A")||s(y)||s(y,!0)||d(!0,y))),C&&!o&&3===f.nodeType&&p===f.nodeValue.length&&d(!1),i&&n["set"+(r?"Start":"End")](f,p)}}var i,o;return o=n.collapsed,r(!0),o||r(),i&&o&&n.collapse(!0),i}}function f(t,n,r){var i,o,a;if(i=r.elementFromPoint(t,n),o=r.body.createTextRange(),i&&"HTML"!=i.tagName||(i=r.body),o.moveToElementText(i),a=e.toArray(o.getClientRects()),a=a.sort(function(e,t){return e=Math.abs(Math.max(e.top-n,e.bottom-n)),t=Math.abs(Math.max(t.top-n,t.bottom-n)),e-t}),a.length>0){n=(a[0].bottom+a[0].top)/2;try{return o.moveToPoint(t,n),o.collapse(!0),o}catch(s){}}return null}function p(e,t){var n=e&&e.parentElement?e.parentElement():null;return g(s(n,t,o))?null:e}var h=e.each,m=n.isContentEditableTrue,g=n.isContentEditableFalse,v=i.isCaretContainer;return d.compareRanges=function(e,t){if(e&&t){if(!e.item&
amp;&!e.duplicate)return e.startContainer==t.startContainer&&e.startOffset==t.startOffset;if(e.item&&t.item&&e.item(0)===t.item(0))return!0;if(e.isEqual&&t.isEqual&&t.isEqual(e))return!0}return!1},d.getCaretRangeFromPoint=function(e,t,n){var r,i;if(n.caretPositionFromPoint)i=n.caretPositionFromPoint(e,t),r=n.createRange(),r.setStart(i.offsetNode,i.offset),r.collapse(!0);else if(n.caretRangeFromPoint)r=n.caretRangeFromPoint(e,t);else if(n.body.createTextRange){r=n.body.createTextRange();try{r.moveToPoint(e,t),r.collapse(!0)}catch(o){r=f(e,t,n)}return p(r,n.body)}return r},d.getSelectedNode=function(e){var t=e.startContainer,n=e.startOffset;return t.hasChildNodes()&&e.endOffset==n+1?t.childNodes[n]:null},d.getNode=function(e,t){return 1==e.nodeType&&e.hasChildNodes()&&(t>=e.childNodes.length&&(t=e.childNodes.length-1),e=e.childNodes[t]),e},d}),r(R,[T,d,c],function(e,t,n){return function(r){function i(e){var
t,n;if(n=r.$(e).parentsUntil(r.getBody()).add(e),n.length===a.length){for(t=n.length;t>=0&&n[t]===a[t];t--);if(t===-1)return a=n,!0}return a=n,!1}var o,a=[];"onselectionchange"in r.getDoc()||r.on("NodeChange Click MouseUp KeyUp Focus",function(t){var n,i;n=r.selection.getRng(),i={startContainer:n.startContainer,startOffset:n.startOffset,endContainer:n.endContainer,endOffset:n.endOffset},"nodechange"!=t.type&&e.compareRanges(i,o)||r.fire("SelectionChange"),o=i}),r.on("contextmenu",function(){r.fire("SelectionChange")}),r.on("SelectionChange",function(){var e=r.selection.getStart(!0);!t.range&&r.selection.isCollapsed()||!i(e)&&r.dom.isChildOf(e,r.getBody())&&r.nodeChanged({selectionChange:!0})}),r.on("MouseUp",function(e){e.isDefaultPrevented()||("IMG"==r.selection.getNode().nodeName?n.setEditorTimeout(r,function(){r.nodeChanged()}):r.nodeChanged())}),t
his.nodeChanged=function(e){var t=r.selection,n,i,o;r.initialized&&t&&!r.settings.disable_nodechange&&!r.readonly&&(o=r.getBody(),n=t.getStart()||o,n.ownerDocument==r.getDoc()&&r.dom.isChildOf(n,o)||(n=o),"IMG"==n.nodeName&&t.isCollapsed()&&(n=n.parentNode),i=[],r.dom.getParent(n,function(e){return e===o||void i.push(e)}),e=e||{},e.element=n,e.parents=i,r.fire("NodeChange",e))}}}),r(A,[],function(){function e(e,t,n){var r,i,o=n?"lastChild":"firstChild",a=n?"prev":"next";if(e[o])return e[o];if(e!==t){if(r=e[a])return r;for(i=e.parent;i&&i!==t;i=i.parent)if(r=i[a])return r}}function t(e,t){this.name=e,this.type=t,1===t&&(this.attributes=[],this.attributes.map={})}var n=/^[ \t\r\n]*$/,r={"#text":3,"#comment":8,"#cdata":4,"#pi":7,"#doctype":10,"#document-fragment":11};return t.prototype={replace:fu
nction(e){var t=this;return e.parent&&e.remove(),t.insert(e,t),t.remove(),t},attr:function(e,t){var n=this,r,i,o;if("string"!=typeof e){for(i in e)n.attr(i,e[i]);return n}if(r=n.attributes){if(t!==o){if(null===t){if(e in r.map)for(delete r.map[e],i=r.length;i--;)if(r[i].name===e)return r=r.splice(i,1),n;return n}if(e in r.map){for(i=r.length;i--;)if(r[i].name===e){r[i].value=t;break}}else r.push({name:e,value:t});return r.map[e]=t,n}return r.map[e]}},clone:function(){var e=this,n=new t(e.name,e.type),r,i,o,a,s;if(o=e.attributes){for(s=[],s.map={},r=0,i=o.length;r<i;r++)a=o[r],"id"!==a.name&&(s[s.length]={name:a.name,value:a.value},s.map[a.name]=a.value);n.attributes=s}return n.value=e.value,n.shortEnded=e.shortEnded,n},wrap:function(e){var t=this;return t.parent.insert(e,t),e.append(t),t},unwrap:function(){var e=this,t,n;for(t=e.firstChild;t;)n=t.next,e.insert(t,e,!0),t=n;e.remove()},remove:function(){var e=this,t=e.parent,n=e.next,r=e.prev;ret
urn t&&(t.firstChild===e?(t.firstChild=n,n&&(n.prev=null)):r.next=n,t.lastChild===e?(t.lastChild=r,r&&(r.next=null)):n.prev=r,e.parent=e.next=e.prev=null),e},append:function(e){var t=this,n;return e.parent&&e.remove(),n=t.lastChild,n?(n.next=e,e.prev=n,t.lastChild=e):t.lastChild=t.firstChild=e,e.parent=t,e},insert:function(e,t,n){var r;return e.parent&&e.remove(),r=t.parent||this,n?(t===r.firstChild?r.firstChild=e:t.prev.next=e,e.prev=t.prev,e.next=t,t.prev=e):(t===r.lastChild?r.lastChild=e:t.next.prev=e,e.next=t.next,e.prev=t,t.next=e),e.parent=r,e},getAll:function(t){var n=this,r,i=[];for(r=n.firstChild;r;r=e(r,n))r.name===t&&i.push(r);return i},empty:function(){var t=this,n,r,i;if(t.firstChild){for(n=[],i=t.firstChild;i;i=e(i,t))n.push(i);for(r=n.length;r--;)i=n[r],i.parent=i.firstChild=i.lastChild=i.next=i.prev=null}return t.firstChild=t.lastChild=null,t},isEmpty:function(t,r){var i=this,o=i.firstChild,a,s;if(r=r||{},o)do{if(1===o.
type){if(o.attributes.map["data-mce-bogus"])continue;if(t[o.name])return!1;for(a=o.attributes.length;a--;)if(s=o.attributes[a].name,"name"===s||0===s.indexOf("data-mce-bookmark"))return!1}if(8===o.type)return!1;if(3===o.type&&!n.test(o.value))return!1;if(3===o.type&&o.parent&&r[o.parent.name]&&n.test(o.value))return!1}while(o=e(o,i));return!0},walk:function(t){return e(this,null,t)}},t.create=function(e,n){var i,o;if(i=new t(e,r[e]||1),n)for(o in n)i.attr(o,n[o]);return i},t}),r(B,[m],function(e){function t(t,n){return t=e.trim(t),t?t.split(n||" "):[]}function n(e){function n(e,n,r){function i(e,t){var n={},r,i;for(r=0,i=e.length;r<i;r++)n[e[r]]=t||{};return n}var s,u,c;for(r=r||[],n=n||"","string"==typeof r&&(r=t(r)),e=t(e),s=e.length;s--;)u=t([l,n].join(" ")),c={attributes:i(u),attributesOrder:u,children:i(r,o)},a[e[s]]=c}function r(e,n){var r,i,o,s;for(e=t(e),r=e.lengt
h,n=t(n);r--;)for(i=a[e[r]],o=0,s=n.length;o<s;o++)i.attributes[n[o]]={},i.attributesOrder.push(n[o])}var a={},l,u,c,d,f,p;return i[e]?i[e]:(l="id accesskey class dir lang style tabindex title",u="address blockquote div dl fieldset form h1 h2 h3 h4 h5 h6 hr menu ol p pre table ul",c="a abbr b bdo br button cite code del dfn em embed i iframe img input ins kbd label map noscript object q s samp script select small span strong sub sup textarea u var #text #comment","html4"!=e&&(l+=" contenteditable contextmenu draggable dropzone hidden spellcheck translate",u+=" article aside details dialog figure header footer hgroup section nav",c+=" audio canvas command datalist mark meter output picture progress time wbr video ruby bdi keygen"),"html5-strict"!=e&&(l+=" xml:lang",p="acronym applet basefont big font strike tt",c=[c,p].join(" "),s(t(p),function(e){n(e,"
;",c)}),f="center dir isindex noframes",u=[u,f].join(" "),d=[u,c].join(" "),s(t(f),function(e){n(e,"",d)})),d=d||[u,c].join(" "),n("html","manifest","head body"),n("head","","base command link meta noscript script style title"),n("title hr noscript br"),n("base","href target"),n("link","href rel media hreflang type sizes hreflang"),n("meta","name http-equiv content charset"),n("style","media type scoped"),n("script","src async defer type charset"),n("body","onafterprint onbeforeprint onbeforeunload onblur onerror onfocus onhashchange onload onmessage onoffline ononline onpagehide onpageshow onpopstate onresize onscroll onstorage onunload",d),n("address dt dd div caption","",d),n("h1 h2 h3 h4 h5 h6 pre p abbr code var
samp kbd sub sup i b u bdo span legend em strong small s cite dfn","",c),n("blockquote","cite",d),n("ol","reversed start type","li"),n("ul","","li"),n("li","value",d),n("dl","","dt dd"),n("a","href target rel media hreflang type",c),n("q","cite",c),n("ins del","cite datetime",d),n("img","src sizes srcset alt usemap ismap width height"),n("iframe","src name width height",d),n("embed","src type width height"),n("object","data type typemustmatch name usemap form width height",[d,"param"].join(" ")),n("param","name value"),n("map","name",[d,"area"].join(" ")),n("area","alt coords shape href target rel media hrefla
ng type"),n("table","border","caption colgroup thead tfoot tbody tr"+("html4"==e?" col":"")),n("colgroup","span","col"),n("col","span"),n("tbody thead tfoot","","tr"),n("tr","","td th"),n("td","colspan rowspan headers",d),n("th","colspan rowspan headers scope abbr",d),n("form","accept-charset action autocomplete enctype method name novalidate target",d),n("fieldset","disabled form name",[d,"legend"].join(" ")),n("label","form for",c),n("input","accept alt autocomplete checked dirname disabled form formaction formenctype formmethod formnovalidate formtarget height list max maxlength min multiple name pattern readonly required size src step type value width"),n("button&q
uot;,"disabled form formaction formenctype formmethod formnovalidate formtarget name type value","html4"==e?d:c),n("select","disabled form multiple name required size","option optgroup"),n("optgroup","disabled label","option"),n("option","disabled label selected value"),n("textarea","cols dirname disabled form maxlength name readonly required rows wrap"),n("menu","type label",[d,"li"].join(" ")),n("noscript","",d),"html4"!=e&&(n("wbr"),n("ruby","",[c,"rt rp"].join(" ")),n("figcaption","",d),n("mark rt rp summary bdi","",c),n("canvas","width height",d),n("video","src crossorigin poster preload autoplay mediagroup loop muted controls width height buffered",[d,&qu
ot;track source"].join(" ")),n("audio","src crossorigin preload autoplay mediagroup loop muted controls buffered volume",[d,"track source"].join(" ")),n("picture","","img source"),n("source","src srcset type media sizes"),n("track","kind src srclang label default"),n("datalist","",[c,"option"].join(" ")),n("article section nav aside header footer","",d),n("hgroup","","h1 h2 h3 h4 h5 h6"),n("figure","",[d,"figcaption"].join(" ")),n("time","datetime",c),n("dialog","open",d),n("command","type label icon disabled checked radiogroup command"),n("output","for form name",c),n("progress","value max",c),n("meter","value min max
low high optimum",c),n("details","open",[d,"summary"].join(" ")),n("keygen","autofocus challenge disabled form keytype name")),"html5-strict"!=e&&(r("script","language xml:space"),r("style","xml:space"),r("object","declare classid code codebase codetype archive standby align border hspace vspace"),r("embed","align name hspace vspace"),r("param","valuetype type"),r("a","charset name rev shape coords"),r("br","clear"),r("applet","codebase archive code object alt name width height align hspace vspace"),r("img","name longdesc align border hspace vspace"),r("iframe","longdesc frameborder marginwidth marginheight scrolling align"),r("font basefont","size color face"),r("input",&quo
t;usemap align"),r("select","onchange"),r("textarea"),r("h1 h2 h3 h4 h5 h6 div p legend caption","align"),r("ul","type compact"),r("li","type"),r("ol dl menu dir","compact"),r("pre","width xml:space"),r("hr","align noshade size width"),r("isindex","prompt"),r("table","summary width frame rules cellspacing cellpadding align bgcolor"),r("col","width align char charoff valign"),r("colgroup","width align char charoff valign"),r("thead","align char charoff valign"),r("tr","align char charoff valign bgcolor"),r("th","axis align char charoff valign nowrap bgcolor width height"),r("form","accept"),r("td","abbr axis scope align char charoff valign nowrap bgcolor width
height"),r("tfoot","align char charoff valign"),r("tbody","align char charoff valign"),r("area","nohref"),r("body","background bgcolor text link vlink alink")),"html4"!=e&&(r("input button select textarea","autofocus"),r("input textarea","placeholder"),r("a","download"),
-r("link script img","crossorigin"),r("iframe","sandbox seamless allowfullscreen")),s(t("a form meter progress dfn"),function(e){a[e]&&delete a[e].children[e]}),delete a.caption.children.table,delete a.script,i[e]=a,a)}function r(e,t){var n;return e&&(n={},"string"==typeof e&&(e={"*":e}),s(e,function(e,r){n[r]=n[r.toUpperCase()]="map"==t?a(e,/[, ]/):u(e,/[, ]/)})),n}var i={},o={},a=e.makeMap,s=e.each,l=e.extend,u=e.explode,c=e.inArray;return function(e){function o(t,n,r){var o=e[t];return o?o=a(o,/[, ]/,a(o.toUpperCase(),/[, ]/)):(o=i[t],o||(o=a(n," ",a(n.toUpperCase()," ")),o=l(o,r),i[t]=o)),o}function d(e){return new RegExp("^"+e.replace(/([?+*])/g,".$1")+"$")}function f(e){var n,r,i,o,s,l,u,f,p,h,m,g,v,b,x,w,E,N,_,S=/^([#+\-])?([^\[!\/]+)(?:\/([^\[!]+))?(?:(!?)\[([^\]]+)\])?$/,k=/^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?
$/,T=/[*?+]/;if(e)for(e=t(e,","),y["@"]&&(w=y["@"].attributes,E=y["@"].attributesOrder),n=0,r=e.length;n<r;n++)if(s=S.exec(e[n])){if(b=s[1],p=s[2],x=s[3],f=s[5],g={},v=[],l={attributes:g,attributesOrder:v},"#"===b&&(l.paddEmpty=!0),"-"===b&&(l.removeEmpty=!0),"!"===s[4]&&(l.removeEmptyAttrs=!0),w){for(N in w)g[N]=w[N];v.push.apply(v,E)}if(f)for(f=t(f,"|"),i=0,o=f.length;i<o;i++)if(s=k.exec(f[i])){if(u={},m=s[1],h=s[2].replace(/::/g,":"),b=s[3],_=s[4],"!"===m&&(l.attributesRequired=l.attributesRequired||[],l.attributesRequired.push(h),u.required=!0),"-"===m){delete g[h],v.splice(c(v,h),1);continue}b&&("="===b&&(l.attributesDefault=l.attributesDefault||[],l.attributesDefault.push({name:h,value:_}),u.defaultValue=_),":"===b&&(l.attributesForced=l.attributesForced||[],l.attributesForced.pus
h({name:h,value:_}),u.forcedValue=_),"<"===b&&(u.validValues=a(_,"?"))),T.test(h)?(l.attributePatterns=l.attributePatterns||[],u.pattern=d(h),l.attributePatterns.push(u)):(g[h]||v.push(h),g[h]=u)}w||"@"!=p||(w=g,E=v),x&&(l.outputName=p,y[x]=l),T.test(p)?(l.pattern=d(p),C.push(l)):y[p]=l}}function p(e){y={},C=[],f(e),s(E,function(e,t){b[t]=e.children})}function h(e){var n=/^(~)?(.+)$/;e&&(i.text_block_elements=i.block_elements=null,s(t(e,","),function(e){var t=n.exec(e),r="~"===t[1],i=r?"span":"div",o=t[2];if(b[o]=b[i],M[o]=i,r||(R[o.toUpperCase()]={},R[o]={}),!y[o]){var a=y[i];a=l({},a),delete a.removeEmptyAttrs,delete a.removeEmpty,y[o]=a}s(b,function(e,t){e[i]&&(b[t]=e=l({},b[t]),e[o]=e[i])})}))}function m(n){var r=/^([+\-]?)(\w+)\[([^\]]+)\]$/;i[e.schema]=null,n&&s(t(n,","),function(e){var n=r.exec(e),i,o;n&&(o=n[1],i=o?b[n[2]]:b[n[2]]={"#comment
":{}},i=b[n[2]],s(t(n[3],"|"),function(e){"-"===o?delete i[e]:i[e]={}}))})}function g(e){var t=y[e],n;if(t)return t;for(n=C.length;n--;)if(t=C[n],t.pattern.test(e))return t}var v=this,y={},b={},C=[],x,w,E,N,_,S,k,T,R,A,B,D,L,M={},P={};e=e||{},E=n(e.schema),e.verify_html===!1&&(e.valid_elements="*[*]"),x=r(e.valid_styles),w=r(e.invalid_styles,"map"),T=r(e.valid_classes,"map"),N=o("whitespace_elements","pre script noscript style textarea video audio iframe object code"),_=o("self_closing_elements","colgroup dd dt li option p td tfoot th thead tr"),S=o("short_ended_elements","area base basefont br col frame hr img input isindex link meta param embed source wbr track"),k=o("boolean_attributes","checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls"),A=o("non_empty_elemen
ts","td th iframe video audio object script pre code",S),B=o("move_caret_before_on_enter_elements","table",A),D=o("text_block_elements","h1 h2 h3 h4 h5 h6 p div address pre form blockquote center dir fieldset header footer article section hgroup aside nav figure"),R=o("block_elements","hr table tbody thead tfoot th tr td li ol ul caption dl dt dd noscript menu isindex option datalist select optgroup figcaption",D),L=o("text_inline_elements","span strong b em i font strike u var cite dfn code mark q sup sub samp"),s((e.special||"script noscript style textarea").split(" "),function(e){P[e]=new RegExp("</"+e+"[^>]*>","gi")}),e.valid_elements?p(e.valid_elements):(s(E,function(e,t){y[t]={attributes:e.attributes,attributesOrder:e.attributesOrder},b[t]=e.children}),"html5"!=e.schema&&s(t("strong/b em/i"),functi
on(e){e=t(e,"/"),y[e[1]].outputName=e[0]}),s(t("ol ul sub sup blockquote span font a table tbody tr strong em b i"),function(e){y[e]&&(y[e].removeEmpty=!0)}),s(t("p h1 h2 h3 h4 h5 h6 th td pre div address caption"),function(e){y[e].paddEmpty=!0}),s(t("span"),function(e){y[e].removeEmptyAttrs=!0})),h(e.custom_elements),m(e.valid_children),f(e.extended_valid_elements),m("+ol[ul|ol],+ul[ul|ol]"),s({dd:"dl",dt:"dl",li:"ul ol",td:"tr",th:"tr",tr:"tbody thead tfoot",tbody:"table",thead:"table",tfoot:"table",legend:"fieldset",area:"map",param:"video audio object"},function(e,n){y[n]&&(y[n].parentsRequired=t(e))}),e.invalid_elements&&s(u(e.invalid_elements),function(e){y[e]&&delete y[e]}),g("span")||f("span[!data-mce-type|*]"),v.children=b,v.getValidStyles=function(){retur
n x},v.getInvalidStyles=function(){return w},v.getValidClasses=function(){return T},v.getBoolAttrs=function(){return k},v.getBlockElements=function(){return R},v.getTextBlockElements=function(){return D},v.getTextInlineElements=function(){return L},v.getShortEndedElements=function(){return S},v.getSelfClosingElements=function(){return _},v.getNonEmptyElements=function(){return A},v.getMoveCaretBeforeOnEnterElements=function(){return B},v.getWhiteSpaceElements=function(){return N},v.getSpecialElements=function(){return P},v.isValidChild=function(e,t){var n=b[e];return!(!n||!n[t])},v.isValid=function(e,t){var n,r,i=g(e);if(i){if(!t)return!0;if(i.attributes[t])return!0;if(n=i.attributePatterns)for(r=n.length;r--;)if(n[r].pattern.test(e))return!0}return!1},v.getElementRule=g,v.getCustomElements=function(){return M},v.addValidElements=f,v.setValidElements=p,v.addCustomElements=h,v.addValidChildren=m,v.elements=y}}),r(D,[B,C,m],function(e,t,n){function r(e,t,n){var r=1,i,o,a,s;for(s=e.get
ShortEndedElements(),a=/<([!?\/])?([A-Za-z0-9\-_\:\.]+)((?:\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\/|\s+)>/g,a.lastIndex=i=n;o=a.exec(t);){if(i=a.lastIndex,"/"===o[1])r--;else if(!o[1]){if(o[2]in s)continue;r++}if(0===r)break}return i}function i(i,a){function s(){}var l=this;i=i||{},l.schema=a=a||new e,i.fix_self_closing!==!1&&(i.fix_self_closing=!0),o("comment cdata text start end pi doctype".split(" "),function(e){e&&(l[e]=i[e]||s)}),l.parse=function(e){function o(e){var t,n;for(t=p.length;t--&&p[t].name!==e;);if(t>=0){for(n=p.length-1;n>=t;n--)e=p[n],e.valid&&l.end(e.name);p.length=t}}function s(e,t,n,r,o){var a,s,l=/[\s\u0000-\u001F]+/g;if(t=t.toLowerCase(),n=t in x?t:z(n||r||o||""),E&&!y&&0!==t.indexOf("data-")){if(a=T[t],!a&&R){for(s=R.length;s--&&(a=R[s],!a.pattern.test(t)););s===-1&&(a=null)}if(!a)return;if
(a.validValues&&!(n in a.validValues))return}if(W[t]&&!i.allow_script_urls){var u=n.replace(l,"");try{u=decodeURIComponent(u)}catch(c){u=unescape(u)}if(V.test(u))return;if(!i.allow_html_data_urls&&$.test(u)&&!/^data:image\//i.test(u))return}h.map[t]=n,h.push({name:t,value:n})}var l=this,u,c=0,d,f,p=[],h,m,g,v,y,b,C,x,w,E,N,_,S,k,T,R,A,B,D,L,M,P,O,H,I,F=0,z=t.decode,U,W=n.makeMap("src,href,data,background,formaction,poster"),V=/((java|vb)script|mhtml):/i,$=/^data:/i;for(P=new RegExp("<(?:(?:!--([\\w\\W]*?)-->)|(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|(?:!DOCTYPE([\\w\\W]*?)>)|(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|(?:\\/([^>]+)>)|(?:([A-Za-z0-9\\-_\\:\\.]+)((?:\\s+[^\"'>]+(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>]*))*|\\/|\\s+)>))","g"),O=/([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:[^\"])*)\")|(?:\'((?:[^\'])*)\')|([^>\s]+)))?/g,C=a.getShortEndedElements(),M=i.s
elf_closing_elements||a.getSelfClosingElements(),x=a.getBoolAttrs(),E=i.validate,b=i.remove_internals,U=i.fix_self_closing,H=a.getSpecialElements();u=P.exec(e);){if(c<u.index&&l.text(z(e.substr(c,u.index-c))),d=u[6])d=d.toLowerCase(),":"===d.charAt(0)&&(d=d.substr(1)),o(d);else if(d=u[7]){if(d=d.toLowerCase(),":"===d.charAt(0)&&(d=d.substr(1)),w=d in C,U&&M[d]&&p.length>0&&p[p.length-1].name===d&&o(d),!E||(N=a.getElementRule(d))){if(_=!0,E&&(T=N.attributes,R=N.attributePatterns),(k=u[8])?(y=k.indexOf("data-mce-type")!==-1,y&&b&&(_=!1),h=[],h.map={},k.replace(O,s)):(h=[],h.map={}),E&&!y){if(A=N.attributesRequired,B=N.attributesDefault,D=N.attributesForced,L=N.removeEmptyAttrs,L&&!h.length&&(_=!1),D)for(m=D.length;m--;)S=D[m],v=S.name,I=S.value,"{$uid}"===I&&(I="mce_"+F++),h.map[v]=I,h.push({name:v,value:I});if(B)for(m=
B.length;m--;)S=B[m],v=S.name,v in h.map||(I=S.value,"{$uid}"===I&&(I="mce_"+F++),h.map[v]=I,h.push({name:v,value:I}));if(A){for(m=A.length;m--&&!(A[m]in h.map););m===-1&&(_=!1)}if(S=h.map["data-mce-bogus"]){if("all"===S){c=r(a,e,P.lastIndex),P.lastIndex=c;continue}_=!1}}_&&l.start(d,h,w)}else _=!1;if(f=H[d]){f.lastIndex=c=u.index+u[0].length,(u=f.exec(e))?(_&&(g=e.substr(c,u.index-c)),c=u.index+u[0].length):(g=e.substr(c),c=e.length),_&&(g.length>0&&l.text(g,!0),l.end(d)),P.lastIndex=c;continue}w||(k&&k.indexOf("/")==k.length-1?_&&l.end(d):p.push({name:d,valid:_}))}else(d=u[1])?(">"===d.charAt(0)&&(d=" "+d),i.allow_conditional_comments||"[if"!==d.substr(0,3).toLowerCase()||(d=" "+d),l.comment(d)):(d=u[2])?l.cdata(d):(d=u[3])?l.doctype(d):(d=u[4])&&l.pi(d,u[5]);c=u.index+u[0].length}for(c<e.length&a
mp;&l.text(z(e.substr(c))),m=p.length-1;m>=0;m--)d=p[m],d.valid&&l.end(d.name)}}var o=n.each;return i.findEndTag=r,i}),r(L,[A,B,D,m],function(e,t,n,r){var i=r.makeMap,o=r.each,a=r.explode,s=r.extend,l=function(t,n){t.padd_empty_with_br?n.empty().append(new e("br","1")).shortEnded=!0:n.empty().append(new e("#text","3")).value="\xa0"},u=function(e,t){return e&&e.firstChild===e.lastChild&&e.firstChild.name===t};return function(c,d){function f(t){var n,r,o,a,s,l,c,f,h,m,g,v,y,b,C,x;for(v=i("tr,td,th,tbody,thead,tfoot,table"),m=d.getNonEmptyElements(),g=d.getWhiteSpaceElements(),y=d.getTextBlockElements(),b=d.getSpecialElements(),n=0;n<t.length;n++)if(r=t[n],r.parent&&!r.fixed)if(y[r.name]&&"li"==r.parent.name){for(C=r.next;C&&y[C.name];)C.name="li",C.fixed=!0,r.parent.insert(C,r.parent),C=C.next;r.unwrap(r)}else{for(a=[r],o=r.parent;o&&!d.isVa
lidChild(o.name,r.name)&&!v[o.name];o=o.parent)a.push(o);if(o&&a.length>1){for(a.reverse(),s=l=p.filterNode(a[0].clone()),h=0;h<a.length-1;h++){for(d.isValidChild(l.name,a[h].name)?(c=p.filterNode(a[h].clone()),l.append(c)):c=l,f=a[h].firstChild;f&&f!=a[h+1];)x=f.next,c.append(f),f=x;l=c}s.isEmpty(m,g)?o.insert(r,a[0],!0):(o.insert(s,a[0],!0),o.insert(r,s)),o=a[0],(o.isEmpty(m,g)||u(o,"br"))&&o.empty().remove()}else if(r.parent){if("li"===r.name){if(C=r.prev,C&&("ul"===C.name||"ul"===C.name)){C.append(r);continue}if(C=r.next,C&&("ul"===C.name||"ul"===C.name)){C.insert(r,C.firstChild,!0);continue}r.wrap(p.filterNode(new e("ul",1)));continue}d.isValidChild(r.parent.name,"div")&&d.isValidChild("div",r.name)?r.wrap(p.filterNode(new e("div",1))):b[r.name]?r.empty().remove():r.unwrap()}}}var p=this,h={},m=[],g={},v={};c=c||{},c.v
alidate=!("validate"in c)||c.validate,c.root_name=c.root_name||"body",p.schema=d=d||new t,p.filterNode=function(e){var t,n,r;n in h&&(r=g[n],r?r.push(e):g[n]=[e]),t=m.length;for(;t--;)n=m[t].name,n in e.attributes.map&&(r=v[n],r?r.push(e):v[n]=[e]);return e},p.addNodeFilter=function(e,t){o(a(e),function(e){var n=h[e];n||(h[e]=n=[]),n.push(t)})},p.addAttributeFilter=function(e,t){o(a(e),function(e){var n;for(n=0;n<m.length;n++)if(m[n].name===e)return void m[n].callbacks.push(t);m.push({name:e,callbacks:[t]})})},p.parse=function(t,r){function o(){function e(e){e&&(t=e.firstChild,t&&3==t.type&&(t.value=t.value.replace(A,"")),t=e.lastChild,t&&3==t.type&&(t.value=t.value.replace(L,"")))}var t=b.firstChild,n,r;if(d.isValidChild(b.name,F.toLowerCase())){for(;t;)n=t.next,3==t.type||1==t.type&&"p"!==t.name&&!R[t.name]&&!t.attr("data-mce-type")?r?r.app
end(t):(r=a(F,1),r.attr(c.forced_root_block_attrs),b.insert(r,t),r.append(t)):(e(r),r=null),t=n;e(r)}}function a(t,n){var r=new e(t,n),i;return t in h&&(i=g[t],i?i.push(r):g[t]=[r]),r}function u(e){var t,n,r,i,o=d.getBlockElements();for(t=e.prev;t&&3===t.type;){if(r=t.value.replace(L,""),r.length>0)return void(t.value=r);if(n=t.next){if(3==n.type&&n.value.length){t=t.prev;continue}if(!o[n.name]&&"script"!=n.name&&"style"!=n.name){t=t.prev;continue}}i=t.prev,t.remove(),t=i}}function p(e){var t,n={};for(t in e)"li"!==t&&"p"!=t&&(n[t]=e[t]);return n}var y,b,C,x,w,E,N,_,S,k,T,R,A,B=[],D,L,M,P,O,H,I,F;if(r=r||{},g={},v={},R=s(i("script,style,head,html,body,title,meta,param"),d.getBlockElements()),I=d.getNonEmptyElements(),H=d.children,T=c.validate,F="forced_root_block"in r?r.forced_root_block:c.forced_root_block,O=d.getWhiteSpaceElements(),A=/^[ \t\r\n]+/,L=/[
\t\r\n]+$/,M=/[ \t\r\n]+/g,P=/^[ \t\r\n]+$/,y=new n({validate:T,allow_script_urls:c.allow_script_urls,allow_conditional_comments:c.allow_conditional_comments,self_closing_elements:p(d.getSelfClosingElements()),cdata:function(e){C.append(a("#cdata",4)).value=e},text:function(e,t){var n;D||(e=e.replace(M," "),C.lastChild&&R[C.lastChild.name]&&(e=e.replace(A,""))),0!==e.length&&(n=a("#text",3),n.raw=!!t,C.append(n).value=e)},comment:function(e){C.append(a("#comment",8)).value=e},pi:function(e,t){C.append(a(e,7)).value=t,u(C)},doctype:function(e){var t;t=C.append(a("#doctype",10)),t.value=e,u(C)},start:function(e,t,n){var r,i,o,s,l;if(o=T?d.getElementRule(e):{}){for(r=a(o.outputName||e,1),r.attributes=t,r.shortEnded=n,C.append(r),l=H[C.name],l&&H[r.name]&&!l[r.name]&&B.push(r),i=m.length;i--;)s=m[i].name,s in t.map&&(S=v[s],S?S.push(r):v[s]=[r]);R[e]&&u(r),n||(C=r)
,!D&&O[e]&&(D=!0)}},end:function(e){var t,n,r,i,o;if(n=T?d.getElementRule(e):{}){if(R[e]&&!D){if(t=C.firstChild,t&&3===t.type)if(r=t.value.replace(A,""),r.length>0)t.value=r,t=t.next;else for(i=t.next,t.remove(),t=i;t&&3===t.type;)r=t.value,i=t.next,(0===r.length||P.test(r))&&(t.remove(),t=i),t=i;if(t=C.lastChild,t&&3===t.type)if(r=t.value.replace(L,""),r.length>0)t.value=r,t=t.prev;else for(i=t.prev,t.remove(),t=i;t&&3===t.type;)r=t.value,i=t.prev,(0===r.length||P.test(r))&&(t.remove(),t=i),t=i}if(D&&O[e]&&(D=!1),(n.removeEmpty||n.paddEmpty)&&C.isEmpty(I,O))if(n.paddEmpty)l(c,C);else if(!C.attributes.map.name&&!C.attributes.map.id)return o=C.parent,R[C.name]?C.empty().remove():C.unwrap(),void(C=o);C=C.parent}}},d),b=C=new e(r.context||c.root_name,11),y.parse(t),T&&B.length&&(r.context?r.invalid=!0:f(B)),F&&("body"==b.nam
e||r.isRootContent)&&o(),!r.invalid){for(k in g){for(S=h[k],x=g[k],N=x.length;N--;)x[N].parent||x.splice(N,1);for(w=0,E=S.length;w<E;w++)S[w](x,k,r)}for(w=0,E=m.length;w<E;w++)if(S=m[w],S.name in v){for(x=v[S.name],N=x.length;N--;)x[N].parent||x.splice(N,1);for(N=0,_=S.callbacks.length;N<_;N++)S.callbacks[N](x,S.name,r)}}return b},c.remove_trailing_brs&&p.addNodeFilter("br",function(t){var n,r=t.length,i,o=s({},d.getBlockElements()),a=d.getNonEmptyElements(),u,f,p,h,m=d.getNonEmptyElements(),g,v;for(o.body=1,n=0;n<r;n++)if(i=t[n],u=i.parent,o[i.parent.name]&&i===u.lastChild){for(p=i.prev;p;){if(h=p.name,"span"!==h||"bookmark"!==p.attr("data-mce-type")){if("br"!==h)break;if("br"===h){i=null;break}}p=p.prev}i&&(i.remove(),u.isEmpty(a,m)&&(g=d.getElementRule(u.name),g&&(g.removeEmpty?u.remove():g.paddEmpty&&l(c,u))))}else{for(f=i;u&&u.firstChild===f&am
p;&u.lastChild===f&&(f=u,!o[u.name]);)u=u.parent;f===u&&c.padd_empty_with_br!==!0&&(v=new e("#text",3),v.value="\xa0",i.replace(v))}}),c.allow_unsafe_link_target||p.addAttributeFilter("href",function(e){function t(e){return e=n(e),e?[e,l].join(" "):l}function n(e){var t=new RegExp("("+l.replace(" ","|")+")","g");return e&&(e=r.trim(e.replace(t,""))),e?e:null}function i(e,r){return r?t(e):n(e)}for(var o=e.length,a,s,l="noopener noreferrer";o--;)a=e[o],s=a.attr("rel"),"a"===a.name&&a.attr("rel",i(s,"_blank"==a.attr("target")))}),c.allow_html_in_named_anchor||p.addAttributeFilter("id,name",function(e){for(var t=e.length,n,r,i,o;t--;)if(o=e[t],"a"===o.name&&o.firstChild&&!o.attr("href")){i=o.parent,n=o.lastChild;do r=n.prev,i.insert(n,o),n=r
;while(n)}}),c.fix_list_elements&&p.addNodeFilter("ul,ol",function(t){for(var n=t.length,r,i;n--;)if(r=t[n],i=r.parent,"ul"===i.name||"ol"===i.name)if(r.prev&&"li"===r.prev.name)r.prev.append(r);else{var o=new e("li",1);o.attr("style","list-style-type: none"),r.wrap(o)}}),c.validate&&d.getValidClasses()&&p.addAttributeFilter("class",function(e){for(var t=e.length,n,r,i,o,a,s=d.getValidClasses(),l,u;t--;){for(n=e[t],r=n.attr("class").split(" "),a="",i=0;i<r.length;i++)o=r[i],u=!1,l=s["*"],l&&l[o]&&(u=!0),l=s[n.name],!u&&l&&l[o]&&(u=!0),u&&(a&&(a+=" "),a+=o);a.length||(a=null),n.attr("class",a)}})}}),r(M,[C,m],function(e,t){var n=t.makeMap;return function(t){var r=[],i,o,a,s,l;return t=t||{},i=t.indent,o=n(t.indent_before||""),a=n(t.indent_after||&
quot;"),s=e.getEncodeFunc(t.entity_encoding||"raw",t.entities),l="html"==t.element_format,{start:function(e,t,n){var u,c,d,f;if(i&&o[e]&&r.length>0&&(f=r[r.length-1],f.length>0&&"\n"!==f&&r.push("\n")),r.push("<",e),t)for(u=0,c=t.length;u<c;u++)d=t[u],r.push(" ",d.name,'="',s(d.value,!0),'"');!n||l?r[r.length]=">":r[r.length]=" />",n&&i&&a[e]&&r.length>0&&(f=r[r.length-1],f.length>0&&"\n"!==f&&r.push("\n"))},end:function(e){var t;r.push("</",e,">"),i&&a[e]&&r.length>0&&(t=r[r.length-1],t.length>0&&"\n"!==t&&r.push("\n"))},text:function(e,t){e.length>0&&(r[r.length]=t?e:s(e))},cdata:function(e){r.push("<![CDATA[",e,"]]>")},comment:fun
ction(e){r.push("<!--",e,"-->")},pi:function(e,t){t?r.push("<?",e," ",s(t),"?>"):r.push("<?",e,"?>"),i&&r.push("\n")},doctype:function(e){r.push("<!DOCTYPE",e,">",i?"\n":"")},reset:function(){r.length=0},getContent:function(){return r.join("").replace(/\n$/,"")}}}}),r(P,[M,B],function(e,t){return function(n,r){var i=this,o=new e(n);n=n||{},n.validate=!("validate"in n)||n.validate,i.schema=r=r||new t,i.writer=o,i.serialize=function(e){function t(e){var n=i[e.type],s,l,u,c,d,f,p,h,m;if(n)n(e);else{if(s=e.name,l=e.shortEnded,u=e.attributes,a&&u&&u.length>1&&(f=[],f.map={},m=r.getElementRule(e.name))){for(p=0,h=m.attributesOrder.length;p<h;p++)c=m.attributesOrder[p],c in u.map&&(d=u.map[c],f.map[c]=d,f.push({name:c,value:d}));for(p=0,h=u.length;p<h;p++)c=u[p].name,c i
n f.map||(d=u.map[c],f.map[c]=d,f.push({name:c,value:d}));u=f}if(o.start(e.name,u,l),!l){if(e=e.firstChild)do t(e);while(e=e.next);o.end(s)}}}var i,a;return a=n.validate,i={3:function(e){o.text(e.value,e.raw)},8:function(e){o.comment(e.value)},7:function(e){o.pi(e.name,e.value)},10:function(e){o.doctype(e.value)},4:function(e){o.cdata(e.value)},11:function(e){if(e=e.firstChild)do t(e);while(e=e.next)}},o.reset(),1!=e.type||n.inner?i[11](e):t(e),o.getContent()}}}),r(O,[w,L,D,C,P,A,B,d,m,S],function(e,t,n,r,i,o,a,s,l,u){function c(e){function t(e){return e&&"br"===e.name}var n,r;n=e.lastChild,t(n)&&(r=n.prev,t(r)&&(n.remove(),r.remove()))}var d=l.each,f=l.trim,p=e.DOM;return function(e,o){function h(e){var t=new RegExp(["<span[^>]+data-mce-bogus[^>]+>[\u200b\ufeff]+<\\/span>","\\s?("+x.join("|")+')="[^"]+"'].join("|"),"gi");return e=u.trim(e.replace(t,""))}fun
ction m(e){var t=e,r=/<(\w+) [^>]*data-mce-bogus="all"[^>]*>/g,i,a,s,l,u,c=o.schema;for(t=h(t),u=c.getShortEndedElements();l=r.exec(t);)a=r.lastIndex,s=l[0].length,i=u[l[1]]?a:n.findEndTag(c,t,a),t=t.substring(0,a-s)+t.substring(i),r.lastIndex=a-s;return t}function g(){return m(o.getBody().innerHTML)}function v(e){l.inArray(x,e)===-1&&(C.addAttributeFilter(e,function(e,t){for(var n=e.length;n--;)e[n].attr(t,null)}),x.push(e))}var y,b,C,x=["data-mce-selected"];return o&&(y=o.dom,b=o.schema),y=y||p,b=b||new a(e),e.entity_encoding=e.entity_encoding||"named",e.remove_trailing_brs=!("remove_trailing_brs"in e)||e.remove_trailing_brs,C=new t(e,b),C.addAttributeFilter("data-mce-tabindex",function(e,t){for(var n=e.length,r;n--;)r=e[n],r.attr("tabindex",r.attributes.map["data-mce-tabindex"]),r.attr(t,null)}),C.addAttributeFilter("src,href,style",function(t,n){for(var r=t.length,i,o,a=&q
uot;data-mce-"+n,s=e.url_converter,l=e.url_converter_scope,u;r--;)i=t[r],o=i.attributes.map[a],o!==u?(i.attr(n,o.length>0?o:null),i.attr(a,null)):(o=i.attributes.map[n],"style"===n?o=y.serializeStyle(y.parseStyle(o),i.name):s&&(o=s.call(l,o,n,i.name)),i.attr(n,o.length>0?o:null))}),C.addAttributeFilter("class",function(e){for(var t=e.length,n,r;t--;)n=e[t],r=n.attr("class"),r&&(r=n.attr("class").replace(/(?:^|\s)mce-item-\w+(?!\S)/g,""),n.attr("class",r.length>0?r:null))}),C.addAttributeFilter("data-mce-type",function(e,t,n){for(var r=e.length,i;r--;)i=e[r],"bookmark"!==i.attributes.map["data-mce-type"]||n.cleanup||i.remove()}),C.addNodeFilter("noscript",function(e){for(var t=e.length,n;t--;)n=e[t].firstChild,n&&(n.value=r.decode(n.value))}),C.addNodeFilter("script,style",function(e,t){function n(e){return e.replace(/(<!--\[CDATA\[|\]
\]-->)/g,"\n").replace(/^[\r\n]*|[\r\n]*$/g,"").replace(/^\s*((<!--)?(\s*\/\/)?\s*<!\[CDATA\[|(<!--\s*)?\/\*\s*<!\[CDATA\[\s*\*\/|(\/\/)?\s*<!--|\/\*\s*<!--\s*\*\/)\s*[\r\n]*/gi,"").replace(/\s*(\/\*\s*\]\]>\s*\*\/(-->)?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g,"")}for(var r=e.length,i,o,a;r--;)i=e[r],o=i.firstChild?i.firstChild.value:"","script"===t?(a=i.attr("type"),a&&i.attr("type","mce-no/type"==a?null:a.replace(/^mce\-/,"")),o.length>0&&(i.firstChild.value="// <![CDATA[\n"+n(o)+"\n// ]]>")):o.length>0&&(i.firstChild.value="<!--\n"+n(o)+"\n-->")}),C.addNodeFilter("#comment",function(e){for(var t=e.length,n;t--;)n=e[t],0===n.value.indexOf("[CDATA[")?(n.name="#cdata",n.type=4,n.value=n.value.r
eplace(/^\[CDATA\[|\]\]$/g,"")):0===n.value.indexOf("mce:protected ")&&(n.name="#text",n.type=3,n.raw=!0,n.value=unescape(n.value).substr(14))}),C.addNodeFilter("xml:namespace,input",function(e,t){for(var n=e.length,r;n--;)r=e[n],7===r.type?r.remove():1===r.type&&("input"!==t||"type"in r.attributes.map||r.attr("type","text"))}),C.addAttributeFilter("data-mce-src,data-mce-href,data-mce-style,data-mce-selected,data-mce-expando,data-mce-type,data-mce-resize",function(e,t){for(var n=e.length;n--;)e[n].attr(t,null)}),{schema:b,addNodeFilter:C.addNodeFilter,addAttributeFilter:C.addAttributeFilter,serialize:function(t,n){var r=this,o,a,l,p,h,m;return s.ie&&y.select("script,style,select,map").length>0?(h=t.innerHTML,t=t.cloneNode(!1),y.setHTML(t,h)):t=t.cloneNode(!0),o=document.implementation,o.createHTMLDocument&&(a=o.createHTMLDocument(""),d(&quo
t;BODY"==t.nodeName?t.childNodes:[t],function(e){a.body.appendChild(a.importNode(e,!0))}),t="BODY"!=t.nodeName?a.body.firstChild:a.body,l=y.doc,y.doc=a),n=n||{},n.format=n.format||"html",n.selection&&(n.forced_root_block=""),n.no_events||(n.node=t,r.onPreProcess(n)),m=C.parse(f(n.getInner?t.innerHTML:y.getOuterHTML(t)),n),c(m),p=new i(e,b),n.content=p.serialize(m),n.cleanup||(n.content=u.trim(n.content),n.content=n.content.replace(/\uFEFF/g,"")),n.no_events||r.onPostProcess(n),l&&(y.doc=l),n.node=null,n.content},addRules:function(e){b.addValidElements(e)},setRules:function(e){b.setValidElements(e)},onPreProcess:function(e){o&&o.fire("PreProcess",e)},onPostProcess:function(e){o&&o.fire("PostProcess",e)},addTempAttr:v,trimHtml:h,getTrimmedContent:g,trimContent:m}}}),r(H,[],function(){function e(e){function t(t,n){var r,i=0,o,a,s,l,u,c,d=-1,f;if(r=t.duplicate(),r.collapse(n),f=r.parentEleme
nt(),f.ownerDocument===e.dom.doc){for(;"false"===f.contentEditable;)f=f.parentNode;if(!f.hasChildNodes())return{node:f,inside:1};for(s=f.children,o=s.length-1;i<=o;)if(c=Math.floor((i+o)/2),l=s[c],r.moveToElementText(l),d=r.compareEndPoints(n?"StartToStart":"EndToEnd",t),d>0)o=c-1;else{if(!(d<0))return{node:l};i=c+1}if(d<0)for(l?r.collapse(!1):(r.moveToElementText(f),r.collapse(!0),l=f,a=!0),u=0;0!==r.compareEndPoints(n?"StartToStart":"StartToEnd",t)&&0!==r.move("character",1)&&f==r.parentElement();)u++;else for(r.collapse(!0),u=0;0!==r.compareEndPoints(n?"StartToStart":"StartToEnd",t)&&0!==r.move("character",-1)&&f==r.parentElement();)u++;return{node:l,position:d,offset:u,inside:a}}}function n(){function n(e){var n=t(o,e),r,i,s=0,l,u,c;if(r=n.node,i=n.offset,n.inside&&!r.hasChildNodes())return void a[e?"setStart":"setEnd"]
(r,0);if(i===u)return void a[e?"setStartBefore":"setEndAfter"](r);if(n.position<0){if(l=n.inside?r.firstChild:r.nextSibling,!l)return void a[e?"setStartAfter":"setEndAfter"](r);if(!i)return void(3==l.nodeType?a[e?"setStart":"setEnd"](l,0):a[e?"setStartBefore":"setEndBefore"](l));for(;l;){if(3==l.nodeType&&(c=l.nodeValue,s+=c.length,s>=i)){r=l,s-=i,s=c.length-s;break}l=l.nextSibling}}else{if(l=r.previousSibling,!l)return a[e?"setStartBefore":"setEndBefore"](r);if(!i)return void(3==r.nodeType?a[e?"setStart":"setEnd"](l,r.nodeValue.length):a[e?"setStartAfter":"setEndAfter"](l));for(;l;){if(3==l.nodeType&&(s+=l.nodeValue.length,s>=i)){r=l,s-=i;break}l=l.previousSibling}}a[e?"setStart":"setEnd"](r,s)}var o=e.getRng(),a=i.createRng(),s,l,u,c,d;if(s=o.item?o.item(0):o.parentElement(),s.ownerDocument!=i.doc)r
eturn a;if(l=e.isCollapsed(),o.item)return a.setStart(s.parentNode,i.nodeIndex(s)),a.setEnd(a.startContainer,a.startOffset+1),a;try{n(!0),l||n()}catch(f){if(f.number!=-2147024809)throw f;d=r.getBookmark(2),u=o.duplicate(),u.collapse(!0),s=u.parentElement(),l||(u=o.duplicate(),u.collapse(!1),c=u.parentElement(),c.innerHTML=c.innerHTML),s.innerHTML=s.innerHTML,r.moveToBookmark(d),o=e.getRng(),n(!0),l||n()}return a}var r=this,i=e.dom,o=!1;this.getBookmark=function(n){function r(e){var t,n,r,o,a=[];for(t=e.parentNode,n=i.getRoot().parentNode;t!=n&&9!==t.nodeType;){for(r=t.children,o=r.length;o--;)if(e===r[o]){a.push(o);break}e=t,t=t.parentNode}return a}function o(e){var n;if(n=t(a,e))return{position:n.position,offset:n.offset,indexes:r(n.node),inside:n.inside}}var a=e.getRng(),s={};return 2===n&&(a.item?s.start={ctrl:!0,indexes:r(a.item(0))}:(s.start=o(!0),e.isCollapsed()||(s.end=o()))),s},this.moveToBookmark=function(e){function t(e){var t,n,r,o;for(t=i.getRoot(),n=e.le
ngth-1;n>=0;n--)o=t.children,r=e[n],r<=o.length-1&&(t=o[r]);return t}function n(n){var i=e[n?"start":"end"],a,s,l,u;i&&(a=i.position>0,s=o.createTextRange(),s.moveToElementText(t(i.indexes)),u=i.offset,u!==l?(s.collapse(i.inside||a),s.moveStart("character",a?-u:u)):s.collapse(n),r.setEndPoint(n?"StartToStart":"EndToStart",s),n&&r.collapse(!0))}var r,o=i.doc.body;e.start&&(e.start.ctrl?(r=o.createControlRange(),r.addElement(t(e.start.indexes)),r.select()):(r=o.createTextRange(),n(!0),n(),r.select()))},this.addRange=function(t){function n(e){var t,n,a,d,h;a=i.create("a"),t=e?s:u,n=e?l:c,d=r.duplicate(),t!=f&&t!=f.documentElement||(t=p,n=0),3==t.nodeType?(t.parentNode.insertBefore(a,t),d.moveToElementText(a),d.moveStart("character",n),i.remove(a),r.setEndPoint(e?"StartToStart":"EndToEnd",d)):(h=t.childNodes,h.length?(n>=h.length?i.insertAfter(a,h
[h.length-1]):t.insertBefore(a,h[n]),d.moveToElementText(a)):t.canHaveHTML&&(t.innerHTML="<span></span>",a=t.firstChild,d.moveToElementText(a),d.collapse(o)),r.setEndPoint(e?"StartToStart":"EndToEnd",d),i.remove(a))}var r,a,s,l,u,c,d,f=e.dom.doc,p=f.body,h,m;if(s=t.startContainer,l=t.startOffset,u=t.endContainer,c=t.endOffset,r=p.createTextRange(),s==u&&1==s.nodeType){if(l==c&&!s.hasChildNodes()){if(s.canHaveHTML)return d=s.previousSibling,d&&!d.hasChildNodes()&&i.isBlock(d)?d.innerHTML="":d=null,s.innerHTML="<span></span><span></span>",r.moveToElementText(s.lastChild),r.select(),i.doc.selection.clear(),s.innerHTML="",void(d&&(d.innerHTML=""));l=i.nodeIndex(s),s=s.parentNode}if(l==c-1)try{if(m=s.childNodes[l],a=p.createControlRange(),a.addElement(m),a.select(),h=e.getRng(),h.item&
&m===h.item(0))return}catch(g){}}n(!0),n(),r.select()},this.getRangeAt=n}return e}),r(I,[d],function(e){return{BACKSPACE:8,DELETE:46,DOWN:40,ENTER:13,LEFT:37,RIGHT:39,SPACEBAR:32,TAB:9,UP:38,modifierPressed:function(e){return e.shiftKey||e.ctrlKey||e.altKey||this.metaKeyPressed(e)},metaKeyPressed:function(t){return e.mac?t.metaKey:t.ctrlKey&&!t.altKey}}}),r(F,[I,m,c,d,_],function(e,t,n,r,i){function o(e,t){for(;t&&t!=e;){if(s(t)||a(t))return t;t=t.parentNode}return null}var a=i.isContentEditableFalse,s=i.isContentEditableTrue;return function(i,s){function l(e){var t=s.settings.object_resizing;return t!==!1&&!r.iOS&&("string"!=typeof t&&(t="table,img,div"),"false"!==e.getAttribute("data-mce-resize")&&(e!=s.getBody()&&s.dom.is(e,t)))}function u(t){var n,r,i,o,a;n=t.screenX-L,r=t.screenY-M,U=n*B[2]+H,W=r*B[3]+I,U=U<5?5:U,W=W<5?5:W,i="IMG"==k.nodeName&&s.settings.r
esize_img_proportional!==!1?!e.modifierPressed(t):e.modifierPressed(t)||"IMG"==k.nodeName&&B[2]*B[3]!==0,i&&(j(n)>j(r)?(W=Y(U*F),U=Y(W/F)):(U=Y(W/F),W=Y(U*F))),_.setStyles(T,{width:U,height:W}),o=B.startPos.x+n,a=B.startPos.y+r,o=o>0?o:0,a=a>0?a:0,_.setStyles(R,{left:o,top:a,display:"block"}),R.innerHTML=U+" × "+W,B[2]<0&&T.clientWidth<=U&&_.setStyle(T,"left",P+(H-U)),B[3]<0&&T.clientHeight<=W&&_.setStyle(T,"top",O+(I-W)),n=X.scrollWidth-K,r=X.scrollHeight-G,n+r!==0&&_.setStyles(R,{left:o-n,top:a-r}),z||(s.fire("ObjectResizeStart",{target:k,width:H,height:I}),z=!0)}function c(){function e(e,t){t&&(k.style[e]||!s.schema.isValid(k.nodeName.toLowerCase(),e)?_.setStyle(k,e,t):_.setAttrib(k,e,t))}z=!1,e("width",U),e("height",W),_.unbind(V,"mousemove",u),_.unbind(V,"mouseup",c),$!=V&&(_.un
bind($,"mousemove",u),_.unbind($,"mouseup",c)),_.remove(T),_.remove(R),q&&"TABLE"!=k.nodeName||d(k),s.fire("ObjectResized",{target:k,width:U,height:W}),_.setAttrib(k,"style",_.getAttrib(k,"style")),s.nodeChanged()}function d(e,t,n){var i,o,a,d,p;f(),x(),i=_.getPos(e,X),P=i.x,O=i.y,p=e.getBoundingClientRect(),o=p.width||p.right-p.left,a=p.height||p.bottom-p.top,k!=e&&(C(),k=e,U=W=0),d=s.fire("ObjectSelected",{target:e}),l(e)&&!d.isDefaultPrevented()?S(A,function(e,i){function s(t){L=t.screenX,M=t.screenY,H=k.clientWidth,I=k.clientHeight,F=I/H,B=e,e.startPos={x:o*e[0]+P,y:a*e[1]+O},K=X.scrollWidth,G=X.scrollHeight,T=k.cloneNode(!0),_.addClass(T,"mce-clonedresizable"),_.setAttrib(T,"data-mce-bogus","all"),T.contentEditable=!1,T.unSelectabe=!0,_.setStyles(T,{left:P,top:O,margin:0}),T.removeAttribute("data-mce-selected"),X.appendChild(T),_.bind(V,"mou
semove",u),_.bind(V,"mouseup",c),$!=V&&(_.bind($,"mousemove",u),_.bind($,"mouseup",c)),R=_.add(X,"div",{"class":"mce-resize-helper","data-mce-bogus":"all"},H+" × "+I)}var l;return t?void(i==t&&s(n)):(l=_.get("mceResizeHandle"+i),l&&_.remove(l),l=_.add(X,"div",{id:"mceResizeHandle"+i,"data-mce-bogus":"all","class":"mce-resizehandle",unselectable:!0,style:"cursor:"+i+"-resize; margin:0; padding:0"}),r.ie&&(l.contentEditable=!1),_.bind(l,"mousedown",function(e){e.stopImmediatePropagation(),e.preventDefault(),s(e)}),e.elm=l,void _.setStyles(l,{left:o*e[0]+P-l.offsetWidth/2,top:a*e[1]+O-l.offsetHeight/2}))}):f(),k.setAttribute("data-mce-selected","1")}function f(){var e,t;x(),k&&k.removeAttribute("data-mce-selected");
for(e in A)t=_.get("mceResizeHandle"+e),t&&(_.unbind(t),_.remove(t))}function p(e){function t(e,t){if(e)do if(e===t)return!0;while(e=e.parentNode)}var n,r;if(!z&&!s.removed)return S(_.select("img[data-mce-selected],hr[data-mce-selected]"),function(e){e.removeAttribute("data-mce-selected")}),r="mousedown"==e.type?e.target:i.getNode(),r=_.$(r).closest(q?"table":"table,img,hr")[0],t(r,X)&&(w(),n=i.getStart(!0),t(n,r)&&t(i.getEnd(!0),r)&&(!q||r!=n&&"IMG"!==n.nodeName))?void d(r):void f()}function h(e,t,n){e&&e.attachEvent&&e.attachEvent("on"+t,n)}function m(e,t,n){e&&e.detachEvent&&e.detachEvent("on"+t,n)}function g(e){var t=e.srcElement,n,r,i,o,a,l,u;n=t.getBoundingClientRect(),l=D.clientX-n.left,u=D.clientY-n.top;for(r in A)if(i=A[r],o=t.offsetWidth*i[0],a=t.offsetHeight*i[1],j(o-l)<8&&j(a-u)<8){B=i;brea
k}z=!0,s.fire("ObjectResizeStart",{target:k,width:k.clientWidth,height:k.clientHeight}),s.getDoc().selection.empty(),d(t,r,D)}function v(e){e.preventDefault?e.preventDefault():e.returnValue=!1}function y(e){return a(o(s.getBody(),e))}function b(e){var t=e.srcElement;if(y(t))return void v(e);if(t!=k){if(s.fire("ObjectSelected",{target:t}),C(),0===t.id.indexOf("mceResizeHandle"))return void(e.returnValue=!1);
-"IMG"!=t.nodeName&&"TABLE"!=t.nodeName||(f(),k=t,h(t,"resizestart",g))}}function C(){m(k,"resizestart",g)}function x(){for(var e in A){var t=A[e];t.elm&&(_.unbind(t.elm),delete t.elm)}}function w(){try{s.getDoc().execCommand("enableObjectResizing",!1,!1)}catch(e){}}function E(e){var t;if(q){t=V.body.createControlRange();try{return t.addElement(e),t.select(),!0}catch(n){}}}function N(){k=T=null,q&&(C(),m(X,"controlselect",b))}var _=s.dom,S=t.each,k,T,R,A,B,D,L,M,P,O,H,I,F,z,U,W,V=s.getDoc(),$=document,q=r.ie&&r.ie<11,j=Math.abs,Y=Math.round,X=s.getBody(),K,G;A={nw:[0,0,-1,-1],ne:[1,0,1,-1],se:[1,1,1,1],sw:[0,1,-1,1]};var J=".mce-content-body";return s.contentStyles.push(J+" div.mce-resizehandle {position: absolute;border: 1px solid black;box-sizing: box-sizing;background: #FFF;width: 7px;height: 7px;z-index: 10000}"+J+" .mce-resizehandle:hover {background: #000}&quo
t;+J+" img[data-mce-selected],"+J+" hr[data-mce-selected] {outline: 1px solid black;resize: none}"+J+" .mce-clonedresizable {position: absolute;"+(r.gecko?"":"outline: 1px dashed black;")+"opacity: .5;filter: alpha(opacity=50);z-index: 10000}"+J+" .mce-resize-helper {background: #555;background: rgba(0,0,0,0.75);border-radius: 3px;border: 1px;color: white;display: none;font-family: sans-serif;font-size: 12px;white-space: nowrap;line-height: 14px;margin: 5px 10px;padding: 5px;position: absolute;z-index: 10001}"),s.on("init",function(){q?(s.on("ObjectResized",function(e){"TABLE"!=e.target.nodeName&&(f(),E(e.target))}),h(X,"controlselect",b),s.on("mousedown",function(e){D=e})):(w(),r.ie>=11&&(s.on("mousedown click",function(e){var t=e.target,n=t.nodeName;z||!/^(TABLE|IMG|HR)$/.test(n)||y(t)||(s.selection.select(t,"TABLE"==n),&quo
t;mousedown"==e.type&&s.nodeChanged())}),s.dom.bind(X,"mscontrolselect",function(e){function t(e){n.setEditorTimeout(s,function(){s.selection.select(e)})}return y(e.target)?(e.preventDefault(),void t(e.target)):void(/^(TABLE|IMG|HR)$/.test(e.target.nodeName)&&(e.preventDefault(),"IMG"==e.target.tagName&&t(e.target)))})));var e=n.throttle(function(e){s.composing||p(e)});s.on("nodechange ResizeEditor ResizeWindow drop",e),s.on("keyup compositionend",function(t){k&&"TABLE"==k.nodeName&&e(t)}),s.on("hide blur",f)}),s.on("remove",x),{isResizable:l,showResizeRect:d,hideResizeRect:f,updateResizeRect:p,controlSelect:E,destroy:N}}}),r(z,[],function(){function e(e){return function(){return e}}function t(e){return function(t){return!e(t)}}function n(e,t){return function(n){return e(t(n))}}function r(){var e=s.call(arguments);return function(t){for(var n=0;n<e.length;n++)if(e[n]
(t))return!0;return!1}}function i(){var e=s.call(arguments);return function(t){for(var n=0;n<e.length;n++)if(!e[n](t))return!1;return!0}}function o(e){var t=s.call(arguments);return t.length-1>=e.length?e.apply(this,t.slice(1)):function(){var e=t.concat([].slice.call(arguments));return o.apply(this,e)}}function a(){}var s=[].slice;return{constant:e,negate:t,and:i,or:r,curry:o,compose:n,noop:a}}),r(U,[_,h,k],function(e,t,n){function r(e){return!m(e)&&(d(e)?!f(e.parentNode):p(e)||c(e)||h(e)||u(e))}function i(e,t){for(e=e.parentNode;e&&e!=t;e=e.parentNode){if(u(e))return!1;if(l(e))return!0}return!0}function o(e){return!!u(e)&&t.reduce(e.getElementsByTagName("*"),function(e,t){return e||l(t)},!1)!==!0}function a(e){return p(e)||o(e)}function s(e,t){return r(e)&&i(e,t)}var l=e.isContentEditableTrue,u=e.isContentEditableFalse,c=e.isBr,d=e.isText,f=e.matchNodeNames("script style textarea"),p=e.matchNodeNames("img input textarea
hr iframe video audio object"),h=e.matchNodeNames("table"),m=n.isCaretContainer;return{isCaretCandidate:r,isInEditable:i,isAtomic:a,isEditableCaretCandidate:s}}),r(W,[],function(){function e(e){return e?{left:c(e.left),top:c(e.top),bottom:c(e.bottom),right:c(e.right),width:c(e.width),height:c(e.height)}:{left:0,top:0,bottom:0,right:0,width:0,height:0}}function t(t,n){return t=e(t),n?t.right=t.left:(t.left=t.left+t.width,t.right=t.left),t.width=0,t}function n(e,t){return e.left===t.left&&e.top===t.top&&e.bottom===t.bottom&&e.right===t.right}function r(e,t,n){return e>=0&&e<=Math.min(t.height,n.height)/2}function i(e,t){return e.bottom<t.top||!(e.top>t.bottom)&&r(t.top-e.bottom,e,t)}function o(e,t){return e.top>t.bottom||!(e.bottom<t.top)&&r(t.bottom-e.top,e,t)}function a(e,t){return e.left<t.left}function s(e,t){return e.right>t.right}function l(e,t){return i(e,t)?-1:o(e,t)?1:a(e,t)?-1:s(e,t)?1:0}
function u(e,t,n){return t>=e.left&&t<=e.right&&n>=e.top&&n<=e.bottom}var c=Math.round;return{clone:e,collapse:t,isEqual:n,isAbove:i,isBelow:o,isLeft:a,isRight:s,compare:l,containsXY:u}}),r(V,[],function(){function e(e){return"string"==typeof e&&e.charCodeAt(0)>=768&&t.test(e)}var t=new RegExp("[\u0300-\u036f\u0483-\u0487\u0488-\u0489\u0591-\u05bd\u05bf\u05c1-\u05c2\u05c4-\u05c5\u05c7\u0610-\u061a\u064b-\u065f\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7-\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08e3-\u0902\u093a\u093c\u0941-\u0948\u094d\u0951-\u0957\u0962-\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2-\u09e3\u0a01-\u0a02\u0a3c\u0a41-\u0a42\u0a47-\u0a48\u0a4b-\u0a4d\u0a51\u0a70-\u0a71\u0a75\u0a81-\u0a82\u0abc\u0ac1-\u0ac5\u0ac7-\u0ac8\u0acd\u0ae2-\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62-\u0b63\u0b8
2\u0bbe\u0bc0\u0bcd\u0bd7\u0c00\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55-\u0c56\u0c62-\u0c63\u0c81\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc-\u0ccd\u0cd5-\u0cd6\u0ce2-\u0ce3\u0d01\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62-\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb-\u0ebc\u0ec8-\u0ecd\u0f18-\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039-\u103a\u103d-\u103e\u1058-\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085-\u1086\u108d\u109d\u135d-\u135f\u1712-\u1714\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17b4-\u17b5\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193b\u1a17-\u1a18\u1a1b\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1ab0-\u1abd\u1abe\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80-\u1b81\u1ba2-\u1ba5\u1ba8-\u1ba9\u1bab-\u1bad\u1be6\u1be8-\u1be9\u1bed\u1bef-\u1bf1\u1c2c-\u1c33\u1
c36-\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1cf4\u1cf8-\u1cf9\u1dc0-\u1df5\u1dfc-\u1dff\u200c-\u200d\u20d0-\u20dc\u20dd-\u20e0\u20e1\u20e2-\u20e4\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302d\u302e-\u302f\u3099-\u309a\ua66f\ua670-\ua672\ua674-\ua67d\ua69e-\ua69f\ua6f0-\ua6f1\ua802\ua806\ua80b\ua825-\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\ua9e5\uaa29-\uaa2e\uaa31-\uaa32\uaa35-\uaa36\uaa43\uaa4c\uaa7c\uaab0\uaab2-\uaab4\uaab7-\uaab8\uaabe-\uaabf\uaac1\uaaec-\uaaed\uaaf6\uabe5\uabe8\uabed\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\uff9e-\uff9f]");return{isExtendingChar:e}}),r($,[z,_,w,T,U,W,V],function(e,t,n,r,i,o,a){function s(e){return"createRange"in e?e.createRange():n.DOM.createRng()}function l(e){return e&&/[\r\n\t ]/.test(e)}function u(e){var t=e.startContainer,n=e.startOffset,r;return!!(l(e.toString())&&v(t.parentNode)&&(r=t.data,l(r[n-1])||l(r[n+1])))}function c(e){function t(
e){var t=e.ownerDocument,n=s(t),r=t.createTextNode("\xa0"),i=e.parentNode,a;return i.insertBefore(r,e),n.setStart(r,0),n.setEnd(r,1),a=o.clone(n.getBoundingClientRect()),i.removeChild(r),a}function n(e){var n,r;return r=e.getClientRects(),n=r.length>0?o.clone(r[0]):o.clone(e.getBoundingClientRect()),b(e)&&0===n.left?t(e):n}function r(e,t){return e=o.collapse(e,t),e.width=1,e.right=e.left+1,e}function i(e){0!==e.height&&(c.length>0&&o.isEqual(e,c[c.length-1])||c.push(e))}function l(e,t){var o=s(e.ownerDocument);if(t<e.data.length){if(a.isExtendingChar(e.data[t]))return c;if(a.isExtendingChar(e.data[t-1])&&(o.setStart(e,t),o.setEnd(e,t+1),!u(o)))return i(r(n(o),!1)),c}t>0&&(o.setStart(e,t-1),o.setEnd(e,t),u(o)||i(r(n(o),!1))),t<e.data.length&&(o.setStart(e,t),o.setEnd(e,t+1),u(o)||i(r(n(o),!0)))}var c=[],d,p;if(y(e.container()))return l(e.container(),e.offset()),c;if(f(e.container()))if(e.isAtEnd())p=x(e.containe
r(),e.offset()),y(p)&&l(p,p.data.length),g(p)&&!b(p)&&i(r(n(p),!1));else{if(p=x(e.container(),e.offset()),y(p)&&l(p,0),g(p)&&e.isAtEnd())return i(r(n(p),!1)),c;d=x(e.container(),e.offset()-1),g(d)&&!b(d)&&(h(d)||h(p)||!g(p))&&i(r(n(d),!1)),g(p)&&i(r(n(p),!0))}return c}function d(t,n,r){function i(){return y(t)?0===n:0===n}function o(){return y(t)?n>=t.data.length:n>=t.childNodes.length}function a(){var e;return e=s(t.ownerDocument),e.setStart(t,n),e.setEnd(t,n),e}function l(){return r||(r=c(new d(t,n))),r}function u(){return l().length>0}function f(e){return e&&t===e.container()&&n===e.offset()}function p(e){return x(t,e?n-1:n)}return{container:e.constant(t),offset:e.constant(n),toRange:a,getClientRects:l,isVisible:u,isAtStart:i,isAtEnd:o,isEqual:f,getNode:p}}var f=t.isElement,p=i.isCaretCandidate,h=t.matchStyleValues("display","block table"),m=t.matchStyleValues(&quo
t;float","left right"),g=e.and(f,p,e.negate(m)),v=e.negate(t.matchStyleValues("white-space","pre pre-line pre-wrap")),y=t.isText,b=t.isBr,C=n.nodeIndex,x=r.getNode;return d.fromRangeStart=function(e){return new d(e.startContainer,e.startOffset)},d.fromRangeEnd=function(e){return new d(e.endContainer,e.endOffset)},d.after=function(e){return new d(e.parentNode,C(e)+1)},d.before=function(e){return new d(e.parentNode,C(e))},d}),r(q,[_,w,z,h,$],function(e,t,n,r,i){function o(e){var t=e.parentNode;return v(t)?o(t):t}function a(e){return e?r.reduce(e.childNodes,function(e,t){return v(t)&&"BR"!=t.nodeName?e=e.concat(a(t)):e.push(t),e},[]):[]}function s(e,t){for(;(e=e.previousSibling)&&g(e);)t+=e.data.length;return t}function l(e){return function(t){return e===t}}function u(t){var n,i,s;return n=a(o(t)),i=r.findIndex(n,l(t),t),n=n.slice(0,i+1),s=r.reduce(n,function(e,t,r){return g(t)&&g(n[r-1])&&e++,e},0),n=r.filter
(n,e.matchNodeNames(t.nodeName)),i=r.findIndex(n,l(t),t),i-s}function c(e){var t;return t=g(e)?"text()":e.nodeName.toLowerCase(),t+"["+u(e)+"]"}function d(e,t,n){var r=[];for(t=t.parentNode;t!=e&&(!n||!n(t));t=t.parentNode)r.push(t);return r}function f(t,i){var o,a,l=[],u,f,p;return o=i.container(),a=i.offset(),g(o)?u=s(o,a):(f=o.childNodes,a>=f.length?(u="after",a=f.length-1):u="before",o=f[a]),l.push(c(o)),p=d(t,o),p=r.filter(p,n.negate(e.isBogus)),l=l.concat(r.map(p,function(e){return c(e)})),l.reverse().join("/")+","+u}function p(t,n,i){var o=a(t);return o=r.filter(o,function(e,t){return!g(e)||!g(o[t-1])}),o=r.filter(o,e.matchNodeNames(n)),o[i]}function h(e,t){for(var n=e,r=0,o;g(n);){if(o=n.data.length,t>=r&&t<=r+o){e=n,t-=r;break}if(!g(n.nextSibling)){e=n,t=o;break}r+=o,n=n.nextSibling}return t>e.data.length&&(t=e.data.length),new i(e,t)}function m(e,t){var n,o,a;return t?
(n=t.split(","),t=n[0].split("/"),a=n.length>1?n[1]:"before",o=r.reduce(t,function(e,t){return(t=/([\w\-\(\)]+)\[([0-9]+)\]/.exec(t))?("text()"===t[1]&&(t[1]="#text"),p(e,t[1],parseInt(t[2],10))):null},e),o?g(o)?h(o,parseInt(a,10)):(a="after"===a?y(o)+1:y(o),new i(o.parentNode,a)):null):null}var g=e.isText,v=e.isBogus,y=t.nodeIndex;return{create:f,resolve:m}}),r(j,[d,m,k,q,$,_,T],function(e,t,n,r,i,o,a){function s(s){var u=s.dom;this.getBookmark=function(e,c){function d(e,n){var r=0;return t.each(u.select(e),function(e){if("all"!==e.getAttribute("data-mce-bogus"))return e!=n&&void r++}),r}function f(e){function t(t){var n,r,i,o=t?"start":"end";n=e[o+"Container"],r=e[o+"Offset"],1==n.nodeType&&"TR"==n.nodeName&&(i=n.childNodes,n=i[Math.min(t?r:r-1,i.length-1)],n&&(r=t?0:n.childNodes.length,e["set"+(t?&qu
ot;Start":"End")](n,r)))}return t(!0),t(),e}function p(e){function t(e,t){var r=e[t?"startContainer":"endContainer"],i=e[t?"startOffset":"endOffset"],o=[],a,s,l=0;if(3==r.nodeType){if(c)for(a=r.previousSibling;a&&3==a.nodeType;a=a.previousSibling)i+=a.nodeValue.length;o.push(i)}else s=r.childNodes,i>=s.length&&s.length&&(l=1,i=Math.max(0,s.length-1)),o.push(u.nodeIndex(s[i],c)+l);for(;r&&r!=n;r=r.parentNode)o.push(u.nodeIndex(r,c));return o}var n=u.getRoot(),r={};return r.start=t(e,!0),s.isCollapsed()||(r.end=t(e)),r}function h(e){function t(e,t){var r;if(o.isElement(e)&&(e=a.getNode(e,t),l(e)))return e;if(n.isCaretContainer(e)){if(o.isText(e)&&n.isCaretContainerBlock(e)&&(e=e.parentNode),r=e.previousSibling,l(r))return r;if(r=e.nextSibling,l(r))return r}}return t(e.startContainer,e.startOffset)||t(e.endContainer,e.endOffset)}var m,g,v,y,b,C,x="",w;
if(2==e)return C=s.getNode(),b=C?C.nodeName:null,m=s.getRng(),l(C)||"IMG"==b?{name:b,index:d(b,C)}:s.tridentSel?s.tridentSel.getBookmark(e):(C=h(m),C?(b=C.tagName,{name:b,index:d(b,C)}):p(m));if(3==e)return m=s.getRng(),{start:r.create(u.getRoot(),i.fromRangeStart(m)),end:r.create(u.getRoot(),i.fromRangeEnd(m))};if(e)return{rng:s.getRng()};if(m=s.getRng(),v=u.uniqueId(),y=s.isCollapsed(),w="overflow:hidden;line-height:0px",m.duplicate||m.item){if(m.item)return C=m.item(0),b=C.nodeName,{name:b,index:d(b,C)};g=m.duplicate();try{m.collapse(),m.pasteHTML('<span data-mce-type="bookmark" id="'+v+'_start" style="'+w+'">'+x+"</span>"),y||(g.collapse(!1),m.moveToElementText(g.parentElement()),0===m.compareEndPoints("StartToEnd",g)&&g.move("character",-1),g.pasteHTML('<span data-mce-type="bookmark" id="'+v+'_end" style="'+w+'">'+x+"</span>"))}
catch(E){return null}}else{if(C=s.getNode(),b=C.nodeName,"IMG"==b)return{name:b,index:d(b,C)};g=f(m.cloneRange()),y||(g.collapse(!1),g.insertNode(u.create("span",{"data-mce-type":"bookmark",id:v+"_end",style:w},x))),m=f(m),m.collapse(!0),m.insertNode(u.create("span",{"data-mce-type":"bookmark",id:v+"_start",style:w},x))}return s.moveToBookmark({id:v,keep:1}),{id:v}},this.moveToBookmark=function(n){function i(e){var t=n[e?"start":"end"],r,i,o,a;if(t){for(o=t[0],i=d,r=t.length-1;r>=1;r--){if(a=i.childNodes,t[r]>a.length-1)return;i=a[t[r]]}3===i.nodeType&&(o=Math.min(t[0],i.nodeValue.length)),1===i.nodeType&&(o=Math.min(t[0],i.childNodes.length)),e?c.setStart(i,o):c.setEnd(i,o)}return!0}function o(r){var i=u.get(n.id+"_"+r),o,a,s,l,c=n.keep;if(i&&(o=i.parentNode,"start"==r?(c?(o=i.firstChild,a=1):a=u.nodeIndex(i),f=p=o,h=m=a):(c
?(o=i.firstChild,a=1):a=u.nodeIndex(i),p=o,m=a),!c)){for(l=i.previousSibling,s=i.nextSibling,t.each(t.grep(i.childNodes),function(e){3==e.nodeType&&(e.nodeValue=e.nodeValue.replace(/\uFEFF/g,""))});i=u.get(n.id+"_"+r);)u.remove(i,1);l&&s&&l.nodeType==s.nodeType&&3==l.nodeType&&!e.opera&&(a=l.nodeValue.length,l.appendData(s.nodeValue),u.remove(s),"start"==r?(f=p=l,h=m=a):(p=l,m=a))}}function a(t){return!u.isBlock(t)||t.innerHTML||e.ie||(t.innerHTML='<br data-mce-bogus="1" />'),t}function l(){var e,t;return e=u.createRng(),t=r.resolve(u.getRoot(),n.start),e.setStart(t.container(),t.offset()),t=r.resolve(u.getRoot(),n.end),e.setEnd(t.container(),t.offset()),e}var c,d,f,p,h,m;if(n)if(t.isArray(n.start)){if(c=u.createRng(),d=u.getRoot(),s.tridentSel)return s.tridentSel.moveToBookmark(n);i(!0)&&i()&&s.setRng(c)}else"string"==typeof n.start?s.setRng(l(n)):n.id?(o("st
art"),o("end"),f&&(c=u.createRng(),c.setStart(a(f),h),c.setEnd(a(p),m),s.setRng(c))):n.name?s.select(u.select(n.name)[n.index]):n.rng&&s.setRng(n.rng)}}var l=o.isContentEditableFalse;return s.isBookmarkNode=function(e){return e&&"SPAN"===e.tagName&&"bookmark"===e.getAttribute("data-mce-type")},s}),r(Y,[y,H,F,T,j,_,d,m,$],function(e,n,r,i,o,a,s,l,u){function c(e,t,i,a){var s=this;s.dom=e,s.win=t,s.serializer=i,s.editor=a,s.bookmarkManager=new o(s),s.controlSelection=new r(s,a),s.win.getSelection||(s.tridentSel=new n(s))}var d=l.each,f=l.trim,p=s.ie;return c.prototype={setCursorLocation:function(e,t){var n=this,r=n.dom.createRng();e?(r.setStart(e,t),r.setEnd(e,t),n.setRng(r),n.collapse(!1)):(n._moveEndPoint(r,n.editor.getBody(),!0),n.setRng(r))},getContent:function(e){var n=this,r=n.getRng(),i=n.dom.create("body"),o=n.getSel(),a,s,l;return e=e||{},a=s="",e.get=!0,e.format=e.format||"h
tml",e.selection=!0,n.editor.fire("BeforeGetContent",e),"text"==e.format?n.isCollapsed()?"":r.text||(o.toString?o.toString():""):(r.cloneContents?(l=r.cloneContents(),l&&i.appendChild(l)):r.item!==t||r.htmlText!==t?(i.innerHTML="<br>"+(r.item?r.item(0).outerHTML:r.htmlText),i.removeChild(i.firstChild)):i.innerHTML=r.toString(),/^\s/.test(i.innerHTML)&&(a=" "),/\s+$/.test(i.innerHTML)&&(s=" "),e.getInner=!0,e.content=n.isCollapsed()?"":a+n.serializer.serialize(i,e)+s,n.editor.fire("GetContent",e),e.content)},setContent:function(e,t){var n=this,r=n.getRng(),i,o=n.win.document,a,s;if(t=t||{format:"html"},t.set=!0,t.selection=!0,t.content=e,t.no_events||n.editor.fire("BeforeSetContent",t),e=t.content,r.insertNode){e+='<span id="__caret">_</span>',r.startContainer==o&&r.endContainer==o?o.body.innerHTML=e:(r.deleteCo
ntents(),0===o.body.childNodes.length?o.body.innerHTML=e:r.createContextualFragment?r.insertNode(r.createContextualFragment(e)):(a=o.createDocumentFragment(),s=o.createElement("div"),a.appendChild(s),s.outerHTML=e,r.insertNode(a))),i=n.dom.get("__caret"),r=o.createRange(),r.setStartBefore(i),r.setEndBefore(i),n.setRng(r),n.dom.remove("__caret");try{n.setRng(r)}catch(l){}}else r.item&&(o.execCommand("Delete",!1,null),r=n.getRng()),/^\s+/.test(e)?(r.pasteHTML('<span id="__mce_tmp">_</span>'+e),n.dom.remove("__mce_tmp")):r.pasteHTML(e);t.no_events||n.editor.fire("SetContent",t)},getStart:function(e){var t=this,n=t.getRng(),r,i,o,a;if(n.duplicate||n.item){if(n.item)return n.item(0);for(o=n.duplicate(),o.collapse(1),r=o.parentElement(),r.ownerDocument!==t.dom.doc&&(r=t.dom.getRoot()),i=a=n.parentElement();a=a.parentNode;)if(a==r){r=i;break}return r}return r=n.startContainer,1==r.nodeType&
;&r.hasChildNodes()&&(e&&n.collapsed||(r=r.childNodes[Math.min(r.childNodes.length-1,n.startOffset)])),r&&3==r.nodeType?r.parentNode:r},getEnd:function(e){var t=this,n=t.getRng(),r,i;return n.duplicate||n.item?n.item?n.item(0):(n=n.duplicate(),n.collapse(0),r=n.parentElement(),r.ownerDocument!==t.dom.doc&&(r=t.dom.getRoot()),r&&"BODY"==r.nodeName?r.lastChild||r:r):(r=n.endContainer,i=n.endOffset,1==r.nodeType&&r.hasChildNodes()&&(e&&n.collapsed||(r=r.childNodes[i>0?i-1:i])),r&&3==r.nodeType?r.parentNode:r)},getBookmark:function(e,t){return this.bookmarkManager.getBookmark(e,t)},moveToBookmark:function(e){return this.bookmarkManager.moveToBookmark(e)},select:function(e,t){var n=this,r=n.dom,i=r.createRng(),o;if(n.lastFocusBookmark=null,e){if(!t&&n.controlSelection.controlSelect(e))return;o=r.nodeIndex(e),i.setStart(e.parentNode,o),i.setEnd(e.parentNode,o+1),t&&(n._moveEndPoint(i,e
,!0),n._moveEndPoint(i,e)),n.setRng(i)}return e},isCollapsed:function(){var e=this,t=e.getRng(),n=e.getSel();return!(!t||t.item)&&(t.compareEndPoints?0===t.compareEndPoints("StartToEnd",t):!n||t.collapsed)},collapse:function(e){var t=this,n=t.getRng(),r;n.item&&(r=n.item(0),n=t.win.document.body.createTextRange(),n.moveToElementText(r)),n.collapse(!!e),t.setRng(n)},getSel:function(){var e=this.win;return e.getSelection?e.getSelection():e.document.selection},getRng:function(e){function t(e,t,n){try{return t.compareBoundaryPoints(e,n)}catch(r){return-1}}var n=this,r,i,o,a,s,l;if(!n.win)return null;if(a=n.win.document,"undefined"==typeof a||null===a)return null;if(!e&&n.lastFocusBookmark){var u=n.lastFocusBookmark;return u.startContainer?(i=a.createRange(),i.setStart(u.startContainer,u.startOffset),i.setEnd(u.endContainer,u.endOffset)):i=u,i}if(e&&n.tridentSel)return n.tridentSel.getRangeAt(0);try{(r=n.getSel())&&(i=r.rangeCou
nt>0?r.getRangeAt(0):r.createRange?r.createRange():a.createRange())}catch(c){}if(l=n.editor.fire("GetSelectionRange",{range:i}),l.range!==i)return l.range;if(p&&i&&i.setStart&&a.selection){try{s=a.selection.createRange()}catch(c){}s&&s.item&&(o=s.item(0),i=a.createRange(),i.setStartBefore(o),i.setEndAfter(o))}return i||(i=a.createRange?a.createRange():a.body.createTextRange()),i.setStart&&9===i.startContainer.nodeType&&i.collapsed&&(o=n.dom.getRoot(),i.setStart(o,0),i.setEnd(o,0)),n.selectedRange&&n.explicitRange&&(0===t(i.START_TO_START,i,n.selectedRange)&&0===t(i.END_TO_END,i,n.selectedRange)?i=n.explicitRange:(n.selectedRange=null,n.explicitRange=null)),i},setRng:function(e,t){var n=this,r,i,o;if(e)if(e.select){n.explicitRange=null;try{e.select()}catch(a){}}else if(n.tridentSel){if(e.cloneRange)try{n.tridentSel.addRange(e)}catch(a){}}else{if(r=n.getSel(),o=n.editor.fire("SetS
electionRange",{range:e}),e=o.range,r){n.explicitRange=e;try{r.removeAllRanges(),r.addRange(e)}catch(a){}t===!1&&r.extend&&(r.collapse(e.endContainer,e.endOffset),r.extend(e.startContainer,e.startOffset)),n.selectedRange=r.rangeCount>0?r.getRangeAt(0):null}e.collapsed||e.startContainer!=e.endContainer||!r.setBaseAndExtent||s.ie||e.endOffset-e.startOffset<2&&e.startContainer.hasChildNodes()&&(i=e.startContainer.childNodes[e.startOffset],i&&"IMG"==i.tagName&&(r.setBaseAndExtent(e.startContainer,e.startOffset,e.endContainer,e.endOffset),r.anchorNode===e.startContainer&&r.focusNode===e.endContainer||r.setBaseAndExtent(i,0,i,1))),n.editor.fire("AfterSetSelectionRange",{range:e})}},setNode:function(e){var t=this;return t.setContent(t.dom.getOuterHTML(e)),e},getNode:function(){function e(e,t){for(var n=e;e&&3===e.nodeType&&0===e.length;)e=t?e.nextSibling:e.previousSibling;return e||n}var
t=this,n=t.getRng(),r,i,o,a,s,l=t.dom.getRoot();return n?(i=n.startContainer,o=n.endContainer,a=n.startOffset,s=n.endOffset,n.setStart?(r=n.commonAncestorContainer,!n.collapsed&&(i==o&&s-a<2&&i.hasChildNodes()&&(r=i.childNodes[a]),3===i.nodeType&&3===o.nodeType&&(i=i.length===a?e(i.nextSibling,!0):i.parentNode,o=0===s?e(o.previousSibling,!1):o.parentNode,i&&i===o))?i:r&&3==r.nodeType?r.parentNode:r):(r=n.item?n.item(0):n.parentElement(),r.ownerDocument!==t.win.document&&(r=l),r)):l},getSelectedBlocks:function(t,n){var r=this,i=r.dom,o,a,s=[];if(a=i.getRoot(),t=i.getParent(t||r.getStart(),i.isBlock),n=i.getParent(n||r.getEnd(),i.isBlock),t&&t!=a&&s.push(t),t&&n&&t!=n){o=t;for(var l=new e(t,a);(o=l.next())&&o!=n;)i.isBlock(o)&&s.push(o)}return n&&t!=n&&n!=a&&s.push(n),s},isForward:function(){var e=this.dom,t=this.getSel(),n,r;return!(t&
&t.anchorNode&&t.focusNode)||(n=e.createRng(),n.setStart(t.anchorNode,t.anchorOffset),n.collapse(!0),r=e.createRng(),r.setStart(t.focusNode,t.focusOffset),r.collapse(!0),n.compareBoundaryPoints(n.START_TO_START,r)<=0)},normalize:function(){var e=this,t=e.getRng();return s.range&&new i(e.dom).normalize(t)&&e.setRng(t,e.isForward()),t},selectorChanged:function(e,t){var n=this,r;return n.selectorChangedData||(n.selectorChangedData={},r={},n.editor.on("NodeChange",function(e){var t=e.element,i=n.dom,o=i.getParents(t,null,i.getRoot()),a={};d(n.selectorChangedData,function(e,t){d(o,function(n){if(i.is(n,t))return r[t]||(d(e,function(e){e(!0,{node:n,selector:t,parents:o})}),r[t]=e),a[t]=e,!1})}),d(r,function(e,n){a[n]||(delete r[n],d(e,function(e){e(!1,{node:t,selector:n,parents:o})}))})})),n.selectorChangedData[e]||(n.selectorChangedData[e]=[]),n.selectorChangedData[e].push(t),n},getScrollContainer:function(){for(var e,t=this.dom.getRoot();t&&a
mp;"BODY"!=t.nodeName;){if(t.scrollHeight>t.clientHeight){e=t;break}t=t.parentNode}return e},scrollIntoView:function(e,t){function n(e){for(var t=0,n=0,r=e;r&&r.nodeType;)t+=r.offsetLeft||0,n+=r.offsetTop||0,r=r.offsetParent;return{x:t,y:n}}var r,i,o=this,s=o.dom,l=s.getRoot(),u,c,d=0;if(a.isElement(e)){if(t===!1&&(d=e.offsetHeight),"BODY"!=l.nodeName){var f=o.getScrollContainer();if(f)return r=n(e).y-n(f).y+d,c=f.clientHeight,u=f.scrollTop,void((r<u||r+25>u+c)&&(f.scrollTop=r<u?r:r-c+25))}i=s.getViewPort(o.editor.getWin()),r=s.getPos(e).y+d,u=i.y,c=i.h,(r<i.y||r+25>u+c)&&o.editor.getWin().scrollTo(0,r<u?r:r-c+25)}},placeCaretAt:function(e,t){this.setRng(i.getCaretRangeFromPoint(e,t,this.editor.getDoc()))},_moveEndPoint:function(t,n,r){var i=n,o=new e(n,i),a=this.dom.schema.getNonEmptyElements();do{if(3==n.nodeType&&0!==f(n.nodeValue).length)return void(r?t.setStart(n,0):t.setEnd(n,n.nodeValue.length));
if(a[n.nodeName]&&!/^(TD|TH)$/.test(n.nodeName))return void(r?t.setStartBefore(n):"BR"==n.nodeName?t.setEndBefore(n):t.setEndAfter(n));if(s.ie&&s.ie<11&&this.dom.isBlock(n)&&this.dom.isEmpty(n))return void(r?t.setStart(n,0):t.setEnd(n,0))}while(n=r?o.next():o.prev());"BODY"==i.nodeName&&(r?t.setStart(i,0):t.setEnd(i,i.childNodes.length))},getBoundingClientRect:function(){var e=this.getRng();return e.collapsed?u.fromRangeStart(e).getClientRects()[0]:e.getBoundingClientRect()},destroy:function(){this.win=null,this.controlSelection.destroy()}},c}),r(X,[j,m],function(e,t){function n(t){this.compare=function(n,i){function o(e){var n={};return r(t.getAttribs(e),function(r){var i=r.nodeName.toLowerCase();0!==i.indexOf("_")&&"style"!==i&&0!==i.indexOf("data-")&&(n[i]=t.getAttrib(e,i))}),n}function a(e,t){var n,r;for(r in e)if(e.hasOwnProperty(r)){if(n=t[r],"undefined&quo
t;==typeof n)return!1;if(e[r]!=n)return!1;delete t[r]}for(r in t)if(t.hasOwnProperty(r))return!1;return!0}return n.nodeName==i.nodeName&&(!!a(o(n),o(i))&&(!!a(t.parseStyle(t.getAttrib(n,"style")),t.parseStyle(t.getAttrib(i,"style")))&&(!e.isBookmarkNode(n)&&!e.isBookmarkNode(i))))}}var r=t.each;return n}),r(K,[w,m,B],function(e,t,n){function r(e,r){function i(e,t){t.classes.length&&u.addClass(e,t.classes.join(" ")),u.setAttribs(e,t.attrs)}function o(e){var t;return c="string"==typeof e?{name:e,classes:[],attrs:{}}:e,t=u.create(c.name),i(t,c),t}function a(e,n){var r="string"!=typeof e?e.nodeName.toLowerCase():e,i=f.getElementRule(r),o=i.parentsRequired;return!(!o||!o.length)&&(n&&t.inArray(o,n)!==-1?n:o[0])}function s(e,n,r){var i,l,c,d=n.length&&n[0],f=d&&d.name;if(c=a(e,f))f==c?(l=n[0],n=n.slice(1)):l=c;else if(d)l=n[0],n=n.slice(1);else if(!r)return e;return l&
amp;&(i=o(l),i.appendChild(e)),r&&(i||(i=u.create("div"),i.appendChild(e)),t.each(r,function(t){var n=o(t);i.insertBefore(n,e)})),s(i,n,l&&l.siblings)}var l,c,d,f=r&&r.schema||new n({});return e&&e.length?(c=e[0],l=o(c),d=u.create("div"),d.appendChild(s(l,e.slice(1),c.siblings)),d):""}function i(e,t){return r(a(e),t)}function o(e){var n,r={classes:[],attrs:{}};return e=r.selector=t.trim(e),"*"!==e&&(n=e.replace(/(?:([#\.]|::?)([\w\-]+)|(\[)([^\]]+)\]?)/g,function(e,n,i,o,a){switch(n){case"#":r.attrs.id=i;break;case".":r.classes.push(i);break;case":":t.inArray("checked disabled enabled read-only required".split(" "),i)!==-1&&(r.attrs[i]=i)}if("["==o){var s=a.match(/([\w\-]+)(?:\=\"([^\"]+))?/);s&&(r.attrs[s[1]]=s[2])}return""})),r.name=n||"div",r}function a(e){return e&&"string"=
=typeof e?(e=e.split(/\s*,\s*/)[0],e=e.replace(/\s*(~\+|~|\+|>)\s*/g,"$1"),t.map(e.split(/(?:>|\s+(?![^\[\]]+\]))/),function(e){var n=t.map(e.split(/(?:~\+|~|\+)/),o),r=n.pop();return n.length&&(r.siblings=n),r}).reverse()):[]}function s(e,t){function n(e){return e.replace(/%(\w+)/g,"")}var i,o,s,c,d="",f,p;if(p=e.settings.preview_styles,p===!1)return"";if("string"!=typeof p&&(p="font-family font-size font-weight font-style text-decoration text-transform color background-color border border-radius outline text-shadow"),"string"==typeof t){if(t=e.formatter.get(t),!t)return;t=t[0]}return"preview"in t&&(p=t.preview,p===!1)?"":(i=t.block||t.inline||"span",c=a(t.selector),c.length?(c[0].name||(c[0].name=i),i=t.selector,o=r(c,e)):o=r([i],e),s=u.select(i,o)[0]||o.firstChild,l(t.styles,function(e,t){e=n(e),e&&u.setStyle(s,t,e)}),l(t.attributes,function(e,
t){e=n(e),e&&u.setAttrib(s,t,e)}),l(t.classes,function(e){e=n(e),u.hasClass(s,e)||u.addClass(s,e)}),e.fire("PreviewFormats"),u.setStyles(o,{position:"absolute",left:-65535}),e.getBody().appendChild(o),f=u.getStyle(e.getBody(),"fontSize",!0),f=/px$/.test(f)?parseInt(f,10):0,l(p.split(" "),function(t){var n=u.getStyle(s,t,!0);if(!("background-color"==t&&/transparent|rgba\s*\([^)]+,\s*0\)/.test(n)&&(n=u.getStyle(e.getBody(),t,!0),"#ffffff"==u.toHex(n).toLowerCase())||"color"==t&&"#000000"==u.toHex(n).toLowerCase())){if("font-size"==t&&/em|%$/.test(n)){if(0===f)return;n=parseFloat(n,10)/(/%$/.test(n)?100:1),n=n*f+"px"}"border"==t&&n&&(d+="padding:0 2px;"),d+=t+":"+n+";"}}),e.fire("AfterPreviewFormats"),u.remove(o),d)}var l=t.each,u=e.DOM;return{getCssText:s,parseSelector:a,selectorToH
tml:i}}),r(G,[h,_,g],function(e,t,n){function r(e,t){var n=o[e];n||(o[e]=n=[]),o[e].push(t)}function i(e,t){s(o[e],function(e){e(t)})}var o={},a=e.filter,s=e.each;return r("pre",function(r){function i(t){return u(t.previousSibling)&&e.indexOf(c,t.previousSibling)!=-1}function o(e,t){n(t).remove(),n(e).append("<br><br>").append(t.childNodes)}var l=r.selection.getRng(),u,c;u=t.matchNodeNames("pre"),l.collapsed||(c=r.selection.getSelectedBlocks(),s(a(a(c,u),i),function(e){o(e.previousSibling,e)}))}),{postProcess:i}}),r(J,[y,T,j,X,z,m,K,G],function(e,t,n,r,i,o,a,s){return function(l){function u(e){return e.nodeType&&(e=e.nodeName),!!l.schema.getTextBlockElements()[e.toLowerCase()]}function c(e){return/^(TH|TD)$/.test(e.nodeName)}function d(e){return e&&/^(IMG)$/.test(e.nodeName)}function f(e,t){return Q.getParents(e,t,Q.getRoot())}function p(e){return 1===e.nodeType&&"_mce_caret"===e.id}function h(){v({v
aligntop:[{selector:"td,th",styles:{verticalAlign:"top"}}],valignmiddle:[{selector:"td,th",styles:{verticalAlign:"middle"}}],valignbottom:[{selector:"td,th",styles:{verticalAlign:"bottom"}}],alignleft:[{selector:"figure.image",collapsed:!1,classes:"align-left",ceFalseOverride:!0,preview:"font-family font-size"},{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"left"},inherit:!1,preview:!1,defaultBlock:"div"},{selector:"img,table",collapsed:!1,styles:{"float":"left"},preview:"font-family font-size"}],aligncenter:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"center"},inherit:!1,preview:!1,defaultBlock:"div"},{selector:"figure.image",collapsed:!1,classes:"align-center",ceFalseOverride:!0,preview:"font-family fo
nt-size"},{selector:"img",collapsed:!1,styles:{display:"block",marginLeft:"auto",marginRight:"auto"},preview:!1},{selector:"table",collapsed:!1,styles:{marginLeft:"auto",marginRight:"auto"},preview:"font-family font-size"}],alignright:[{selector:"figure.image",collapsed:!1,classes:"align-right",ceFalseOverride:!0,preview:"font-family font-size"},{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"right"},inherit:!1,preview:"font-family font-size",defaultBlock:"div"},{selector:"img,table",collapsed:!1,styles:{"float":"right"},preview:"font-family font-size"}],alignjustify:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"justify"},inherit:!1,defaultBlock:"div",preview:"font-family font-size"}],b
old:[{inline:"strong",remove:"all"},{inline:"span",styles:{fontWeight:"bold"}},{inline:"b",remove:"all"}],italic:[{inline:"em",remove:"all"},{inline:"span",styles:{fontStyle:"italic"}},{inline:"i",remove:"all"}],underline:[{inline:"span",styles:{textDecoration:"underline"},exact:!0},{inline:"u",remove:"all"}],strikethrough:[{inline:"span",styles:{textDecoration:"line-through"},exact:!0},{inline:"strike",remove:"all"}],forecolor:{inline:"span",styles:{color:"%value"},links:!0,remove_similar:!0},hilitecolor:{inline:"span",styles:{backgroundColor:"%value"},links:!0,remove_similar:!0},fontname:{inline:"span",styles:{fontFamily:"%value"}},fontsize:{inline:"span",styles:{fontSize:"%value"}},fontsize_class:{inline:
"span",attributes:{"class":"%value"}},blockquote:{block:"blockquote",wrapper:1,remove:"all"},subscript:{inline:"sub"},superscript:{inline:"sup"},code:{inline:"code"},link:{inline:"a",selector:"a",remove:"all",split:!0,deep:!0,onmatch:function(){return!0},onformat:function(e,t,n){me(n,function(t,n){Q.setAttrib(e,n,t)})}},removeformat:[{selector:"b,strong,em,i,font,u,strike,sub,sup,dfn,code,samp,kbd,var,cite,mark,q,del,ins",remove:"all",split:!0,expand:!1,block_expand:!0,deep:!0},{selector:"span",attributes:["style","class"],remove:"empty",split:!0,expand:!1,
-deep:!0},{selector:"*",attributes:["style","class"],split:!1,expand:!1,deep:!0}]}),me("p h1 h2 h3 h4 h5 h6 div address pre div dt dd samp".split(/\s/),function(e){v(e,{block:e,remove:"all"})}),v(l.settings.formats)}function m(){l.addShortcut("meta+b","bold_desc","Bold"),l.addShortcut("meta+i","italic_desc","Italic"),l.addShortcut("meta+u","underline_desc","Underline");for(var e=1;e<=6;e++)l.addShortcut("access+"+e,"",["FormatBlock",!1,"h"+e]);l.addShortcut("access+7","",["FormatBlock",!1,"p"]),l.addShortcut("access+8","",["FormatBlock",!1,"div"]),l.addShortcut("access+9","",["FormatBlock",!1,"address"])}function g(e){return e?J[e]:J}function v(e,t){e&&("string"!=typeo
f e?me(e,function(e,t){v(t,e)}):(t=t.length?t:[t],me(t,function(e){e.deep===ce&&(e.deep=!e.selector),e.split===ce&&(e.split=!e.selector||e.inline),e.remove===ce&&e.selector&&!e.inline&&(e.remove="none"),e.selector&&e.inline&&(e.mixed=!0,e.block_expand=!0),"string"==typeof e.classes&&(e.classes=e.classes.split(/\s+/))}),J[e]=t))}function y(e){return e&&J[e]&&delete J[e],J}function b(e,t){var n=g(t);if(n)for(var r=0;r<n.length;r++)if(n[r].inherit===!1&&Q.is(e,n[r].selector))return!0;return!1}function C(e){var t;return l.dom.getParent(e,function(e){return t=l.dom.getStyle(e,"text-decoration"),t&&"none"!==t}),t}function x(e){var t;1===e.nodeType&&e.parentNode&&1===e.parentNode.nodeType&&(t=C(e.parentNode),l.dom.getStyle(e,"color")&&t?l.dom.setStyle(e,"text-decoration",t):l.dom.getStyle(e,"text-
decoration")===t&&l.dom.setStyle(e,"text-decoration",null))}function w(t,n,r){function i(e,t){if(t=t||f,e){if(t.onformat&&t.onformat(e,t,n,r),me(t.styles,function(t,r){Q.setStyle(e,r,F(t,n))}),t.styles){var i=Q.getAttrib(e,"style");i&&e.setAttribute("data-mce-style",i)}me(t.attributes,function(t,r){Q.setAttrib(e,r,F(t,n))}),me(t.classes,function(t){t=F(t,n),Q.hasClass(e,t)||Q.addClass(e,t)})}}function o(e,t){var n=!1;return!!f.selector&&(me(e,function(e){if(!("collapsed"in e&&e.collapsed!==v))return Q.is(t,e.selector)&&!p(t)?(i(t,e),n=!0,!1):void 0}),n)}function a(){function t(t,n){var i=new e(n);for(r=i.prev2();r;r=i.prev2()){if(3==r.nodeType&&r.data.length>0)return r;if(r.childNodes.length>1||r==t||"BR"==r.tagName)return r}}var n=l.selection.getRng(),i=n.startContainer,o=n.endContainer;if(i!=o&&0===n.endOffset){var a=t(i,o),s=3==a.nodeType?a.data.length:a.ch
ildNodes.length;n.setEnd(a,s)}return n}function c(e,r,a){var s=[],l,c,h=!0;l=f.inline||f.block,c=Q.create(l),i(c),ee.walk(e,function(e){function r(e){var g,v,y,b;if(b=h,g=e.nodeName.toLowerCase(),v=e.parentNode.nodeName.toLowerCase(),1===e.nodeType&&de(e)&&(b=h,h="true"===de(e),y=!0),D(g,"br"))return m=0,void(f.block&&Q.remove(e));if(f.wrapper&&_(e,t,n))return void(m=0);if(h&&!y&&f.block&&!f.wrapper&&u(g)&&te(v,l))return e=Q.rename(e,l),i(e),s.push(e),void(m=0);if(f.selector){var C=o(d,e);if(!f.inline||C)return void(m=0)}!h||y||!te(l,g)||!te(v,l)||!a&&3===e.nodeType&&1===e.nodeValue.length&&65279===e.nodeValue.charCodeAt(0)||p(e)||f.inline&&ne(e)?(m=0,me(ge(e.childNodes),r),y&&(h=b),m=0):(m||(m=Q.clone(c,se),e.parentNode.insertBefore(m,e),s.push(m)),m.appendChild(e))}var m;me(e,r)}),f.links===!0&&me(s,function(e){function t(e){"A"===e.
nodeName&&i(e,f),me(ge(e.childNodes),t)}t(e)}),me(s,function(e){function r(e){var t=0;return me(e.childNodes,function(e){z(e)||he(e)||t++}),t}function o(e){var t=!1;return me(e.childNodes,function(e){if(M(e))return t=e,!1}),t}function a(e,t){do{if(1!==r(e))break;if(e=o(e),!e)break;if(t(e))return e}while(e);return null}function l(e){var t,n;return t=o(e),t&&!he(t)&&B(t,f)&&(n=Q.clone(t,se),i(n),Q.replace(n,e,le),Q.remove(t,1)),n||e}var u;if(u=r(e),(s.length>1||!ne(e))&&0===u)return void Q.remove(e,1);if(f.inline||f.wrapper){if(f.exact||1!==u||(e=l(e)),me(d,function(t){me(Q.select(t.inline,e),function(e){he(e)||$(t,n,e,t.exact?e:null)})}),_(e.parentNode,t,n)&&$(f,n,e)&&(e=0),f.merge_with_parents&&Q.getParent(e.parentNode,function(r){if(_(r,t,n))return $(f,n,e)&&(e=0),le}),!ne(e)&&!H(e,"fontSize")){var c=a(e,P("fontSize"));c&&w("fontsize",{value:H(c,"fontSize&qu
ot;)},e)}e&&f.merge_siblings!==!1&&(e=Y(j(e),e),e=Y(e,j(e,le)))}})}var d=g(t),f=d[0],h,m,v=!r&&Z.isCollapsed();if("false"!==de(Z.getNode())){if(f){if(r)r.nodeType?o(d,r)||(m=Q.createRng(),m.setStartBefore(r),m.setEndAfter(r),c(W(m,d),null,!0)):c(r,null,!0);else if(v&&f.inline&&!Q.select("td[data-mce-selected],th[data-mce-selected]").length)K("apply",t,n);else{var y=l.selection.getNode();re||!d[0].defaultBlock||Q.getParent(y,Q.isBlock)||w(d[0].defaultBlock),l.selection.setRng(a()),h=Z.getBookmark(),c(W(Z.getRng(le),d),h),f.styles&&((f.styles.color||f.styles.textDecoration)&&(ve(y,x,"childNodes"),x(y)),f.styles.backgroundColor&&L(y,P("fontSize"),O("backgroundColor",F(f.styles.backgroundColor,n)))),Z.moveToBookmark(h),G(Z.getRng(le)),l.nodeChanged()}s.postProcess(t,l)}}else{r=Z.getNode();for(var b=0,C=d.length;b<C;b++)if(d[b].ceFalseOverride&&Q.is(r,d[b
].selector))return void i(r,d[b])}}function E(e,t,n,r){function i(e){var n,r,o,a,s;if(1===e.nodeType&&de(e)&&(a=y,y="true"===de(e),s=!0),n=ge(e.childNodes),y&&!s)for(r=0,o=p.length;r<o&&!$(p[r],t,e,e);r++);if(h.deep&&n.length){for(r=0,o=n.length;r<o;r++)i(n[r]);s&&(y=a)}}function o(n){var i;return me(f(n.parentNode).reverse(),function(n){var o;i||"_start"==n.id||"_end"==n.id||(o=_(n,e,t,r),o&&o.split!==!1&&(i=n))}),i}function a(e,n,r,i){var o,a,s,l,u,c;if(e){for(c=e.parentNode,o=n.parentNode;o&&o!=c;o=o.parentNode){for(a=Q.clone(o,se),u=0;u<p.length;u++)if($(p[u],t,a,a)){a=0;break}a&&(s&&a.appendChild(s),l||(l=a),s=a)}!i||h.mixed&&ne(e)||(n=Q.split(e,n)),s&&(r.parentNode.insertBefore(s,r),l.appendChild(r))}return n}function s(e){return a(o(e),e,e,!0)}function u(e){var t=Q.get(e?"_start":"_end"),n=t[e?"firstChild"
:"lastChild"];return he(n)&&(n=n[e?"firstChild":"lastChild"]),3==n.nodeType&&0===n.data.length&&(n=e?t.previousSibling||t.nextSibling:t.nextSibling||t.previousSibling),Q.remove(t,!0),n}function d(e){var t,n,r=e.commonAncestorContainer;if(e=W(e,p,le),h.split){if(t=X(e,le),n=X(e),t!=n){if(/^(TR|TH|TD)$/.test(t.nodeName)&&t.firstChild&&(t="TR"==t.nodeName?t.firstChild.firstChild||t:t.firstChild||t),r&&/^T(HEAD|BODY|FOOT|R)$/.test(r.nodeName)&&c(n)&&n.firstChild&&(n=n.firstChild||n),Q.isChildOf(t,n)&&!ne(n)&&!c(t)&&!c(n))return t=U(t,"span",{id:"_start","data-mce-type":"bookmark"}),s(t),void(t=u(le));t=U(t,"span",{id:"_start","data-mce-type":"bookmark"}),n=U(n,"span",{id:"_end","data-mce-type":"bookmark"}),s(t),s(n),t=u(le),n=u()}else
t=n=s(t);e.startContainer=t.parentNode?t.parentNode:t,e.startOffset=ie(t),e.endContainer=n.parentNode?n.parentNode:n,e.endOffset=ie(n)+1}ee.walk(e,function(e){me(e,function(e){i(e),1===e.nodeType&&"underline"===l.dom.getStyle(e,"text-decoration")&&e.parentNode&&"underline"===C(e.parentNode)&&$({deep:!1,exact:!0,inline:"span",styles:{textDecoration:"underline"}},null,e)})})}var p=g(e),h=p[0],m,v,y=!0;if(n)return void(n.nodeType?(v=Q.createRng(),v.setStartBefore(n),v.setEndAfter(n),d(v)):d(n));if("false"!==de(Z.getNode()))Z.isCollapsed()&&h.inline&&!Q.select("td[data-mce-selected],th[data-mce-selected]").length?K("remove",e,t,r):(m=Z.getBookmark(),d(Z.getRng(le)),Z.moveToBookmark(m),h.inline&&S(e,t,Z.getStart())&&G(Z.getRng(!0)),l.nodeChanged());else{n=Z.getNode();for(var b=0,x=p.length;b<x&&(!p[b].ceFalseOverride||!$(p[b],t,n,n));b
++);}}function N(e,t,n){var r=g(e);!S(e,t,n)||"toggle"in r[0]&&!r[0].toggle?w(e,t,n):E(e,t,n)}function _(e,t,n,r){function i(e,t,i){var o,a,s=t[i],l;if(t.onmatch)return t.onmatch(e,t,i);if(s)if(s.length===ce){for(o in s)if(s.hasOwnProperty(o)){if(a="attributes"===i?Q.getAttrib(e,o):H(e,o),r&&!a&&!t.exact)return;if((!r||t.exact)&&!D(a,I(F(s[o],n),o)))return}}else for(l=0;l<s.length;l++)if("attributes"===i?Q.getAttrib(e,s[l]):H(e,s[l]))return t;return t}var o=g(t),a,s,l;if(o&&e)for(s=0;s<o.length;s++)if(a=o[s],B(e,a)&&i(e,a,"attributes")&&i(e,a,"styles")){if(l=a.classes)for(s=0;s<l.length;s++)if(!Q.hasClass(e,l[s]))return;return a}}function S(e,t,n){function r(n){var r=Q.getRoot();return n!==r&&(n=Q.getParent(n,function(n){return!!b(n,e)||(n.parentNode===r||!!_(n,e,t,!0))}),_(n,e,t))}var i;return n?r(n):(n=Z.getNode(),r(n)?le:(i=Z.getStart(),i!=n&&r(i)?le:
se))}function k(e,t){var n,r=[],i={};return n=Z.getStart(),Q.getParent(n,function(n){var o,a;for(o=0;o<e.length;o++)a=e[o],!i[a]&&_(n,a,t)&&(i[a]=!0,r.push(a))},Q.getRoot()),r}function T(e){var t=g(e),n,r,i,o,a;if(t)for(n=Z.getStart(),r=f(n),o=t.length-1;o>=0;o--){if(a=t[o].selector,!a||t[o].defaultBlock)return le;for(i=r.length-1;i>=0;i--)if(Q.is(r[i],a))return le}return se}function R(e,t,n){var r;return ue||(ue={},r={},l.on("NodeChange",function(e){var t=f(e.element),n={};t=o.grep(t,function(e){return 1==e.nodeType&&!e.getAttribute("data-mce-bogus")}),me(ue,function(e,i){me(t,function(o){return _(o,i,{},e.similar)?(r[i]||(me(e,function(e){e(!0,{node:o,format:i,parents:t})}),r[i]=e),n[i]=e,!1):!b(o,i)&&void 0})}),me(r,function(i,o){n[o]||(delete r[o],me(i,function(n){n(!1,{node:e.element,format:o,parents:t})}))})})),me(e.split(","),function(e){ue[e]||(ue[e]=[],ue[e].similar=n),ue[e].push(t)}),this}function A(e){
return a.getCssText(l,e)}function B(e,t){return D(e,t.inline)?le:D(e,t.block)?le:t.selector?1==e.nodeType&&Q.is(e,t.selector):void 0}function D(e,t){return e=e||"",t=t||"",e=""+(e.nodeName||e),t=""+(t.nodeName||t),e.toLowerCase()==t.toLowerCase()}function L(e,t,n){me(e.childNodes,function(e){M(e)&&(t(e)&&n(e),e.hasChildNodes()&&L(e,t,n))})}function M(e){return 1==e.nodeType&&!he(e)&&!z(e)&&!p(e)}function P(e){return i.curry(function(e,t){return!(!t||!H(t,e))},e)}function O(e,t){return i.curry(function(e,t,n){Q.setStyle(n,e,t)},e,t)}function H(e,t){return I(Q.getStyle(e,t),t)}function I(e,t){return"color"!=t&&"backgroundColor"!=t||(e=Q.toHex(e)),"fontWeight"==t&&700==e&&(e="bold"),"fontFamily"==t&&(e=e.replace(/[\'\"]/g,"").replace(/,\s+/g,",")),""+e}function F(e,t){return&q
uot;string"!=typeof e?e=e(t):t&&(e=e.replace(/%(\w+)/g,function(e,n){return t[n]||e})),e}function z(e){return e&&3===e.nodeType&&/^([\t \r\n]+|)$/.test(e.nodeValue)}function U(e,t,n){var r=Q.create(t,n);return e.parentNode.insertBefore(r,e),r.appendChild(e),r}function W(t,n,r){function i(e){function t(e){return"BR"==e.nodeName&&e.getAttribute("data-mce-bogus")&&!e.nextSibling}var r,i,o,a,s;if(r=i=e?g:y,a=e?"previousSibling":"nextSibling",s=Q.getRoot(),3==r.nodeType&&!z(r)&&(e?v>0:b<r.nodeValue.length))return r;for(;;){if(!n[0].block_expand&&ne(i))return i;for(o=i[a];o;o=o[a])if(!he(o)&&!z(o)&&!t(o))return i;if(i==s||i.parentNode==s){r=i;break}i=i.parentNode}return r}function o(e,t){for(t===ce&&(t=3===e.nodeType?e.length:e.childNodes.length);e&&e.hasChildNodes();)e=e.childNodes[t],e&&(t=3===e.nodeType?e.length:e.childNodes.length);
return{node:e,offset:t}}function a(e){for(var t=e;t;){if(1===t.nodeType&&de(t))return"false"===de(t)?t:e;t=t.parentNode}return e}function s(t,n,i){function o(e,t){var n,o,a=e.nodeValue;return"undefined"==typeof t&&(t=i?a.length:0),i?(n=a.lastIndexOf(" ",t),o=a.lastIndexOf("\xa0",t),n=n>o?n:o,n===-1||r||n++):(n=a.indexOf(" ",t),o=a.indexOf("\xa0",t),n=n!==-1&&(o===-1||n<o)?n:o),n}var a,s,u,c;if(3===t.nodeType){if(u=o(t,n),u!==-1)return{container:t,offset:u};c=t}for(a=new e(t,Q.getParent(t,ne)||l.getBody());s=a[i?"prev":"next"]();)if(3===s.nodeType){if(c=s,u=o(s),u!==-1)return{container:s,offset:u}}else if(ne(s))break;if(c)return n=i?0:c.length,{container:c,offset:n}}function c(e,r){var i,o,a,s;for(3==e.nodeType&&0===e.nodeValue.length&&e[r]&&(e=e[r]),i=f(e),o=0;o<i.length;o++)for(a=0;a<n.length;a++)if(s=n[a],!("collapsed"in s&&s
.collapsed!==t.collapsed)&&Q.is(i[o],s.selector))return i[o];return e}function d(e,t){var r,i=Q.getRoot();if(n[0].wrapper||(r=Q.getParent(e,n[0].block,i)),r||(r=Q.getParent(3==e.nodeType?e.parentNode:e,function(e){return e!=i&&u(e)})),r&&n[0].wrapper&&(r=f(r,"ul,ol").reverse()[0]||r),!r)for(r=e;r[t]&&!ne(r[t])&&(r=r[t],!D(r,"br")););return r||e}var p,h,m,g=t.startContainer,v=t.startOffset,y=t.endContainer,b=t.endOffset;if(1==g.nodeType&&g.hasChildNodes()&&(p=g.childNodes.length-1,g=g.childNodes[v>p?p:v],3==g.nodeType&&(v=0)),1==y.nodeType&&y.hasChildNodes()&&(p=y.childNodes.length-1,y=y.childNodes[b>p?p:b-1],3==y.nodeType&&(b=y.nodeValue.length)),g=a(g),y=a(y),(he(g.parentNode)||he(g))&&(g=he(g)?g:g.parentNode,g=g.nextSibling||g,3==g.nodeType&&(v=0)),(he(y.parentNode)||he(y))&&(y=he(y)?y:y.parentNode,y=y.previousSibling||y,3==y.nodeType&am
p;&(b=y.length)),n[0].inline&&(t.collapsed&&(m=s(g,v,!0),m&&(g=m.container,v=m.offset),m=s(y,b),m&&(y=m.container,b=m.offset)),h=o(y,b),h.node)){for(;h.node&&0===h.offset&&h.node.previousSibling;)h=o(h.node.previousSibling);h.node&&h.offset>0&&3===h.node.nodeType&&" "===h.node.nodeValue.charAt(h.offset-1)&&h.offset>1&&(y=h.node,y.splitText(h.offset-1))}return(n[0].inline||n[0].block_expand)&&(n[0].inline&&3==g.nodeType&&0!==v||(g=i(!0)),n[0].inline&&3==y.nodeType&&b!==y.nodeValue.length||(y=i())),n[0].selector&&n[0].expand!==se&&!n[0].inline&&(g=c(g,"previousSibling"),y=c(y,"nextSibling")),(n[0].block||n[0].selector)&&(g=d(g,"previousSibling"),y=d(y,"nextSibling"),n[0].block&&(ne(g)||(g=i(!0)),ne(y)||(y=i()))),1==g.nodeType&&(v=ie(g),g=g.parentNode),1
==y.nodeType&&(b=ie(y)+1,y=y.parentNode),{startContainer:g,startOffset:v,endContainer:y,endOffset:b}}function V(e,t){return t.links&&"A"==e.tagName}function $(e,t,n,r){var i,o,a;if(!B(n,e)&&!V(n,e))return se;if("all"!=e.remove)for(me(e.styles,function(i,o){i=I(F(i,t),o),"number"==typeof o&&(o=i,r=0),(e.remove_similar||!r||D(H(r,o),i))&&Q.setStyle(n,o,""),a=1}),a&&""===Q.getAttrib(n,"style")&&(n.removeAttribute("style"),n.removeAttribute("data-mce-style")),me(e.attributes,function(e,i){var o;if(e=F(e,t),"number"==typeof i&&(i=e,r=0),!r||D(Q.getAttrib(r,i),e)){if("class"==i&&(e=Q.getAttrib(n,i),e&&(o="",me(e.split(/\s+/),function(e){/mce\-\w+/.test(e)&&(o+=(o?" ":"")+e)}),o)))return void Q.setAttrib(n,i,o);"class"==i&&n.removeAttribute("className&q
uot;),ae.test(i)&&n.removeAttribute("data-mce-"+i),n.removeAttribute(i)}}),me(e.classes,function(e){e=F(e,t),r&&!Q.hasClass(r,e)||Q.removeClass(n,e)}),o=Q.getAttribs(n),i=0;i<o.length;i++){var s=o[i].nodeName;if(0!==s.indexOf("_")&&0!==s.indexOf("data-"))return se}return"none"!=e.remove?(q(n,e),le):void 0}function q(e,t){function n(e,t,n){return e=j(e,t,n),!e||"BR"==e.nodeName||ne(e)}var r=e.parentNode,i;t.block&&(re?r==Q.getRoot()&&(t.list_block&&D(e,t.list_block)||me(ge(e.childNodes),function(e){te(re,e.nodeName.toLowerCase())?i?i.appendChild(e):(i=U(e,re),Q.setAttribs(i,l.settings.forced_root_block_attrs)):i=0})):ne(e)&&!ne(r)&&(n(e,se)||n(e.firstChild,le,1)||e.insertBefore(Q.create("br"),e.firstChild),n(e,le)||n(e.lastChild,se,1)||e.appendChild(Q.create("br")))),t.selector&&t.inline&&!D(t.inline,e)||Q.remove(e,1)}function j(e,t,
n){if(e)for(t=t?"nextSibling":"previousSibling",e=n?e:e[t];e;e=e[t])if(1==e.nodeType||!z(e))return e}function Y(e,t){function n(e,t){for(i=e;i;i=i[t]){if(3==i.nodeType&&0!==i.nodeValue.length)return e;if(1==i.nodeType&&!he(i))return i}return e}var i,o,a=new r(Q);if(e&&t&&(e=n(e,"previousSibling"),t=n(t,"nextSibling"),a.compare(e,t))){for(i=e.nextSibling;i&&i!=t;)o=i,i=i.nextSibling,e.appendChild(o);return Q.remove(t),me(ge(t.childNodes),function(t){e.appendChild(t)}),e}return t}function X(t,n){var r,i,o;return r=t[n?"startContainer":"endContainer"],i=t[n?"startOffset":"endOffset"],1==r.nodeType&&(o=r.childNodes.length-1,!n&&i&&i--,r=r.childNodes[i>o?o:i]),3===r.nodeType&&n&&i>=r.nodeValue.length&&(r=new e(r,l.getBody()).next()||r),3!==r.nodeType||n||0!==i||(r=new e(r,l.getBody()).prev()||r),r}function K(t,n,r,i)
{function o(e){var t=Q.create("span",{id:m,"data-mce-bogus":!0,style:v?"color:red":""});return e&&t.appendChild(l.getDoc().createTextNode(oe)),t}function a(e,t){for(;e;){if(3===e.nodeType&&e.nodeValue!==oe||e.childNodes.length>1)return!1;t&&1===e.nodeType&&t.push(e),e=e.firstChild}return!0}function s(e){for(;e;){if(e.id===m)return e;e=e.parentNode}}function c(t){var n;if(t)for(n=new e(t,t),t=n.current();t;t=n.next())if(3===t.nodeType)return t}function d(e,t){var n,r;if(e)r=Z.getRng(!0),a(e)?(t!==!1&&(r.setStartBefore(e),r.setEndBefore(e)),Q.remove(e)):(n=c(e),n.nodeValue.charAt(0)===oe&&(n.deleteData(0,1),r.startContainer==n&&r.startOffset>0&&r.setStart(n,r.startOffset-1),r.endContainer==n&&r.endOffset>0&&r.setEnd(n,r.endOffset-1)),Q.remove(e,1)),Z.setRng(r);else if(e=s(Z.getStart()),!e)for(;e=Q.get(m);)d(e,!1)}function f(){var e,t,i,a,l,u,d;e=Z.getRng(!0)
,a=e.startOffset,u=e.startContainer,d=u.nodeValue,t=s(Z.getStart()),t&&(i=c(t));var f=/[^\s\u00a0\u00ad\u200b\ufeff]/;d&&a>0&&a<d.length&&f.test(d.charAt(a))&&f.test(d.charAt(a-1))?(l=Z.getBookmark(),e.collapse(!0),e=W(e,g(n)),e=ee.split(e),w(n,r,e),Z.moveToBookmark(l)):(t&&i.nodeValue===oe?w(n,r,t):(t=o(!0),i=t.firstChild,e.insertNode(t),a=1,w(n,r,t)),Z.setCursorLocation(i,a))}function p(){var e=Z.getRng(!0),t,a,s,l,c,d,f=[],p,h;for(t=e.startContainer,a=e.startOffset,c=t,3==t.nodeType&&(a!=t.nodeValue.length&&(l=!0),c=c.parentNode);c;){if(_(c,n,r,i)){d=c;break}c.nextSibling&&(l=!0),f.push(c),c=c.parentNode}if(d)if(l)s=Z.getBookmark(),e.collapse(!0),e=W(e,g(n),!0),e=ee.split(e),E(n,r,e),Z.moveToBookmark(s);else{for(h=o(),c=h,p=f.length-1;p>=0;p--)c.appendChild(Q.clone(f[p],!1)),c=c.firstChild;c.appendChild(Q.doc.createTextNode(oe)),c=c.firstChild;var m=Q.getParent(d,u);m&&Q.isEmpty(m)?d.parentNo
de.replaceChild(h,d):Q.insertAfter(h,d),Z.setCursorLocation(c,1),Q.isEmpty(d)&&Q.remove(d)}}function h(){var e;e=s(Z.getStart()),e&&!Q.isEmpty(e)&&ve(e,function(e){1!=e.nodeType||e.id===m||Q.isEmpty(e)||Q.setAttrib(e,"data-mce-bogus",null)},"childNodes")}var m="_mce_caret",v=l.settings.caret_debug;l._hasCaretEvents||(pe=function(){var e=[],t;if(a(s(Z.getStart()),e))for(t=e.length;t--;)Q.setAttrib(e[t],"data-mce-bogus","1")},fe=function(e){var t=e.keyCode;d(),8==t&&Z.isCollapsed()&&Z.getStart().innerHTML==oe&&d(s(Z.getStart())),37!=t&&39!=t||d(s(Z.getStart())),h()},l.on("SetContent",function(e){e.selection&&h()}),l._hasCaretEvents=!0),"apply"==t?f():p()}function G(t){var n=t.startContainer,r=t.startOffset,i,o,a,s,l;if((t.startContainer!=t.endContainer||!d(t.startContainer.childNodes[t.startOffset]))&&(3==n.nodeType&&r>=n.nodeValue.le
ngth&&(r=ie(n),n=n.parentNode,i=!0),1==n.nodeType))for(s=n.childNodes,n=s[Math.min(r,s.length-1)],o=new e(n,Q.getParent(n,Q.isBlock)),(r>s.length-1||i)&&o.next(),a=o.current();a;a=o.next())if(3==a.nodeType&&!z(a))return l=Q.create("a",{"data-mce-bogus":"all"},oe),a.parentNode.insertBefore(l,a),t.setStart(a,0),Z.setRng(t),void Q.remove(l)}var J={},Q=l.dom,Z=l.selection,ee=new t(Q),te=l.schema.isValidChild,ne=Q.isBlock,re=l.settings.forced_root_block,ie=Q.nodeIndex,oe="\ufeff",ae=/^(src|href|style)$/,se=!1,le=!0,ue,ce,de=Q.getContentEditable,fe,pe,he=n.isBookmarkNode,me=o.each,ge=o.grep,ve=o.walk,ye=o.extend;ye(this,{get:g,register:v,unregister:y,apply:w,remove:E,toggle:N,match:S,matchAll:k,matchNode:_,canApply:T,formatChanged:R,getCssText:A}),h(),m(),l.on("BeforeGetContent",function(e){pe&&"raw"!=e.format&&pe()}),l.on("mouseup keydown",function(e){fe&&fe(e)})}}),r(
Q,[],function(){var e=0,t=1,n=2,r=function(r,i){var o=r.length+i.length+2,a=new Array(o),s=new Array(o),l=function(e,t,n){return{start:e,end:t,diag:n}},u=function(o,a,s,l,c){var f=d(o,a,s,l);if(null===f||f.start===a&&f.diag===a-l||f.end===o&&f.diag===o-s)for(var p=o,h=s;p<a||h<l;)p<a&&h<l&&r[p]===i[h]?(c.push([e,r[p]]),++p,++h):a-o>l-s?(c.push([n,r[p]]),++p):(c.push([t,i[h]]),++h);else{u(o,f.start,s,f.start-f.diag,c);for(var m=f.start;m<f.end;++m)c.push([e,r[m]]);u(f.end,a,f.end-f.diag,l,c)}},c=function(e,t,n,o){for(var a=e;a-t<o&&a<n&&r[a]===i[a-t];)++a;return l(e,a,t)},d=function(e,t,n,o){var l=t-e,u=o-n;if(0===l||0===u)return null;var d=l-u,f=u+l,p=(f%2===0?f:f+1)/2;a[1+p]=e,s[1+p]=t+1;for(var h=0;h<=p;++h){for(var m=-h;m<=h;m+=2){var g=m+p;m===-h||m!=h&&a[g-1]<a[g+1]?a[g]=a[g+1]:a[g]=a[g-1]+1;for(var v=a[g],y=v-e+n-m;v<t&&y<o&&r[v]===i[y];)a[g]=++v,++y;if(d%2!=0&&am
p;d-h<=m&&m<=d+h&&s[g-d]<=a[g])return c(s[g-d],m+e-n,t,o)}for(m=d-h;m<=d+h;m+=2){for(g=m+p-d,m===d-h||m!=d+h&&s[g+1]<=s[g-1]?s[g]=s[g+1]-1:s[g]=s[g-1],v=s[g]-1,y=v-e+n-m;v>=e&&y>=n&&r[v]===i[y];)s[g]=v--,y--;if(d%2===0&&-h<=m&&m<=h&&s[g]<=a[g+d])return c(s[g],m+e-n,t,o)}}},f=[];return u(0,r.length,0,i.length,f),f};return{KEEP:e,DELETE:n,INSERT:t,diff:r}}),r(Z,[h,C,Q],function(e,t,n){var r=function(e){return 1===e.nodeType?e.outerHTML:3===e.nodeType?t.encodeRaw(e.data,!1):8===e.nodeType?"<!--"+e.data+"-->":""},i=function(e){var t,n,r;for(r=document.createElement("div"),t=document.createDocumentFragment(),e&&(r.innerHTML=e);n=r.firstChild;)t.appendChild(n);return t},o=function(e,t,n){var r=i(t);if(e.hasChildNodes()&&n<e.childNodes.length){var o=e.childNodes[n];o.parentNode.insertBefore(r,o)}else e.appendChild(r)},a=function(e,t)
{if(e.hasChildNodes()&&t<e.childNodes.length){var n=e.childNodes[t];n.parentNode.removeChild(n)}},s=function(t,r){var i=0;e.each(t,function(e){e[0]===n.KEEP?i++:e[0]===n.INSERT?(o(r,e[1],i),i++):e[0]===n.DELETE&&a(r,i)})},l=function(t){return e.map(t.childNodes,r)},u=function(t,i){var o=e.map(i.childNodes,r);return s(n.diff(o,t),i),i};return{read:l,write:u}}),r(ee,[h,Z],function(e,t){var n=function(e){return e.indexOf("</iframe>")!==-1},r=function(e){return{type:"fragmented",fragments:e,content:"",bookmark:null,beforeBookmark:null}},i=function(e){return{type:"complete",fragments:null,content:e,bookmark:null,beforeBookmark:null}},o=function(o){var a,s,l;return a=t.read(o.getBody()),l=e.map(a,function(e){return o.serializer.trimContent(e)}),s=l.join(""),n(s)?r(l):i(s)},a=function(e,n,r){"fragmented"===n.type?t.write(n.fragments,e.getBody()):e.setContent(n.content,{format:"raw"}),e.selection.
moveToBookmark(r?n.beforeBookmark:n.bookmark)},s=function(e){return"fragmented"===e.type?e.fragments.join(""):e.content},l=function(e,t){return s(e)===s(t)};return{createFragmentedLevel:r,createCompleteLevel:i,createFromEditor:o,applyToEditor:a,isEq:l}}),r(te,[I,m,ee],function(e,t,n){return function(e){function r(t){e.setDirty(t)}function i(e){a.typing=!1,a.add({},e)}function o(){a.typing&&(a.typing=!1,a.add())}var a=this,s=0,l=[],u,c,d=0;return e.on("init",function(){a.add()}),e.on("BeforeExecCommand",function(e){var t=e.command;"Undo"!==t&&"Redo"!==t&&"mceRepaint"!==t&&(o(),a.beforeChange())}),e.on("ExecCommand",function(e){var t=e.command;"Undo"!==t&&"Redo"!==t&&"mceRepaint"!==t&&i(e)}),e.on("ObjectResizeStart Cut",function(){a.beforeChange()}),e.on("SaveContent ObjectResized blur",i),e.on("D
ragEnd",i),e.on("KeyUp",function(t){var o=t.keyCode;t.isDefaultPrevented()||((o>=33&&o<=36||o>=37&&o<=40||45===o||t.ctrlKey)&&(i(),e.nodeChanged()),46!==o&&8!==o||e.nodeChanged(),c&&a.typing&&(e.isDirty()||(r(l[0]&&!n.isEq(n.createFromEditor(e),l[0])),e.isDirty()&&e.fire("change",{level:l[0],lastLevel:null})),e.fire("TypingUndo"),c=!1,e.nodeChanged()))}),e.on("KeyDown",function(e){var t=e.keyCode;if(!e.isDefaultPrevented()){if(t>=33&&t<=36||t>=37&&t<=40||45===t)return void(a.typing&&i(e));var n=e.ctrlKey&&!e.altKey||e.metaKey;!(t<16||t>20)||224===t||91===t||a.typing||n||(a.beforeChange(),a.typing=!0,a.add({},e),c=!0)}}),e.on("MouseDown",function(e){a.typing&&i(e)}),e.addShortcut("meta+z","","Undo"),e.addShortcut("meta+y,meta+shift+z","","Redo&
quot;),e.on("AddUndo Undo Redo ClearUndos",function(t){t.isDefaultPrevented()||e.nodeChanged()}),a={data:l,typing:!1,beforeChange:function(){d||(u=e.selection.getBookmark(2,!0))},add:function(i,o){var a,c=e.settings,f,p;if(p=n.createFromEditor(e),i=i||{},i=t.extend(i,p),d||e.removed)return null;if(f=l[s],e.fire("BeforeAddUndo",{level:i,lastLevel:f,originalEvent:o}).isDefaultPrevented())return null;if(f&&n.isEq(f,i))return null;if(l[s]&&(l[s].beforeBookmark=u),c.custom_undo_redo_levels&&l.length>c.custom_undo_redo_levels){for(a=0;a<l.length-1;a++)l[a]=l[a+1];l.length--,s=l.length}i.bookmark=e.selection.getBookmark(2,!0),s<l.length-1&&(l.length=s+1),l.push(i),s=l.length-1;var h={level:i,lastLevel:f,originalEvent:o};return e.fire("AddUndo",h),s>0&&(r(!0),e.fire("change",h)),i},undo:function(){var t;return a.typing&&(a.add(),a.typing=!1),s>0&&(t=l[--s],n.applyToEditor(e,t,!0),r
(!0),e.fire("undo",{level:t})),t},redo:function(){var t;return s<l.length-1&&(t=l[++s],n.applyToEditor(e,t,!1),r(!0),e.fire("redo",{level:t})),t},clear:function(){l=[],s=0,a.typing=!1,a.data=l,e.fire("ClearUndos")},hasUndo:function(){return s>0||a.typing&&l[0]&&!n.isEq(n.createFromEditor(e),l[0])},hasRedo:function(){return s<l.length-1&&!a.typing},transact:function(e){o(),a.beforeChange();try{d++,e()}finally{d--}return a.add()},extra:function(t,r){var i,o;a.transact(t)&&(o=l[s].bookmark,i=l[s-1],n.applyToEditor(e,i,!0),a.transact(r)&&(l[s-1].beforeBookmark=o))}}}}),r(ne,[y,T,k,d],function(e,t,n,r){var i=r.ie&&r.ie<11;return function(o){function a(a){function h(e){return e&&s.isBlock(e)&&!/^(TD|TH|CAPTION|FORM)$/.test(e.nodeName)&&!/^(fixed|absolute)/i.test(e.style.position)&&"true"!==s.getContentEditable(e)}function m(e){return e&&/^(TD|
TH|CAPTION)$/.test(e.nodeName)}function g(e){var t;s.isBlock(e)&&(t=l.getRng(),e.appendChild(s.create("span",null,"\xa0")),l.select(e),e.lastChild.outerHTML="",l.setRng(t))}function v(e){var t=e,n=[],r;if(t){for(;t=t.firstChild;){if(s.isBlock(t))return;1!=t.nodeType||f[t.nodeName.toLowerCase()]||n.push(t)}for(r=n.length;r--;)t=n[r],!t.hasChildNodes()||t.firstChild==t.lastChild&&""===t.firstChild.nodeValue?s.remove(t):"A"==t.nodeName&&" "===(t.innerText||t.textContent)&&s.remove(t)}}function y(t){function n(e){for(;e;){if(1==e.nodeType||3==e.nodeType&&e.data&&/[\r\n\s]/.test(e.data))return e;e=e.nextSibling}}var i,o,a,u=t,c;if(t){if(r.ie&&r.ie<9&&P&&P.firstChild&&P.firstChild==P.lastChild&&"BR"==P.firstChild.tagName&&s.remove(P.firstChild),/^(LI|DT|DD)$/.test(t.nodeName)){var d=n(t.firstChild);d&&/^(UL|OL|DL)$
/.test(d.nodeName)&&t.insertBefore(s.doc.createTextNode("\xa0"),t.firstChild)}if(a=s.createRng(),r.ie||t.normalize(),t.hasChildNodes()){for(i=new e(t,t);o=i.current();){if(3==o.nodeType){a.setStart(o,0),a.setEnd(o,0);break}if(p[o.nodeName.toLowerCase()]){a.setStartBefore(o),a.setEndBefore(o);break}u=o,o=i.next()}o||(a.setStart(u,0),a.setEnd(u,0))}else"BR"==t.nodeName?t.nextSibling&&s.isBlock(t.nextSibling)?((!O||O<9)&&(c=s.create("br"),t.parentNode.insertBefore(c,t)),a.setStartBefore(t),a.setEndBefore(t)):(a.setStartAfter(t),a.setEndAfter(t)):(a.setStart(t,0),a.setEnd(t,0));l.setRng(a),s.remove(c),l.scrollIntoView(t)}}function b(e){var t=u.forced_root_block;t&&t.toLowerCase()===e.tagName.toLowerCase()&&s.setAttribs(e,u.forced_root_block_attrs)}function C(e){e.innerHTML=i?"":'<br data-mce-bogus="1">'}function x(e){var t=L,n,r,o,a=d.getTextInlineElements();if(e||"TABLE"==U?(n=s
.create(e||V),b(n)):n=P.cloneNode(!1),o=n,u.keep_styles!==!1)do if(a[t.nodeName]){if("_mce_caret"==t.id)continue;r=t.cloneNode(!1),s.setAttrib(r,"id",""),n.hasChildNodes()?(r.appendChild(n.firstChild),n.appendChild(r)):(o=r,n.appendChild(r))}while((t=t.parentNode)&&t!=D);return i||(o.innerHTML='<br data-mce-bogus="1">'),n}function w(t){var n,r,i;if(3==L.nodeType&&(t?M>0:M<L.nodeValue.length))return!1;if(L.parentNode==P&&$&&!t)return!0;if(t&&1==L.nodeType&&L==P.firstChild)return!0;if("TABLE"===L.nodeName||L.previousSibling&&"TABLE"==L.previousSibling.nodeName)return $&&!t||!$&&t;for(n=new e(L,P),3==L.nodeType&&(t&&0===M?n.prev():t||M!=L.nodeValue.length||n.next());r=n.current();){if(1===r.nodeType){if(!r.getAttribute("data-mce-bogus")&&(i=r.nodeName.toLowerCase(),f[i]&&"br"!==i))return!1}els
e if(3===r.nodeType&&!/^[ \t\r\n]*$/.test(r.nodeValue))return!1;t?n.prev():n.next()}return!0}function E(e,t){var n,r,i,a,l,u,c=V||"P";if(r=s.getParent(e,s.isBlock),!r||!h(r)){if(r=r||D,u=r==o.getBody()||m(r)?r.nodeName.toLowerCase():r.parentNode.nodeName.toLowerCase(),!r.hasChildNodes())return n=s.create(c),b(n),r.appendChild(n),A.setStart(n,0),A.setEnd(n,0),n;for(a=e;a.parentNode!=r;)a=a.parentNode;for(;a&&!s.isBlock(a);)i=a,a=a.previousSibling;if(i&&d.isValidChild(u,c.toLowerCase())){for(n=s.create(c),b(n),i.parentNode.insertBefore(n,i),a=i;a&&!s.isBlock(a);)l=a.nextSibling,n.appendChild(a),a=l;A.setStart(e,t),A.setEnd(e,t)}}return e}function N(){function e(e){for(var t=z[e?"firstChild":"lastChild"];t&&1!=t.nodeType;)t=t[e?"nextSibling":"previousSibling"];return t===P}function t(){var e=z.parentNode;return/^(LI|DT|DD)$/.test(e.nodeName)?e:z}if(z!=o.getBody()){var n=z.parentNode.nodeName;/^(OL
|UL|LI)$/.test(n)&&(V="LI"),I=V?x(V):s.create("BR"),e(!0)&&e()?"LI"==n?s.insertAfter(I,t()):s.replace(I,z):e(!0)?"LI"==n?(s.insertAfter(I,t()),I.appendChild(s.doc.createTextNode(" ")),I.appendChild(z)):z.parentNode.insertBefore(I,z):e()?(s.insertAfter(I,t()),g(I)):(z=t(),B=A.cloneRange(),B.setStartAfter(P),B.setEndAfter(z),F=B.extractContents(),"LI"==V&&"LI"==F.firstChild.nodeName?(I=F.firstChild,s.insertAfter(F,z)):(s.insertAfter(F,z),s.insertAfter(I,z))),s.remove(P),y(I),c.add()}}function _(){o.execCommand("InsertLineBreak",!1,a)}function S(e){do 3===e.nodeType&&(e.nodeValue=e.nodeValue.replace(/^[\r\n]+/,"")),e=e.firstChild;while(e)}function k(e){var t=s.getRoot(),n,r;for(n=e;n!==t&&"false"!==s.getContentEditable(n);)"true"===s.getContentEditable(n)&&(r=n),n=n.parentNode;return n!==t?r:t}function T(e){var t;i||(e.normalize()
,t=e.lastChild,t&&!/^(left|right)$/gi.test(s.getStyle(t,"float",!0))||s.add(e,"br"))}function R(){I=/^(H[1-6]|PRE|FIGURE)$/.test(U)&&"HGROUP"!=W?x(V):x(),u.end_container_on_empty_block&&h(z)&&s.isEmpty(P)?I=s.split(z,P):s.insertAfter(I,P),y(I)}var A,B,D,L,M,P,O,H,I,F,z,U,W,V,$;if(A=l.getRng(!0),!a.isDefaultPrevented()){if(!A.collapsed)return void o.execCommand("Delete");if(new t(s).normalize(A),L=A.startContainer,M=A.startOffset,V=(u.force_p_newlines?"p":"")||u.forced_root_block,V=V?V.toUpperCase():"",O=s.doc.documentMode,H=a.shiftKey,1==L.nodeType&&L.hasChildNodes()&&($=M>L.childNodes.length-1,L=L.childNodes[Math.min(M,L.childNodes.length-1)]||L,M=$&&3==L.nodeType?L.nodeValue.length:0),D=k(L)){if(c.beforeChange(),!s.isBlock(D)&&D!=s.getRoot())return void(V&&!H||_());if((V&&!H||!V&&H)&&(L=E(L,M)),P=s.getParent(L,s.is
Block),z=P?s.getParent(P.parentNode,s.isBlock):null,U=P?P.nodeName.toUpperCase():"",W=z?z.nodeName.toUpperCase():"","LI"!=W||a.ctrlKey||(P=z,U=W),o.undoManager.typing&&(o.undoManager.typing=!1,o.undoManager.add()),/^(LI|DT|DD)$/.test(U)){if(!V&&H)return void _();if(s.isEmpty(P))return void N()}if("PRE"==U&&u.br_in_pre!==!1){if(!H)return void _()}else if(!V&&!H&&"LI"!=U||V&&H)return void _();V&&P===o.getBody()||(V=V||"P",n.isCaretContainerBlock(P)?(I=n.showCaretContainerBlock(P),s.isEmpty(P)&&C(P),y(I)):w()?R():w(!0)?(I=P.parentNode.insertBefore(x(),P),g(I),y(P)):(B=A.cloneRange(),B.setEndAfter(P),F=B.extractContents(),S(F),I=F.firstChild,s.insertAfter(F,P),v(I),T(P),s.isEmpty(P)&&C(P),I.normalize(),s.isEmpty(I)?(s.remove(I),R()):y(I)),s.setAttrib(I,"id",""),o.fire("NewBlock",{newBlock:I}),c.typing=!1,c.add())}}}var s=o.dom,
l=o.selection,u=o.settings,c=o.undoManager,d=o.schema,f=d.getNonEmptyElements(),p=d.getMoveCaretBeforeOnEnterElements();o.on("keydown",function(e){13==e.keyCode&&a(e)!==!1&&e.preventDefault()})}}),r(re,[],function(){return function(e){function t(){var t=i.getStart(),s=e.getBody(),l,u,c,d,f,p,h,m=-16777215,g,v,y,b,C;if(C=n.forced_root_block,t&&1===t.nodeType&&C){for(;t&&t!=s;){if(a[t.nodeName])return;t=t.parentNode}if(l=i.getRng(),l.setStart){u=l.startContainer,c=l.startOffset,d=l.endContainer,f=l.endOffset;try{v=e.getDoc().activeElement===s}catch(x){}}else l.item&&(t=l.item(0),l=e.getDoc().body.createTextRange(),l.moveToElementText(t)),v=l.parentElement().ownerDocument===e.getDoc(),y=l.duplicate(),y.collapse(!0),c=y.move("character",m)*-1,y.collapsed||(y=l.duplicate(),y.collapse(!1),f=y.move("character",m)*-1-c);for(t=s.firstChild,b=s.nodeName.toLowerCase();t;)if((3===t.nodeType||1==t.nodeType&&!a[
t.nodeName])&&o.isValidChild(b,C.toLowerCase())){if(3===t.nodeType&&0===t.nodeValue.length){h=t,t=t.nextSibling,r.remove(h);continue}p||(p=r.create(C,e.settings.forced_root_block_attrs),
-t.parentNode.insertBefore(p,t),g=!0),h=t,t=t.nextSibling,p.appendChild(h)}else p=null,t=t.nextSibling;if(g&&v){if(l.setStart)l.setStart(u,c),l.setEnd(d,f),i.setRng(l);else try{l=e.getDoc().body.createTextRange(),l.moveToElementText(s),l.collapse(!0),l.moveStart("character",c),f>0&&l.moveEnd("character",f),l.select()}catch(x){}e.nodeChanged()}}}var n=e.settings,r=e.dom,i=e.selection,o=e.schema,a=o.getBlockElements();n.forced_root_block&&e.on("NodeChange",t)}}),r(ie,[z,y,_,$,k,U],function(e,t,n,r,i,o){function a(e){return e>0}function s(e){return e<0}function l(e,t){for(var n;n=e(t);)if(!N(n))return n;return null}function u(e,n,r,i,o){var u=new t(e,i);if(s(n)){if((x(e)||N(e))&&(e=l(u.prev,!0),r(e)))return e;for(;e=l(u.prev,o);)if(r(e))return e}if(a(n)){if((x(e)||N(e))&&(e=l(u.next,!0),r(e)))return e;for(;e=l(u.next,o);)if(r(e))return e}return null}function c(e,t){for(e=e.parentNode;e&&e!=t;e=e.paren
tNode)if(C(e))return e;return t}function d(e,t){for(;e&&e!=t;){if(w(e))return e;e=e.parentNode}return null}function f(e,t,n){return d(e.container(),n)==d(t.container(),n)}function p(e,t,n){return c(e.container(),n)==c(t.container(),n)}function h(e,t){var n,r;return t?(n=t.container(),r=t.offset(),S(n)?n.childNodes[r+e]:null):null}function m(e,t){var n=t.ownerDocument.createRange();return e?(n.setStartBefore(t),n.setEndBefore(t)):(n.setStartAfter(t),n.setEndAfter(t)),n}function g(e,t,n){return d(t,e)==d(n,e)}function v(e,t,n){var r,i;for(i=e?"previousSibling":"nextSibling";n&&n!=t;){if(r=n[i],E(r)&&(r=r[i]),x(r)){if(g(t,r,n))return r;break}if(k(r))break;n=n.parentNode}return null}function y(e,t,r){var o,a,s,l,u=_(v,!0,t),c=_(v,!1,t);if(a=r.startContainer,s=r.startOffset,i.isCaretContainerBlock(a)){if(S(a)||(a=a.parentNode),l=a.getAttribute("data-mce-caret"),"before"==l&&(o=a.nextSibling,x(o)))return T(o);if("
;after"==l&&(o=a.previousSibling,x(o)))return R(o)}if(!r.collapsed)return r;if(n.isText(a)){if(E(a)){if(1===e){if(o=c(a))return T(o);if(o=u(a))return R(o)}if(e===-1){if(o=u(a))return R(o);if(o=c(a))return T(o)}return r}if(i.endsWithCaretContainer(a)&&s>=a.data.length-1)return 1===e&&(o=c(a))?T(o):r;if(i.startsWithCaretContainer(a)&&s<=1)return e===-1&&(o=u(a))?R(o):r;if(s===a.data.length)return o=c(a),o?T(o):r;if(0===s)return o=u(a),o?R(o):r}return r}function b(e,t){return x(h(e,t))}var C=n.isContentEditableTrue,x=n.isContentEditableFalse,w=n.matchStyleValues("display","block table table-cell table-caption"),E=i.isCaretContainer,N=i.isCaretContainerBlock,_=e.curry,S=n.isElement,k=o.isCaretCandidate,T=_(m,!0),R=_(m,!1);return{isForwards:a,isBackwards:s,findNode:u,getEditingHost:c,getParentBlock:d,isInSameBlock:f,isInSameEditingHost:p,isBeforeContentEditableFalse:_(b,0),isAfterContentEditableFalse:_(b,-1),normalize
Range:y}}),r(oe,[_,U,$,ie,h,z],function(e,t,n,r,i,o){function a(e,t){for(var n=[];e&&e!=t;)n.push(e),e=e.parentNode;return n}function s(e,t){return e.hasChildNodes()&&t<e.childNodes.length?e.childNodes[t]:null}function l(e,t){if(m(e)){if(v(t.previousSibling)&&!f(t.previousSibling))return n.before(t);if(f(t))return n(t,0)}if(g(e)){if(v(t.nextSibling)&&!f(t.nextSibling))return n.after(t);if(f(t))return n(t,t.data.length)}return g(e)?h(t)?n.before(t):n.after(t):n.before(t)}function u(t,i){var o;return!!e.isBr(t)&&(o=c(1,n.after(t),i),!!o&&!r.isInSameBlock(n.before(t),n.before(o),i))}function c(e,t,h){var C,x,w,E,N,_,S;if(!p(h)||!t)return null;if(S=t,C=S.container(),x=S.offset(),f(C)){if(g(e)&&x>0)return n(C,--x);if(m(e)&&x<C.length)return n(C,++x);w=C}else{if(g(e)&&x>0&&(E=s(C,x-1),v(E)))return!y(E)&&(N=r.findNode(E,e,b,E))?f(N)?n(N,N.data.length):n.after(N):f(E)?n(E,E.data.length):n.bef
ore(E);if(m(e)&&x<C.childNodes.length&&(E=s(C,x),v(E)))return u(E,h)?c(e,n.after(E),h):!y(E)&&(N=r.findNode(E,e,b,E))?f(N)?n(N,0):n.before(N):f(E)?n(E,0):n.after(E);w=S.getNode()}return(m(e)&&S.isAtEnd()||g(e)&&S.isAtStart())&&(w=r.findNode(w,e,o.constant(!0),h,!0),b(w))?l(e,w):(E=r.findNode(w,e,b,h),_=i.last(i.filter(a(C,h),d)),!_||E&&_.contains(E)?E?l(e,E):null:S=m(e)?n.after(_):n.before(_))}var d=e.isContentEditableFalse,f=e.isText,p=e.isElement,h=e.isBr,m=r.isForwards,g=r.isBackwards,v=t.isCaretCandidate,y=t.isAtomic,b=t.isEditableCaretCandidate;return function(e){return{next:function(t){return c(1,t,e)},prev:function(t){return c(-1,t,e)}}}}),r(ae,[m,oe,$],function(e,t,n){var r=function(e){var t=e.firstChild,n=e.lastChild;return t&&"meta"===t.name&&(t=t.next),n&&"mce_marker"===n.attr("id")&&(n=n.prev),!(!t||t!==n)&&("ul"===t.name||"ol&qu
ot;===t.name)},i=function(e){var t=e.firstChild,n=e.lastChild;return t&&"META"===t.nodeName&&t.parentNode.removeChild(t),n&&"mce_marker"===n.id&&n.parentNode.removeChild(n),e},o=function(e,t,n){var r=t.serialize(n),o=e.createFragment(r);return i(o)},a=function(t){return e.grep(t.childNodes,function(e){return"LI"===e.nodeName})},s=function(e){return!e.firstChild},l=function(e){return e.length>0&&s(e[e.length-1])?e.slice(0,-1):e},u=function(e,t){var n=e.getParent(t,e.isBlock);return n&&"LI"===n.nodeName?n:null},c=function(e,t){return!!u(e,t)},d=function(e,t){var n=t.cloneRange(),r=t.cloneRange();return n.setStartBefore(e),r.setEndAfter(e),[n.cloneContents(),r.cloneContents()]},f=function(e,r){var i=n.before(e),o=new t(r),a=o.next(i);return a?a.toRange():null},p=function(e,r){var i=n.after(e),o=new t(r),a=o.prev(i);return a?a.toRange():null},h=function(t,n,r,i){var o=d(t,i),a=t.parentNode;return
a.insertBefore(o[0],t),e.each(n,function(e){a.insertBefore(e,t)}),a.insertBefore(o[1],t),a.removeChild(t),p(n[n.length-1],r)},m=function(t,n,r){var i=t.parentNode;return e.each(n,function(e){i.insertBefore(e,t)}),f(t,r)},g=function(e,t,n,r){return r.insertAfter(t.reverse(),e),p(t[0],n)},v=function(e,r,i,s){var c=o(r,e,s),d=u(r,i.startContainer),f=l(a(c.firstChild)),p=1,v=2,y=r.getRoot(),b=function(e){var o=n.fromRangeStart(i),a=new t(r.getRoot()),s=e===p?a.prev(o):a.next(o);return!s||u(r,s.getNode())!==d};return b(p)?m(d,f,y):b(v)?g(d,f,y,r):h(d,f,y,i)};return{isListFragment:r,insertAtCaret:v,isParentBlockLi:c,trimListItems:l,listItems:a}}),r(se,[d,m,P,oe,$,X,_,ae],function(e,t,n,r,i,o,a,s){var l=a.matchNodeNames("td th"),u=function(e,t,n){if("all"===n.getAttribute("data-mce-bogus"))n.parentNode.insertBefore(e.dom.createFragment(t),n);else{var r=n.firstChild,i=n.lastChild;!r||r===i&&"BR"===r.nodeName?e.dom.setHTML(n,t):e.selection.setC
ontent(t)}},c=function(a,c,d){function f(e){function t(e){return r[e]&&3==r[e].nodeType}var n,r,i;return n=L.getRng(!0),r=n.startContainer,i=n.startOffset,3==r.nodeType&&(i>0?e=e.replace(/^ /," "):t("previousSibling")||(e=e.replace(/^ /," ")),i<r.length?e=e.replace(/ (<br>|)$/," "):t("nextSibling")||(e=e.replace(/( | )(<br>|)$/," "))),e}function p(){var e,t,n;e=L.getRng(!0),t=e.startContainer,n=e.startOffset,3==t.nodeType&&e.collapsed&&("\xa0"===t.data[n]?(t.deleteData(n,1),/[\u00a0| ]$/.test(c)||(c+=" ")):"\xa0"===t.data[n-1]&&(t.deleteData(n-1,1),/[\u00a0| ]$/.test(c)||(c=" "+c)))}function h(){if(B){var e=a.getBody(),n=new o(M);t.each(M.select("*[data-mce-fragment]"),function(t){for(var r=t.parentNode;r&&r!=e;r=r.parentNode)D[t.nodeName.toLowerCase()]&&n.c
ompare(r,t)&&M.remove(t,!0)})}}function m(e){for(var t=e;t=t.walk();)1===t.type&&t.attr("data-mce-fragment","1")}function g(e){t.each(e.getElementsByTagName("*"),function(e){e.removeAttribute("data-mce-fragment")})}function v(e){return!!e.getAttribute("data-mce-fragment")}function y(e){return e&&!a.schema.getShortEndedElements()[e.nodeName]}function b(t){function n(e){for(var t=a.getBody();e&&e!==t;e=e.parentNode)if("false"===a.dom.getContentEditable(e))return e;return null}function o(e){var t=i.fromRangeStart(e),n=new r(a.getBody());if(t=n.next(t))return t.toRange()}var s,u,c;if(t){if(L.scrollIntoView(t),s=n(t))return M.remove(t),void L.select(s);k=M.createRng(),T=t.previousSibling,T&&3==T.nodeType?(k.setStart(T,T.nodeValue.length),e.ie||(R=t.nextSibling,R&&3==R.nodeType&&(T.appendData(R.data),R.parentNode.removeChild(R)))):(k.setStartBefore(t),k.setEndBefore(t)),u=M.
getParent(t,M.isBlock),M.remove(t),u&&M.isEmpty(u)&&(a.$(u).empty(),k.setStart(u,0),k.setEnd(u,0),l(u)||v(u)||!(c=o(k))?M.add(u,M.create("br",{"data-mce-bogus":"1"})):(k=c,M.remove(u))),L.setRng(k)}}var C,x,w,E,N,_,S,k,T,R,A,B,D=a.schema.getTextInlineElements(),L=a.selection,M=a.dom;/^ | $/.test(c)&&(c=f(c)),C=a.parser,B=d.merge,x=new n({validate:a.settings.validate},a.schema),A='<span id="mce_marker" data-mce-type="bookmark">​</span>',_={content:c,format:"html",selection:!0},a.fire("BeforeSetContent",_),c=_.content,c.indexOf("{$caret}")==-1&&(c+="{$caret}"),c=c.replace(/\{\$caret\}/,A),k=L.getRng();var P=k.startContainer||(k.parentElement?k.parentElement():null),O=a.getBody();P===O&&L.isCollapsed()&&M.isBlock(O.firstChild)&&y(O.firstChild)&&M.isEmpty(O.firstChild)&&(k=M.createRng(),k.setS
tart(O.firstChild,0),k.setEnd(O.firstChild,0),L.setRng(k)),L.isCollapsed()||(a.selection.setRng(a.selection.getRng()),a.getDoc().execCommand("Delete",!1,null),p()),w=L.getNode();var H={context:w.nodeName.toLowerCase(),data:d.data};if(N=C.parse(c,H),d.paste===!0&&s.isListFragment(N)&&s.isParentBlockLi(M,w))return k=s.insertAtCaret(x,M,a.selection.getRng(!0),N),a.selection.setRng(k),void a.fire("SetContent",_);if(m(N),T=N.lastChild,"mce_marker"==T.attr("id"))for(S=T,T=T.prev;T;T=T.walk(!0))if(3==T.type||!M.isBlock(T.name)){a.schema.isValidChild(T.parent.name,"span")&&T.parent.insert(S,T,"br"===T.name);break}if(a._selectionOverrides.showBlockCaretContainer(w),H.invalid){for(L.setContent(A),w=L.getNode(),E=a.getBody(),9==w.nodeType?w=T=E:T=w;T!==E;)w=T,T=T.parentNode;c=w==E?E.innerHTML:M.getOuterHTML(w),c=x.serialize(C.parse(c.replace(/<span (id="mce_marker"|id=mce_marker).+?<\/span>/i
,function(){return x.serialize(N)}))),w==E?M.setHTML(E,c):M.setOuterHTML(w,c)}else c=x.serialize(N),u(a,c,w);h(),b(M.get("mce_marker")),g(a.getBody()),a.fire("SetContent",_),a.addVisual()},d=function(e){var n;return"string"!=typeof e?(n=t.extend({paste:e.paste,data:{paste:e.paste}},e),{content:e.content,details:n}):{content:e,details:{}}},f=function(e,t){var n=d(t);c(e,n.content,n.details)};return{insertAtCaret:f}}),r(le,[d,m,T,y,se,_],function(e,n,r,i,o,a){var s=n.each,l=n.extend,u=n.map,c=n.inArray,d=n.explode,f=e.ie&&e.ie<11,p=!0,h=!1;return function(n){function m(e,t,r,i){var o,a,l=0;if(/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint)$/.test(e)||i&&i.skip_focus||n.focus(),i=n.fire("BeforeExecCommand",{command:e,ui:t,value:r}),i.isDefaultPrevented())return!1;if(a=e.toLowerCase(),o=D.exec[a])return o(a,t,r),n.fire("ExecCommand",{command:e,ui:t,value:r}),!0;if(s(n.plugins,function(i){if(i.execComma
nd&&i.execCommand(e,t,r))return n.fire("ExecCommand",{command:e,ui:t,value:r}),l=!0,!1}),l)return l;if(n.theme&&n.theme.execCommand&&n.theme.execCommand(e,t,r))return n.fire("ExecCommand",{command:e,ui:t,value:r}),!0;try{l=n.getDoc().execCommand(e,t,r)}catch(u){}return!!l&&(n.fire("ExecCommand",{command:e,ui:t,value:r}),!0)}function g(e){var t;if(!n.quirks.isHidden()){if(e=e.toLowerCase(),t=D.state[e])return t(e);try{return n.getDoc().queryCommandState(e)}catch(r){}return!1}}function v(e){var t;if(!n.quirks.isHidden()){if(e=e.toLowerCase(),t=D.value[e])return t(e);try{return n.getDoc().queryCommandValue(e)}catch(r){}}}function y(e,t){t=t||"exec",s(e,function(e,n){s(n.toLowerCase().split(","),function(n){D[t][n]=e})})}function b(e,t,r){e=e.toLowerCase(),D.exec[e]=function(e,i,o,a){return t.call(r||n,i,o,a)}}function C(e){if(e=e.toLowerCase(),D.exec[e])return!0;try{return n.getDoc().queryCommandSupported
(e)}catch(t){}return!1}function x(e,t,r){e=e.toLowerCase(),D.state[e]=function(){return t.call(r||n)}}function w(e,t,r){e=e.toLowerCase(),D.value[e]=function(){return t.call(r||n)}}function E(e){return e=e.toLowerCase(),!!D.exec[e]}function N(e,r,i){return r===t&&(r=h),i===t&&(i=null),n.getDoc().execCommand(e,r,i)}function _(e){return B.match(e)}function S(e,r){B.toggle(e,r?{value:r}:t),n.nodeChanged()}function k(e){M=A.getBookmark(e)}function T(){A.moveToBookmark(M)}var R,A,B,D={state:{},exec:{},value:{}},L=n.settings,M;n.on("PreInit",function(){R=n.dom,A=n.selection,L=n.settings,B=n.formatter}),l(this,{execCommand:m,queryCommandState:g,queryCommandValue:v,queryCommandSupported:C,addCommands:y,addCommand:b,addQueryStateHandler:x,addQueryValueHandler:w,hasCustomCommand:E}),y({"mceResetDesignMode,mceBeginUndoLevel":function(){},"mceEndUndoLevel,mceAddUndoLevel":function(){n.undoManager.add()},"Cut,Copy,Paste":function(t){var r=n
.getDoc(),i;try{N(t)}catch(o){i=p}if("paste"!==t||r.queryCommandEnabled(t)||(i=!0),i||!r.queryCommandSupported(t)){var a=n.translate("Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X/C/V keyboard shortcuts instead.");e.mac&&(a=a.replace(/Ctrl\+/g,"\u2318+")),n.notificationManager.open({text:a,type:"error"})}},unlink:function(){if(A.isCollapsed()){var e=n.dom.getParent(n.selection.getStart(),"a");return void(e&&n.dom.remove(e,!0))}B.remove("link")},"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull,JustifyNone":function(e){var t=e.substring(7);"full"==t&&(t="justify"),s("left,center,right,justify".split(","),function(e){t!=e&&B.remove("align"+e)}),"none"!=t&&S("align"+t)},"InsertUnorderedList,InsertOrderedList":function(e){var t,n;N(e),t=R.getParent(A.getNode(),&
quot;ol,ul"),t&&(n=t.parentNode,/^(H[1-6]|P|ADDRESS|PRE)$/.test(n.nodeName)&&(k(),R.split(n,t),T()))},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(e){S(e)},"ForeColor,HiliteColor,FontName":function(e,t,n){S(e,n)},FontSize:function(e,t,n){var r,i;n>=1&&n<=7&&(i=d(L.font_size_style_values),r=d(L.font_size_classes),n=r?r[n-1]||n:i[n-1]||n),S(e,n)},RemoveFormat:function(e){B.remove(e)},mceBlockQuote:function(){S("blockquote")},FormatBlock:function(e,t,n){return S(n||"p")},mceCleanup:function(){var e=A.getBookmark();n.setContent(n.getContent({cleanup:p}),{cleanup:p}),A.moveToBookmark(e)},mceRemoveNode:function(e,t,r){var i=r||A.getNode();i!=n.getBody()&&(k(),n.dom.remove(i,p),T())},mceSelectNodeDepth:function(e,t,r){var i=0;R.getParent(A.getNode(),function(e){if(1==e.nodeType&&i++==r)return A.select(e),h},n.getBody())},mceSelectNode:function(e,t,n){A.select(n)},mceIn
sertContent:function(e,t,r){o.insertAtCaret(n,r)},mceInsertRawHTML:function(e,t,r){A.setContent("tiny_mce_marker"),n.setContent(n.getContent().replace(/tiny_mce_marker/g,function(){return r}))},mceToggleFormat:function(e,t,n){S(n)},mceSetContent:function(e,t,r){n.setContent(r)},"Indent,Outdent":function(e){var t,r,i;t=L.indentation,r=/[a-z%]+$/i.exec(t),t=parseInt(t,10),g("InsertUnorderedList")||g("InsertOrderedList")?N(e):(L.forced_root_block||R.getParent(A.getNode(),R.isBlock)||B.apply("div"),s(A.getSelectedBlocks(),function(o){if("false"!==R.getContentEditable(o)&&"LI"!==o.nodeName){var a=n.getParam("indent_use_margin",!1)?"margin":"padding";a="TABLE"===o.nodeName?"margin":a,a+="rtl"==R.getStyle(o,"direction",!0)?"Right":"Left","outdent"==e?(i=Math.max(0,parseInt(o.style[a]||0,10)-t),R.setStyle(o,a,i?i+r:
"")):(i=parseInt(o.style[a]||0,10)+t+r,R.setStyle(o,a,i))}}))},mceRepaint:function(){},InsertHorizontalRule:function(){n.execCommand("mceInsertContent",!1,"<hr />")},mceToggleVisualAid:function(){n.hasVisual=!n.hasVisual,n.addVisual()},mceReplaceContent:function(e,t,r){n.execCommand("mceInsertContent",!1,r.replace(/\{\$selection\}/g,A.getContent({format:"text"})))},mceInsertLink:function(e,t,n){var r;"string"==typeof n&&(n={href:n}),r=R.getParent(A.getNode(),"a"),n.href=n.href.replace(" ","%20"),r&&n.href||B.remove("link"),n.href&&B.apply("link",n,r)},selectAll:function(){var e=R.getRoot(),t;if(A.getRng().setStart){var n=R.getParent(A.getStart(),a.isContentEditableTrue);n&&(t=R.createRng(),t.selectNodeContents(n),A.setRng(t))}else t=A.getRng(),t.item||(t.moveToElementText(e),t.select())},"delete":function(){N("Delete"
);var e=n.getBody();R.isEmpty(e)&&(n.setContent(""),e.firstChild&&R.isBlock(e.firstChild)?n.selection.setCursorLocation(e.firstChild,0):n.selection.setCursorLocation(e,0))},mceNewDocument:function(){n.setContent("")},InsertLineBreak:function(e,t,o){function a(){for(var e=new i(m,v),t,r=n.schema.getNonEmptyElements();t=e.next();)if(r[t.nodeName.toLowerCase()]||t.length>0)return!0}var s=o,l,u,c,d=A.getRng(!0);new r(R).normalize(d);var h=d.startOffset,m=d.startContainer;if(1==m.nodeType&&m.hasChildNodes()){var g=h>m.childNodes.length-1;m=m.childNodes[Math.min(h,m.childNodes.length-1)]||m,h=g&&3==m.nodeType?m.nodeValue.length:0}var v=R.getParent(m,R.isBlock),y=v?v.nodeName.toUpperCase():"",b=v?R.getParent(v.parentNode,R.isBlock):null,C=b?b.nodeName.toUpperCase():"",x=s&&s.ctrlKey;"LI"!=C||x||(v=b,y=C),m&&3==m.nodeType&&h>=m.nodeValue.length&&(f||a()||(l=R.create(&qu
ot;br"),d.insertNode(l),d.setStartAfter(l),d.setEndAfter(l),u=!0)),l=R.create("br"),d.insertNode(l);var w=R.doc.documentMode;return f&&"PRE"==y&&(!w||w<8)&&l.parentNode.insertBefore(R.doc.createTextNode("\r"),l),c=R.create("span",{}," "),l.parentNode.insertBefore(c,l),A.scrollIntoView(c),R.remove(c),u?(d.setStartBefore(l),d.setEndBefore(l)):(d.setStartAfter(l),d.setEndAfter(l)),A.setRng(d),n.undoManager.add(),p}}),y({"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(e){var t="align"+e.substring(7),n=A.isCollapsed()?[R.getParent(A.getNode(),R.isBlock)]:A.getSelectedBlocks(),r=u(n,function(e){return!!B.matchNode(e,t)});return c(r,p)!==-1},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(e){return _(e)},mceBlockQuote:function(){return _("blockquote")},Outdent:function(){var e;if(L.inline_styles){if((e=R.getParent(A.getStart()
,R.isBlock))&&parseInt(e.style.paddingLeft,10)>0)return p;if((e=R.getParent(A.getEnd(),R.isBlock))&&parseInt(e.style.paddingLeft,10)>0)return p}return g("InsertUnorderedList")||g("InsertOrderedList")||!L.inline_styles&&!!R.getParent(A.getNode(),"BLOCKQUOTE")},"InsertUnorderedList,InsertOrderedList":function(e){var t=R.getParent(A.getNode(),"ul,ol");return t&&("insertunorderedlist"===e&&"UL"===t.tagName||"insertorderedlist"===e&&"OL"===t.tagName)}},"state"),y({"FontSize,FontName":function(e){var t=0,n;return(n=R.getParent(A.getNode(),"span"))&&(t="fontsize"==e?n.style.fontSize:n.style.fontFamily.replace(/, /g,",").replace(/[\'\"]/g,"").toLowerCase()),t}},"value"),y({Undo:function(){n.undoManager.undo()},Redo:function(){n.undoManager.redo()}})}}),r(ue,[m],functi
on(e){function t(e,o){var a=this,s,l;if(e=r(e),o=a.settings=o||{},s=o.base_uri,/^([\w\-]+):([^\/]{2})/i.test(e)||/^\s*#/.test(e))return void(a.source=e);var u=0===e.indexOf("//");0!==e.indexOf("/")||u||(e=(s?s.protocol||"http":"http")+"://mce_host"+e),/^[\w\-]*:?\/\//.test(e)||(l=o.base_uri?o.base_uri.path:new t(location.href).directory,""===o.base_uri.protocol?e="//mce_host"+a.toAbsPath(l,e):(e=/([^#?]*)([#?]?.*)/.exec(e),e=(s&&s.protocol||"http")+"://mce_host"+a.toAbsPath(l,e[1])+e[2])),e=e.replace(/@@/g,"(mce_at)"),e=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(e),n(i,function(t,n){var r=e[n];r&&(r=r.replace(/\(mce_at\)/g,"@@")),a[t]=r}),s&&(a.protocol||(a.protocol=s.protocol),a.userInfo||(a.user
Info=s.userInfo),a.port||"mce_host"!==a.host||(a.port=s.port),a.host&&"mce_host"!==a.host||(a.host=s.host),a.source=""),u&&(a.protocol="")}var n=e.each,r=e.trim,i="source protocol authority userInfo user password host port relative path directory file query anchor".split(" "),o={ftp:21,http:80,https:443,mailto:25};return t.prototype={setPath:function(e){var t=this;e=/^(.*?)\/?(\w+)?$/.exec(e),t.path=e[0],t.directory=e[1],t.file=e[2],t.source="",t.getURI()},toRelative:function(e){var n=this,r;if("./"===e)return e;if(e=new t(e,{base_uri:n}),"mce_host"!=e.host&&n.host!=e.host&&e.host||n.port!=e.port||n.protocol!=e.protocol&&""!==e.protocol)return e.getURI();var i=n.getURI(),o=e.getURI();return i==o||"/"==i.charAt(i.length-1)&&i.substr(0,i.length-1)==o?i:(r=n.toRelPath(n.path,e.path),e.query&&(r+="?"+e.query),e.an
chor&&(r+="#"+e.anchor),r)},toAbsolute:function(e,n){return e=new t(e,{base_uri:this}),e.getURI(n&&this.isSameOrigin(e))},isSameOrigin:function(e){if(this.host==e.host&&this.protocol==e.protocol){if(this.port==e.port)return!0;var t=o[this.protocol];if(t&&(this.port||t)==(e.port||t))return!0}return!1},toRelPath:function(e,t){var n,r=0,i="",o,a;if(e=e.substring(0,e.lastIndexOf("/")),e=e.split("/"),n=t.split("/"),e.length>=n.length)for(o=0,a=e.length;o<a;o++)if(o>=n.length||e[o]!=n[o]){r=o+1;break}if(e.length<n.length)for(o=0,a=n.length;o<a;o++)if(o>=e.length||e[o]!=n[o]){r=o+1;break}if(1===r)return t;for(o=0,a=e.length-(r-1);o<a;o++)i+="../";for(o=r-1,a=n.length;o<a;o++)i+=o!=r-1?"/"+n[o]:n[o];return i},toAbsPath:function(e,t){var r,i=0,o=[],a,s;for(a=/\/$/.test(t)?"/":"",e=e.split("/"),t=t.split("/"),n(e,function(e){e&am
p;&o.push(e)}),e=o,r=t.length-1,o=[];r>=0;r--)0!==t[r].length&&"."!==t[r]&&(".."!==t[r]?i>0?i--:o.push(t[r]):i++);return r=e.length-i,s=r<=0?o.reverse().join("/"):e.slice(0,r).join("/")+"/"+o.reverse().join("/"),0!==s.indexOf("/")&&(s="/"+s),a&&s.lastIndexOf("/")!==s.length-1&&(s+=a),s},getURI:function(e){var t,n=this;return n.source&&!e||(t="",e||(t+=n.protocol?n.protocol+"://":"//",n.userInfo&&(t+=n.userInfo+"@"),n.host&&(t+=n.host),n.port&&(t+=":"+n.port)),n.path&&(t+=n.path),n.query&&(t+="?"+n.query),n.anchor&&(t+="#"+n.anchor),n.source=t),n.source}},t.parseDataUri=function(e){var t,n;return e=decodeURIComponent(e).split(","),n=/data:([^;]+)/.exec(e[0]),n&&(t=n[1]),{type:t,data:e[1]}},t.getDocumen
tBaseUrl=function(e){var t;return t=0!==e.protocol.indexOf("http")&&"file:"!==e.protocol?e.href:e.protocol+"//"+e.host+e.pathname,/^[^:]+:\/\/\/?[^\/]+\//.test(t)&&(t=t.replace(/[\?#].*$/,"").replace(/[\/\\][^\/]+$/,""),/[\/\\]$/.test(t)||(t+="/")),t},t}),r(ce,[m],function(e){function t(){}var n=e.each,r=e.extend,i,o;return t.extend=i=function(e){function t(){var e,t,n,r=this;if(!o&&(r.init&&r.init.apply(r,arguments),t=r.Mixins))for(e=t.length;e--;)n=t[e],n.init&&n.init.apply(r,arguments)}function a(){return this}function s(e,t){return function(){var n=this,r=n._super,i;return n._super=u[e],i=t.apply(n,arguments),n._super=r,i}}var l=this,u=l.prototype,c,d,f;o=!0,c=new l,o=!1,e.Mixins&&(n(e.Mixins,function(t){for(var n in t)"init"!==n&&(e[n]=t[n])}),u.Mixins&&(e.Mixins=u.Mixins.concat(e.Mixins))),e.Methods&&n(e.Methods.split(","),func
tion(t){e[t]=a}),e.Properties&&n(e.Properties.split(","),function(t){var n="_"+t;e[t]=function(e){var t=this,r;return e!==r?(t[n]=e,t):t[n]}}),e.Statics&&n(e.Statics,function(e,n){t[n]=e}),e.Defaults&&u.Defaults&&(e.Defaults=r({},u.Defaults,e.Defaults));for(d in e)f=e[d],"function"==typeof f&&u[d]?c[d]=s(d,f):c[d]=f;return t.prototype=c,t.constructor=t,t.extend=i,t},t}),r(de,[m],function(e){function t(t){function n(){return!1}function r(){return!0}function i(e,i){var o,s,l,u;if(e=e.toLowerCase(),i=i||{},i.type=e,i.target||(i.target=c),i.preventDefault||(i.preventDefault=function(){i.isDefaultPrevented=r},i.stopPropagation=function(){i.isPropagationStopped=r},i.stopImmediatePropagation=function(){i.isImmediatePropagationStopped=r},i.isDefaultPrevented=n,i.isPropagationStopped=n,i.isImmediatePropagationStopped=n),t.beforeFire&&t.beforeFire(i),o=d[e])for(s=0,l=o.length;s<l;s++){if(u=o[s],u.once&&a(
e,u.func),i.isImmediatePropagationStopped())return i.stopPropagation(),i;if(u.func.call(c,i)===!1)return i.preventDefault(),i}return i}function o(t,r,i,o){var a,s,l;if(r===!1&&(r=n),r)for(r={func:r},o&&e.extend(r,o),s=t.toLowerCase().split(" "),l=s.length;l--;)t=s[l],a=d[t],a||(a=d[t]=[],f(t,!0)),i?a.unshift(r):a.push(r);return u}function a(e,t){var n,r,i,o,a;if(e)for(o=e.toLowerCase().split(" "),n=o.length;n--;){if(e=o[n],r=d[e],!e){for(i in d)f(i,!1),delete d[i];return u}if(r){if(t)for(a=r.length;a--;)r[a].func===t&&(r=r.slice(0,a).concat(r.slice(a+1)),d[e]=r);else r.length=0;r.length||(f(e,!1),delete d[e])}}else{for(e in d)f(e,!1);d={}}return u}function s(e,t,n){return o(e,t,n,{once:!0})}function l(e){return e=e.toLowerCase(),!(!d[e]||0===d[e].length)}var u=this,c,d={},f;t=t||{},c=t.scope||u,f=t.toggleEvent||n,u.fire=i,u.on=o,u.off=a,u.once=s,u.has=l}var n=e.makeMap("focus blur focusin focusout click dblclick mousedown mouseup mous
emove mouseover beforepaste paste cut copy selectionchange mouseout mouseenter mouseleave wheel keydown keypress keyup input contextmenu dragstart dragend dragover draggesture dragdrop drop drag submit compositionstart compositionend compositionupdate touchstart touchmove touchend"," ");return t.isNative=function(e){return!!n[e.toLowerCase()]},t}),r(fe,[],function(){function e(e){this.create=e.create}return e.create=function(t,n){return new e({create:function(e,r){function i(t){e.set(r,t.value)}function o(e){t.set(n,e.value)}var a;return e.on("change:"+r,o),t.on("change:"+n,i),a=e._bindings,a||(a=e._bindings=[],e.on("destroy",function(){for(var e=a.length;e--;)a[e]()})),a.push(function(){t.off("change:"+n,i)}),t.get(n)}})},e}),r(pe,[de],function(e){function t(t){return t._eventDispatcher||(t._eventDispatcher=new e({scope:t,toggleEvent:function(n,r){e.isNative(n)&&t.toggleNativeEvent&&t.toggleNativeEvent(n,r)}})),
t._eventDispatcher}return{fire:function(e,n,r){var i=this;if(i.removed&&"remove"!==e)return n;if(n=t(i).fire(e,n,r),r!==!1&&i.parent)for(var o=i.parent();o&&!n.isPropagationStopped();)o.fire(e,n,!1),o=o.parent();return n},on:function(e,n,r){return t(this).on(e,n,r)},off:function(e,n){return t(this).off(e,n)},once:function(e,n){return t(this).once(e,n)},hasEventListeners:function(e){return t(this).has(e)}}}),r(he,[fe,pe,ce,m],function(e,t,n,r){function i(e){return e.nodeType>0}function o(e,t){var n,a;if(e===t)return!0;if(null===e||null===t)return e===t;if("object"!=typeof e||"object"!=typeof t)return e===t;if(r.isArray(t)){if(e.length!==t.length)return!1;for(n=e.length;n--;)if(!o(e[n],t[n]))return!1}if(i(e)||i(t))return e===t;a={};for(n in t){if(!o(e[n],t[n]))return!1;a[n]=!0}for(n in e)if(!a[n]&&!o(e[n],t[n]))return!1;return!0}return n.extend({Mixins:[t],init:function(t){var n,r;t=t||{};for(n in t)r=t[n],r instanceof e
&&(t[n]=r.create(this,n));this.data=t},set:function(t,n){var r,i,a=this.data[t];if(n instanceof e&&(n=n.create(this,t)),"object"==typeof t){for(r in t)this.set(r,t[r]);return this}return o(a,n)||(this.data[t]=n,i={target:this,name:t,value:n,oldValue:a},this.fire("change:"+t,i),this.fire("change",i)),this},get:function(e){return this.data[e]},has:function(e){return e in this.data},bind:function(t){return e.create(this,t)},destroy:function(){this.fire("destroy")}})}),r(me,[ce],function(e){function t(e){for(var t=[],n=e.length,r;n--;)r=e[n],r.__checked||(t.push(r),r.__checked=1);for(n=t.length;n--;)delete t[n].__checked;return t}var n=/^([\w\\*]+)?(?:#([\w\-\\]+))?(?:\.([\w\\\.]+))?(?:\[\@?([\w\\]+)([\^\$\*!~]?=)([\w\\]+)\])?(?:\:(.+))?/i,r=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,i=/^\s*|\s*$/g,o,a=e.extend({init
:function(e){function t(e){if(e)return e=e.toLowerCase(),function(t){return"*"===e||t.type===e}}function o(e){if(e)return function(t){return t._name===e}}function a(e){if(e)return e=e.split("."),function(t){for(var n=e.length;n--;)if(!t.classes.contains(e[n]))return!1;return!0}}function s(e,t,n){if(e)return function(r){var i=r[e]?r[e]():"";return t?"="===t?i===n:"*="===t?i.indexOf(n)>=0:"~="===t?(" "+i+" ").indexOf(" "+n+" ")>=0:"!="===t?i!=n:"^="===t?0===i.indexOf(n):"$="===t&&i.substr(i.length-n.length)===n:!!n}}function l(e){var t;if(e)return e=/(?:not\((.+)\))|(.+)/i.exec(e),e[1]?(t=c(e[1],[]),function(e){return!d(e,t)}):(e=e[2],function(t,n,r){return"first"===e?0===n:"last"===e?n===r-1:"even"===e?n%2===0:"odd"===e?n%2===1:!!t[e]&&t[e]()})}function u(e,r,u){function c(e){e&&r.push(e
)}var d;return d=n.exec(e.replace(i,"")),c(t(d[1])),c(o(d[2])),c(a(d[3])),c(s(d[4],d[5],d[6])),c(l(d[7])),r.pseudo=!!d[7],r.direct=u,r}function c(e,t){var n=[],i,o,a;do if(r.exec(""),o=r.exec(e),o&&(e=o[3],n.push(o[1]),o[2])){i=o[3];break}while(o);for(i&&c(i,t),e=[],a=0;a<n.length;a++)">"!=n[a]&&e.push(u(n[a],[],">"===n[a-1]));return t.push(e),t}var d=this.match;this._selectors=c(e,[])},match:function(e,t){var n,r,i,o,a,s,l,u,c,d,f,p,h;for(t=t||this._selectors,n=0,r=t.length;n<r;n++){for(a=t[n],o=a.length,h=e,p=0,i=o-1;i>=0;i--)for(u=a[i];h;){if(u.pseudo)for(f=h.parent().items(),c=d=f.length;c--&&f[c]!==h;);for(s=0,l=u.length;s<l;s++)if(!u[s](h,c,d)){s=l+1;break}if(s===l){p++;break}if(i===o-1)break;h=h.parent()}if(p===o)return!0}return!1},find:function(e){function n(e,t,i){var o,a,s,l,u,c=t[i];for(o=0,a=e.length;o<a;o++){for(u=e[o],s=0,l=c.length;s<l;s++)if(!c[s](u,o,a)){s=l+1;break}if(s=
==l)i==t.length-1?r.push(u):u.items&&n(u.items(),t,i+1);else if(c.direct)return;u.items&&n(u.items(),t,i)}}var r=[],i,s,l=this._selectors;if(e.items){for(i=0,s=l.length;i<s;i++)n(e.items(),l[i],0);s>1&&(r=t(r))}return o||(o=a.Collection),new o(r)}});return a}),r(ge,[m,me,ce],function(e,t,n){var r,i,o=Array.prototype.push,a=Array.prototype.slice;return i={length:0,init:function(e){e&&this.add(e)},add:function(t){var n=this;return e.isArray(t)?o.apply(n,t):t instanceof r?n.add(t.toArray()):o.call(n,t),n},set:function(e){var t=this,n=t.length,r;for(t.length=0,t.add(e),r=t.length;r<n;r++)delete t[r];return t},filter:function(e){var n=this,i,o,a=[],s,l;for("string"==typeof e?(e=new t(e),l=function(t){return e.match(t)}):l=e,i=0,o=n.length;i<o;i++)s=n[i],l(s)&&a.push(s);return new r(a)},slice:function(){return new r(a.apply(this,arguments))},eq:function(e){return e===-1?this.slice(e):this.slice(e,+e+1)},each:function(t){return
e.each(this,t),this},toArray:function(){return e.toArray(this)},indexOf:function(e){for(var t=this,n=t.length;n--&&t[n]!==e;);return n},reverse:function(){return new r(e.toArray(this).reverse())},hasClass:function(e){return!!this[0]&&this[0].classes.contains(e)},prop:function(e,t){var n=this,r,i;return t!==r?(n.each(function(n){n[e]&&n[e](t)}),n):(i=n[0],i&&i[e]?i[e]():void 0)},exec:function(t){var n=this,r=e.toArray(arguments).slice(1);return n.each(function(e){e[t]&&e[t].apply(e,r)}),n},remove:function(){for(var e=this.length;e--;)this[e].remove();return this},addClass:function(e){return this.each(function(t){t.classes.add(e)})},removeClass:function(e){return this.each(function(t){t.classes.remove(e)})}},e.each("fire on off show hide append prepend before after reflow".split(" "),function(t){i[t]=function(){var n=e.toArray(arguments);return this.each(function(e){t in e&&e[t].apply(e,n)}),this}}),e.each("text
name disabled active selected checked visible parent value data".split(" "),function(e){i[e]=function(t){return this.prop(e,t)}}),r=n.extend(i),t.Collection=r,r}),r(ve,[d,m,w],function(e,t,n){var r=0,i={id:function(){return"mceu_"+r++},create:function(e,r,i){var o=document.createElement(e);return n.DOM.setAttribs(o,r),"string"==typeof i?o.innerHTML=i:t.each(i,function(e){e.nodeType&&o.appendChild(e)}),o},createFragment:function(e){return n.DOM.createFragment(e)},getWindowSize:function(){return n.DOM.getViewPort()},getSize:function(e){var t,n;if(e.getBoundingClientRect){var r=e.getBoundingClientRect();t=Math.max(r.width||r.right-r.left,e.offsetWidth),n=Math.max(r.height||r.bottom-r.bottom,e.offsetHeight)}else t=e.offsetWidth,n=e.offsetHeight;return{width:t,height:n}},getPos:function(e,t){return n.DOM.getPos(e,t||i.getContainer())},getContainer:function(){return e.container?e.container:document.body},getViewPort:function(e){return n.DOM.getVi
ewPort(e)},get:function(e){return document.getElementById(e)},addClass:function(e,t){return n.DOM.addClass(e,t)},removeClass:function(e,t){return n.DOM.removeClass(e,t)},hasClass:function(e,t){return n.DOM.hasClass(e,t)},toggleClass:function(e,t,r){return n.DOM.toggleClass(e,t,r)},css:function(e,t,r){return n.DOM.setStyle(e,t,r)},getRuntimeStyle:function(e,t){return n.DOM.getStyle(e,t,!0)},on:function(e,t,r,i){
-return n.DOM.bind(e,t,r,i)},off:function(e,t,r){return n.DOM.unbind(e,t,r)},fire:function(e,t,r){return n.DOM.fire(e,t,r)},innerHtml:function(e,t){n.DOM.setHTML(e,t)}};return i}),r(ye,[],function(){return{parseBox:function(e){var t,n=10;if(e)return"number"==typeof e?(e=e||0,{top:e,left:e,bottom:e,right:e}):(e=e.split(" "),t=e.length,1===t?e[1]=e[2]=e[3]=e[0]:2===t?(e[2]=e[0],e[3]=e[1]):3===t&&(e[3]=e[1]),{top:parseInt(e[0],n)||0,right:parseInt(e[1],n)||0,bottom:parseInt(e[2],n)||0,left:parseInt(e[3],n)||0})},measureBox:function(e,t){function n(t){var n=document.defaultView;return n?(t=t.replace(/[A-Z]/g,function(e){return"-"+e}),n.getComputedStyle(e,null).getPropertyValue(t)):e.currentStyle[t]}function r(e){var t=parseFloat(n(e),10);return isNaN(t)?0:t}return{top:r(t+"TopWidth"),right:r(t+"RightWidth"),bottom:r(t+"BottomWidth"),left:r(t+"LeftWidth")}}}}),r(be,[m],function(e){function t(){}function n(e){thi
s.cls=[],this.cls._map={},this.onchange=e||t,this.prefix=""}return e.extend(n.prototype,{add:function(e){return e&&!this.contains(e)&&(this.cls._map[e]=!0,this.cls.push(e),this._change()),this},remove:function(e){if(this.contains(e)){for(var t=0;t<this.cls.length&&this.cls[t]!==e;t++);this.cls.splice(t,1),delete this.cls._map[e],this._change()}return this},toggle:function(e,t){var n=this.contains(e);return n!==t&&(n?this.remove(e):this.add(e),this._change()),this},contains:function(e){return!!this.cls._map[e]},_change:function(){delete this.clsValue,this.onchange.call(this)}}),n.prototype.toString=function(){var e;if(this.clsValue)return this.clsValue;e="";for(var t=0;t<this.cls.length;t++)t>0&&(e+=" "),e+=this.prefix+this.cls[t];return e},n}),r(Ce,[c],function(e){var t={},n;return{add:function(r){var i=r.parent();if(i){if(!i._layout||i._layout.isNative())return;t[i._id]||(t[i._id]=i),n||(n=!0,e.requestAn
imationFrame(function(){var e,r;n=!1;for(e in t)r=t[e],r.state.get("rendered")&&r.reflow();t={}},document.body))}},remove:function(e){t[e._id]&&delete t[e._id]}}}),r(xe,[ce,m,de,he,ge,ve,g,ye,be,Ce],function(e,t,n,r,i,o,a,s,l,u){function c(e){return e._eventDispatcher||(e._eventDispatcher=new n({scope:e,toggleEvent:function(t,r){r&&n.isNative(t)&&(e._nativeEvents||(e._nativeEvents={}),e._nativeEvents[t]=!0,e.state.get("rendered")&&d(e))}})),e._eventDispatcher}function d(e){function t(t){var n=e.getParentCtrl(t.target);n&&n.fire(t.type,t)}function n(){var e=u._lastHoverCtrl;e&&(e.fire("mouseleave",{target:e.getEl()}),e.parents().each(function(e){e.fire("mouseleave",{target:e.getEl()})}),u._lastHoverCtrl=null)}function r(t){var n=e.getParentCtrl(t.target),r=u._lastHoverCtrl,i=0,o,a,s;if(n!==r){if(u._lastHoverCtrl=n,a=n.parents().toArray().reverse(),a.push(n),r){for(s=r.parents().toArray().r
everse(),s.push(r),i=0;i<s.length&&a[i]===s[i];i++);for(o=s.length-1;o>=i;o--)r=s[o],r.fire("mouseleave",{target:r.getEl()})}for(o=i;o<a.length;o++)n=a[o],n.fire("mouseenter",{target:n.getEl()})}}function i(t){t.preventDefault(),"mousewheel"==t.type?(t.deltaY=-.025*t.wheelDelta,t.wheelDeltaX&&(t.deltaX=-.025*t.wheelDeltaX)):(t.deltaX=0,t.deltaY=t.detail),t=e.fire("wheel",t)}var o,s,l,u,c,d;if(c=e._nativeEvents){for(l=e.parents().toArray(),l.unshift(e),o=0,s=l.length;!u&&o<s;o++)u=l[o]._eventsRoot;for(u||(u=l[l.length-1]||e),e._eventsRoot=u,s=o,o=0;o<s;o++)l[o]._eventsRoot=u;var h=u._delegates;h||(h=u._delegates={});for(d in c){if(!c)return!1;"wheel"!==d||p?("mouseenter"===d||"mouseleave"===d?u._hasMouseEnter||(a(u.getEl()).on("mouseleave",n).on("mouseover",r),u._hasMouseEnter=1):h[d]||(a(u.getEl()).on(d,t),h[d]=!0),c[d]=!1):f?a(e.getEl()).on("mousewhe
el",i):a(e.getEl()).on("DOMMouseScroll",i)}}}var f="onmousewheel"in document,p=!1,h="mce-",m,g=0,v={Statics:{classPrefix:h},isRtl:function(){return m.rtl},classPrefix:h,init:function(e){function n(e){var t;for(e=e.split(" "),t=0;t<e.length;t++)i.classes.add(e[t])}var i=this,o,u;i.settings=e=t.extend({},i.Defaults,e),i._id=e.id||"mceu_"+g++,i._aria={role:e.role},i._elmCache={},i.$=a,i.state=new r({visible:!0,active:!1,disabled:!1,value:""}),i.data=new r(e.data),i.classes=new l(function(){i.state.get("rendered")&&(i.getEl().className=this.toString())}),i.classes.prefix=i.classPrefix,o=e.classes,o&&(i.Defaults&&(u=i.Defaults.classes,u&&o!=u&&n(u)),n(o)),t.each("title text name visible disabled active value".split(" "),function(t){t in e&&i[t](e[t])}),i.on("click",function(){if(i.disabled())return!1}),i.settings=e,i.borderBox=s.parse
Box(e.border),i.paddingBox=s.parseBox(e.padding),i.marginBox=s.parseBox(e.margin),e.hidden&&i.hide()},Properties:"parent,name",getContainerElm:function(){return o.getContainer()},getParentCtrl:function(e){for(var t,n=this.getRoot().controlIdLookup;e&&n&&!(t=n[e.id]);)e=e.parentNode;return t},initLayoutRect:function(){var e=this,t=e.settings,n,r,i=e.getEl(),a,l,u,c,d,f,p,h;n=e.borderBox=e.borderBox||s.measureBox(i,"border"),e.paddingBox=e.paddingBox||s.measureBox(i,"padding"),e.marginBox=e.marginBox||s.measureBox(i,"margin"),h=o.getSize(i),f=t.minWidth,p=t.minHeight,u=f||h.width,c=p||h.height,a=t.width,l=t.height,d=t.autoResize,d="undefined"!=typeof d?d:!a&&!l,a=a||u,l=l||c;var m=n.left+n.right,g=n.top+n.bottom,v=t.maxWidth||65535,y=t.maxHeight||65535;return e._layoutRect=r={x:t.x||0,y:t.y||0,w:a,h:l,deltaW:m,deltaH:g,contentW:a-m,contentH:l-g,innerW:a-m,innerH:l-g,startMinWidth:f||0,startMinHeight:p||0
,minW:Math.min(u,v),minH:Math.min(c,y),maxW:v,maxH:y,autoResize:d,scrollW:0},e._lastLayoutRect={},r},layoutRect:function(e){var t=this,n=t._layoutRect,r,i,o,a,s,l;return n||(n=t.initLayoutRect()),e?(o=n.deltaW,a=n.deltaH,e.x!==s&&(n.x=e.x),e.y!==s&&(n.y=e.y),e.minW!==s&&(n.minW=e.minW),e.minH!==s&&(n.minH=e.minH),i=e.w,i!==s&&(i=i<n.minW?n.minW:i,i=i>n.maxW?n.maxW:i,n.w=i,n.innerW=i-o),i=e.h,i!==s&&(i=i<n.minH?n.minH:i,i=i>n.maxH?n.maxH:i,n.h=i,n.innerH=i-a),i=e.innerW,i!==s&&(i=i<n.minW-o?n.minW-o:i,i=i>n.maxW-o?n.maxW-o:i,n.innerW=i,n.w=i+o),i=e.innerH,i!==s&&(i=i<n.minH-a?n.minH-a:i,i=i>n.maxH-a?n.maxH-a:i,n.innerH=i,n.h=i+a),e.contentW!==s&&(n.contentW=e.contentW),e.contentH!==s&&(n.contentH=e.contentH),r=t._lastLayoutRect,r.x===n.x&&r.y===n.y&&r.w===n.w&&r.h===n.h||(l=m.repaintControls,l&&l.map&&!l.map[t._id]&&(l.push(t),l.map[t
._id]=!0),r.x=n.x,r.y=n.y,r.w=n.w,r.h=n.h),t):n},repaint:function(){var e=this,t,n,r,i,o,a,s,l,u,c;u=document.createRange?function(e){return e}:Math.round,t=e.getEl().style,i=e._layoutRect,l=e._lastRepaintRect||{},o=e.borderBox,a=o.left+o.right,s=o.top+o.bottom,i.x!==l.x&&(t.left=u(i.x)+"px",l.x=i.x),i.y!==l.y&&(t.top=u(i.y)+"px",l.y=i.y),i.w!==l.w&&(c=u(i.w-a),t.width=(c>=0?c:0)+"px",l.w=i.w),i.h!==l.h&&(c=u(i.h-s),t.height=(c>=0?c:0)+"px",l.h=i.h),e._hasBody&&i.innerW!==l.innerW&&(c=u(i.innerW),r=e.getEl("body"),r&&(n=r.style,n.width=(c>=0?c:0)+"px"),l.innerW=i.innerW),e._hasBody&&i.innerH!==l.innerH&&(c=u(i.innerH),r=r||e.getEl("body"),r&&(n=n||r.style,n.height=(c>=0?c:0)+"px"),l.innerH=i.innerH),e._lastRepaintRect=l,e.fire("repaint",{},!1)},updateLayoutRect:function(){var e=this;e.parent()._lastRect=
null,o.css(e.getEl(),{width:"",height:""}),e._layoutRect=e._lastRepaintRect=e._lastLayoutRect=null,e.initLayoutRect()},on:function(e,t){function n(e){var t,n;return"string"!=typeof e?e:function(i){return t||r.parentsAndSelf().each(function(r){var i=r.settings.callbacks;if(i&&(t=i[e]))return n=r,!1}),t?t.call(n,i):(i.action=e,void this.fire("execute",i))}}var r=this;return c(r).on(e,n(t)),r},off:function(e,t){return c(this).off(e,t),this},fire:function(e,t,n){var r=this;if(t=t||{},t.control||(t.control=r),t=c(r).fire(e,t),n!==!1&&r.parent)for(var i=r.parent();i&&!t.isPropagationStopped();)i.fire(e,t,!1),i=i.parent();return t},hasEventListeners:function(e){return c(this).has(e)},parents:function(e){var t=this,n,r=new i;for(n=t.parent();n;n=n.parent())r.add(n);return e&&(r=r.filter(e)),r},parentsAndSelf:function(e){return new i(this).add(this.parents(e))},next:function(){var e=this.parent().items();return e[e.index
Of(this)+1]},prev:function(){var e=this.parent().items();return e[e.indexOf(this)-1]},innerHtml:function(e){return this.$el.html(e),this},getEl:function(e){var t=e?this._id+"-"+e:this._id;return this._elmCache[t]||(this._elmCache[t]=a("#"+t)[0]),this._elmCache[t]},show:function(){return this.visible(!0)},hide:function(){return this.visible(!1)},focus:function(){try{this.getEl().focus()}catch(e){}return this},blur:function(){return this.getEl().blur(),this},aria:function(e,t){var n=this,r=n.getEl(n.ariaTarget);return"undefined"==typeof t?n._aria[e]:(n._aria[e]=t,n.state.get("rendered")&&r.setAttribute("role"==e?e:"aria-"+e,t),n)},encode:function(e,t){return t!==!1&&(e=this.translate(e)),(e||"").replace(/[&<>"]/g,function(e){return"&#"+e.charCodeAt(0)+";"})},translate:function(e){return m.translate?m.translate(e):e},before:function(e){var t=this,n=t.parent();ret
urn n&&n.insert(e,n.items().indexOf(t),!0),t},after:function(e){var t=this,n=t.parent();return n&&n.insert(e,n.items().indexOf(t)),t},remove:function(){var e=this,t=e.getEl(),n=e.parent(),r,i;if(e.items){var o=e.items().toArray();for(i=o.length;i--;)o[i].remove()}n&&n.items&&(r=[],n.items().each(function(t){t!==e&&r.push(t)}),n.items().set(r),n._lastRect=null),e._eventsRoot&&e._eventsRoot==e&&a(t).off();var s=e.getRoot().controlIdLookup;return s&&delete s[e._id],t&&t.parentNode&&t.parentNode.removeChild(t),e.state.set("rendered",!1),e.state.destroy(),e.fire("remove"),e},renderBefore:function(e){return a(e).before(this.renderHtml()),this.postRender(),this},renderTo:function(e){return a(e||this.getContainerElm()).append(this.renderHtml()),this.postRender(),this},preRender:function(){},render:function(){},renderHtml:function(){return'<div id="'+this._id+'" class="'+this
.classes+'"></div>'},postRender:function(){var e=this,t=e.settings,n,r,i,o,s;e.$el=a(e.getEl()),e.state.set("rendered",!0);for(o in t)0===o.indexOf("on")&&e.on(o.substr(2),t[o]);if(e._eventsRoot){for(i=e.parent();!s&&i;i=i.parent())s=i._eventsRoot;if(s)for(o in s._nativeEvents)e._nativeEvents[o]=!0}d(e),t.style&&(n=e.getEl(),n&&(n.setAttribute("style",t.style),n.style.cssText=t.style)),e.settings.border&&(r=e.borderBox,e.$el.css({"border-top-width":r.top,"border-right-width":r.right,"border-bottom-width":r.bottom,"border-left-width":r.left}));var l=e.getRoot();l.controlIdLookup||(l.controlIdLookup={}),l.controlIdLookup[e._id]=e;for(var c in e._aria)e.aria(c,e._aria[c]);e.state.get("visible")===!1&&(e.getEl().style.display="none"),e.bindStates(),e.state.on("change:visible",function(t){var n=t.value,r;e.state.get("render
ed")&&(e.getEl().style.display=n===!1?"none":"",e.getEl().getBoundingClientRect()),r=e.parent(),r&&(r._lastRect=null),e.fire(n?"show":"hide"),u.add(e)}),e.fire("postrender",{},!1)},bindStates:function(){},scrollIntoView:function(e){function t(e,t){var n,r,i=e;for(n=r=0;i&&i!=t&&i.nodeType;)n+=i.offsetLeft||0,r+=i.offsetTop||0,i=i.offsetParent;return{x:n,y:r}}var n=this.getEl(),r=n.parentNode,i,o,a,s,l,u,c=t(n,r);return i=c.x,o=c.y,a=n.offsetWidth,s=n.offsetHeight,l=r.clientWidth,u=r.clientHeight,"end"==e?(i-=l-a,o-=u-s):"center"==e&&(i-=l/2-a/2,o-=u/2-s/2),r.scrollLeft=i,r.scrollTop=o,this},getRoot:function(){for(var e=this,t,n=[];e;){if(e.rootControl){t=e.rootControl;break}n.push(e),t=e,e=e.parent()}t||(t=this);for(var r=n.length;r--;)n[r].rootControl=t;return t},reflow:function(){u.remove(this);var e=this.parent();return e._layout&&!e._layout.isNative()&&a
mp;e.reflow(),this}};return t.each("text title visible disabled active value".split(" "),function(e){v[e]=function(t){return 0===arguments.length?this.state.get(e):("undefined"!=typeof t&&this.state.set(e,t),this)}}),m=e.extend(v)}),r(we,[],function(){var e={},t;return{add:function(t,n){e[t.toLowerCase()]=n},has:function(t){return!!e[t.toLowerCase()]},create:function(n,r){var i,o,a;if(!t){a=tinymce.ui;for(o in a)e[o.toLowerCase()]=a[o];t=!0}if("string"==typeof n?(r=r||{},r.type=n):(r=n,n=r.type),n=n.toLowerCase(),i=e[n],!i)throw new Error("Could not find control by type: "+n);return i=new i(r),i.type=n,i}}}),r(Ee,[],function(){return function(e){function t(e){return e&&1===e.nodeType}function n(e){return e=e||C,t(e)?e.getAttribute("role"):null}function r(e){for(var t,r=e||C;r=r.parentNode;)if(t=n(r))return t}function i(e){var n=C;if(t(n))return n.getAttribute("aria-"+e)}function o(e){var t=e.tagNam
e.toUpperCase();return"INPUT"==t||"TEXTAREA"==t||"SELECT"==t}function a(e){return!(!o(e)||e.hidden)||!!/^(button|menuitem|checkbox|tab|menuitemcheckbox|option|gridcell|slider)$/.test(n(e))}function s(e){function t(e){if(1==e.nodeType&&"none"!=e.style.display&&!e.disabled){a(e)&&n.push(e);for(var r=0;r<e.childNodes.length;r++)t(e.childNodes[r])}}var n=[];return t(e||b.getEl()),n}function l(e){var t,n;e=e||x,n=e.parents().toArray(),n.unshift(e);for(var r=0;r<n.length&&(t=n[r],!t.settings.ariaRoot);r++);return t}function u(e){var t=l(e),n=s(t.getEl());t.settings.ariaRemember&&"lastAriaIndex"in t?c(t.lastAriaIndex,n):c(0,n)}function c(e,t){return e<0?e=t.length-1:e>=t.length&&(e=0),t[e]&&t[e].focus(),e}function d(e,t){var n=-1,r=l();t=t||s(r.getEl());for(var i=0;i<t.length;i++)t[i]===C&&(n=i);n+=e,r.lastAriaIndex=c(n,t)}function f(){var e=r();"tablist&quo
t;==e?d(-1,s(C.parentNode)):x.parent().submenu?v():d(-1)}function p(){var e=n(),t=r();"tablist"==t?d(1,s(C.parentNode)):"menuitem"==e&&"menu"==t&&i("haspopup")?y():d(1)}function h(){d(-1)}function m(){var e=n(),t=r();"menuitem"==e&&"menubar"==t?y():"button"==e&&i("haspopup")?y({key:"down"}):d(1)}function g(e){var t=r();if("tablist"==t){var n=s(x.getEl("body"))[0];n&&n.focus()}else d(e.shiftKey?-1:1)}function v(){x.fire("cancel")}function y(e){e=e||{},x.fire("click",{target:C,aria:e})}var b=e.root,C,x;try{C=document.activeElement}catch(w){C=document.body}return x=b.getParentCtrl(C),b.on("keydown",function(e){function t(e,t){o(C)||"slider"!==n(C)&&t(e)!==!1&&e.preventDefault()}if(!e.isDefaultPrevented())switch(e.keyCode){case 37:t(e,f);break;case 39:t(e,p);break;case 38:t(e,h);break
;case 40:t(e,m);break;case 27:v();break;case 14:case 13:case 32:t(e,y);break;case 9:g(e)!==!1&&e.preventDefault()}}),b.on("focusin",function(e){C=e.target,x=e.control}),{focusFirst:u}}}),r(Ne,[xe,ge,me,we,Ee,m,g,be,Ce],function(e,t,n,r,i,o,a,s,l){var u={};return e.extend({init:function(e){var n=this;n._super(e),e=n.settings,e.fixed&&n.state.set("fixed",!0),n._items=new t,n.isRtl()&&n.classes.add("rtl"),n.bodyClasses=new s(function(){n.state.get("rendered")&&(n.getEl("body").className=this.toString())}),n.bodyClasses.prefix=n.classPrefix,n.classes.add("container"),n.bodyClasses.add("container-body"),e.containerCls&&n.classes.add(e.containerCls),n._layout=r.create((e.layout||"")+"layout"),n.settings.items?n.add(n.settings.items):n.add(n.render()),n._hasBody=!0},items:function(){return this._items},find:function(e){return e=u[e]=u[e]||new n(e),e.find(this)},
add:function(e){var t=this;return t.items().add(t.create(e)).parent(t),t},focus:function(e){var t=this,n,r,i;return e&&(r=t.keyboardNav||t.parents().eq(-1)[0].keyboardNav)?void r.focusFirst(t):(i=t.find("*"),t.statusbar&&i.add(t.statusbar.items()),i.each(function(e){return e.settings.autofocus?(n=null,!1):void(e.canFocus&&(n=n||e))}),n&&n.focus(),t)},replace:function(e,t){for(var n,r=this.items(),i=r.length;i--;)if(r[i]===e){r[i]=t;break}i>=0&&(n=t.getEl(),n&&n.parentNode.removeChild(n),n=e.getEl(),n&&n.parentNode.removeChild(n)),t.parent(this)},create:function(t){var n=this,i,a=[];return o.isArray(t)||(t=[t]),o.each(t,function(t){t&&(t instanceof e||("string"==typeof t&&(t={type:t}),i=o.extend({},n.settings.defaults,t),t.type=i.type=i.type||t.type||n.settings.defaultType||(i.defaults?i.defaults.type:null),t=r.create(i)),a.push(t))}),a},renderNew:function(){var e=this;return e.items().each
(function(t,n){var r;t.parent(e),t.state.get("rendered")||(r=e.getEl("body"),r.hasChildNodes()&&n<=r.childNodes.length-1?a(r.childNodes[n]).before(t.renderHtml()):a(r).append(t.renderHtml()),t.postRender(),l.add(t))}),e._layout.applyClasses(e.items().filter(":visible")),e._lastRect=null,e},append:function(e){return this.add(e).renderNew()},prepend:function(e){var t=this;return t.items().set(t.create(e).concat(t.items().toArray())),t.renderNew()},insert:function(e,t,n){var r=this,i,o,a;return e=r.create(e),i=r.items(),!n&&t<i.length-1&&(t+=1),t>=0&&t<i.length&&(o=i.slice(0,t).toArray(),a=i.slice(t).toArray(),i.set(o.concat(e,a))),r.renderNew()},fromJSON:function(e){var t=this;for(var n in e)t.find("#"+n).value(e[n]);return t},toJSON:function(){var e=this,t={};return e.find("*").each(function(e){var n=e.name(),r=e.value();n&&"undefined"!=typeof r&&(t[n]=r)}),
t},renderHtml:function(){var e=this,t=e._layout,n=this.settings.role;return e.preRender(),t.preRender(e),'<div id="'+e._id+'" class="'+e.classes+'"'+(n?' role="'+this.settings.role+'"':"")+'><div id="'+e._id+'-body" class="'+e.bodyClasses+'">'+(e.settings.html||"")+t.renderHtml(e)+"</div></div>"},postRender:function(){var e=this,t;return e.items().exec("postRender"),e._super(),e._layout.postRender(e),e.state.set("rendered",!0),e.settings.style&&e.$el.css(e.settings.style),e.settings.border&&(t=e.borderBox,e.$el.css({"border-top-width":t.top,"border-right-width":t.right,"border-bottom-width":t.bottom,"border-left-width":t.left})),e.parent()||(e.keyboardNav=new i({root:e})),e},initLayoutRect:function(){var e=this,t=e._super();return e._layout.recalc(e),t},recalc:function(){var e=this,t=e._layoutRect,n=e._las
tRect;if(!n||n.w!=t.w||n.h!=t.h)return e._layout.recalc(e),t=e.layoutRect(),e._lastRect={x:t.x,y:t.y,w:t.w,h:t.h},!0},reflow:function(){var t;if(l.remove(this),this.visible()){for(e.repaintControls=[],e.repaintControls.map={},this.recalc(),t=e.repaintControls.length;t--;)e.repaintControls[t].repaint();"flow"!==this.settings.layout&&"stack"!==this.settings.layout&&this.repaint(),e.repaintControls=[]}return this}})}),r(_e,[g],function(e){function t(e){var t,n,r,i,o,a,s,l,u=Math.max;return t=e.documentElement,n=e.body,r=u(t.scrollWidth,n.scrollWidth),i=u(t.clientWidth,n.clientWidth),o=u(t.offsetWidth,n.offsetWidth),a=u(t.scrollHeight,n.scrollHeight),s=u(t.clientHeight,n.clientHeight),l=u(t.offsetHeight,n.offsetHeight),{width:r<o?i:r,height:a<l?s:a}}function n(e){var t,n;if(e.changedTouches)for(t="screenX screenY pageX pageY clientX clientY".split(" "),n=0;n<t.length;n++)e[t[n]]=e.changedTouches[0][t[n]]}return function(r,
i){function o(){return s.getElementById(i.handle||r)}var a,s=i.document||document,l,u,c,d,f,p;i=i||{},u=function(r){var u=t(s),h,m;n(r),r.preventDefault(),l=r.button,h=o(),f=r.screenX,p=r.screenY,m=window.getComputedStyle?window.getComputedStyle(h,null).getPropertyValue("cursor"):h.runtimeStyle.cursor,a=e("<div></div>").css({position:"absolute",top:0,left:0,width:u.width,height:u.height,zIndex:2147483647,opacity:1e-4,cursor:m}).appendTo(s.body),e(s).on("mousemove touchmove",d).on("mouseup touchend",c),i.start(r)},d=function(e){return n(e),e.button!==l?c(e):(e.deltaX=e.screenX-f,e.deltaY=e.screenY-p,e.preventDefault(),void i.drag(e))},c=function(t){n(t),e(s).off("mousemove touchmove",d).off("mouseup touchend",c),a.remove(),i.stop&&i.stop(t)},this.destroy=function(){e(o()).off()},e(o()).on("mousedown touchstart",u)}}),r(Se,[g,_e],function(e,t){return{init:function(){var e=this;e.on(&quo
t;repaint",e.renderScroll)},renderScroll:function(){function n(){function t(t,a,s,l,u,c){var d,f,p,h,m,g,v,y,b;if(f=i.getEl("scroll"+t)){if(y=a.toLowerCase(),b=s.toLowerCase(),e(i.getEl("absend")).css(y,i.layoutRect()[l]-1),!u)return void e(f).css("display","none");e(f).css("display","block"),d=i.getEl("body"),p=i.getEl("scroll"+t+"t"),h=d["client"+s]-2*o,h-=n&&r?f["client"+c]:0,m=d["scroll"+s],g=h/m,v={},v[y]=d["offset"+a]+o,v[b]=h,e(f).css(v),v={},v[y]=d["scroll"+a]*g,v[b]=h*g,e(p).css(v)}}var n,r,a;a=i.getEl("body"),n=a.scrollWidth>a.clientWidth,r=a.scrollHeight>a.clientHeight,t("h","Left","Width","contentW",n,"Height"),t("v","Top","Height","contentH",r,"Width")}function r(){function n(n,r,a,s,l){var u,c=i._id+"
;-scroll"+n,d=i.classPrefix;e(i.getEl()).append('<div id="'+c+'" class="'+d+"scrollbar "+d+"scrollbar-"+n+'"><div id="'+c+'t" class="'+d+'scrollbar-thumb"></div></div>'),i.draghelper=new t(c+"t",{start:function(){u=i.getEl("body")["scroll"+r],e("#"+c).addClass(d+"active")},drag:function(e){var t,c,d,f,p=i.layoutRect();c=p.contentW>p.innerW,d=p.contentH>p.innerH,f=i.getEl("body")["client"+a]-2*o,f-=c&&d?i.getEl("scroll"+n)["client"+l]:0,t=f/i.getEl("body")["scroll"+a],i.getEl("body")["scroll"+r]=u+e["delta"+s]/t},stop:function(){e("#"+c).removeClass(d+"active")}})}i.classes.add("scroll"),n("v","Top","Height","Y","Width"),n("h","Left","Width&q
uot;,"X","Height")}var i=this,o=2;i.settings.autoScroll&&(i._hasScroll||(i._hasScroll=!0,r(),i.on("wheel",function(e){var t=i.getEl("body");t.scrollLeft+=10*(e.deltaX||0),t.scrollTop+=10*e.deltaY,n()}),e(i.getEl("body")).on("scroll",n)),n())}}}),r(ke,[Ne,Se],function(e,t){return e.extend({Defaults:{layout:"fit",containerCls:"panel"},Mixins:[t],renderHtml:function(){var e=this,t=e._layout,n=e.settings.html;return e.preRender(),t.preRender(e),"undefined"==typeof n?n='<div id="'+e._id+'-body" class="'+e.bodyClasses+'">'+t.renderHtml(e)+"</div>":("function"==typeof n&&(n=n.call(e)),e._hasBody=!1),'<div id="'+e._id+'" class="'+e.classes+'" hidefocus="1" tabindex="-1" role="group">'+(e._preBodyHtml||"")+n+"</div>"}})}),r(Te,[ve],function(e){function t(t
,n,r){var i,o,a,s,l,u,c,d,f,p;return f=e.getViewPort(),o=e.getPos(n),a=o.x,s=o.y,t.state.get("fixed")&&"static"==e.getRuntimeStyle(document.body,"position")&&(a-=f.x,s-=f.y),i=t.getEl(),p=e.getSize(i),l=p.width,u=p.height,p=e.getSize(n),c=p.width,d=p.height,r=(r||"").split(""),"b"===r[0]&&(s+=d),"r"===r[1]&&(a+=c),"c"===r[0]&&(s+=Math.round(d/2)),"c"===r[1]&&(a+=Math.round(c/2)),"b"===r[3]&&(s-=u),"r"===r[4]&&(a-=l),"c"===r[3]&&(s-=Math.round(u/2)),"c"===r[4]&&(a-=Math.round(l/2)),{x:a,y:s,w:l,h:u}}return{testMoveRel:function(n,r){for(var i=e.getViewPort(),o=0;o<r.length;o++){var a=t(this,n,r[o]);if(this.state.get("fixed")){if(a.x>0&&a.x+a.w<i.w&&a.y>0&&a.y+a.h<i.h)return r[o]}else if(a.x>i.x&&a.x+a.w<i.w+i.x&&
amp;a.y>i.y&&a.y+a.h<i.h+i.y)return r[o]}return r[0]},moveRel:function(e,n){"string"!=typeof n&&(n=this.testMoveRel(e,n));var r=t(this,e,n);return this.moveTo(r.x,r.y)},moveBy:function(e,t){var n=this,r=n.layoutRect();return n.moveTo(r.x+e,r.y+t),n},moveTo:function(t,n){function r(e,t,n){return e<0?0:e+n>t?(e=t-n,e<0?0:e):e}var i=this;if(i.settings.constrainToViewport){var o=e.getViewPort(window),a=i.layoutRect();t=r(t,o.w+o.x,a.w),n=r(n,o.h+o.y,a.h)}return i.state.get("rendered")?i.layoutRect({x:t,y:n}).repaint():(i.settings.x=t,i.settings.y=n),i.fire("move",{x:t,y:n}),i}}}),r(Re,[ve],function(e){return{resizeToContent:function(){this._layoutRect.autoResize=!0,this._lastRect=null,this.reflow()},resizeTo:function(t,n){if(t<=1||n<=1){var r=e.getWindowSize();t=t<=1?t*r.w:t,n=n<=1?n*r.h:n}return this._layoutRect.autoResize=!1,this.layoutRect({minW:t,minH:n,w:t,h:n}).reflow()},resizeBy:function(e,t){var n=this,r=n.
layoutRect();return n.resizeTo(r.w+e,r.h+t)}}}),r(Ae,[ke,Te,Re,ve,g,c],function(e,t,n,r,i,o){function a(e,t){for(;e;){if(e==t)return!0;e=e.parent()}}function s(e){for(var t=v.length;t--;){var n=v[t],r=n.getParentCtrl(e.target);if(n.settings.autohide){if(r&&(a(r,n)||n.parent()===r))continue;e=n.fire("autohide",{target:e.target}),e.isDefaultPrevented()||n.hide()}}}function l(){h||(h=function(e){2!=e.button&&s(e)},i(document).on("click touchstart",h))}function u(){m||(m=function(){var e;for(e=v.length;e--;)d(v[e])},i(window).on("scroll",m))}function c(){if(!g){var e=document.documentElement,t=e.clientWidth,n=e.clientHeight;g=function(){document.all&&t==e.clientWidth&&n==e.clientHeight||(t=e.clientWidth,n=e.clientHeight,C.hideAll())},i(window).on("resize",g)}}function d(e){function t(t,n){for(var r,i=0;i<v.length;i++)if(v[i]!=e)for(r=v[i].parent();r&&(r=r.parent());)r==e&&v[i].fixed(t).moveBy(0,n)
.repaint()}var n=r.getViewPort().y;e.settings.autofix&&(e.state.get("fixed")?e._autoFixY>n&&(e.fixed(!1).layoutRect({y:e._autoFixY}).repaint(),t(!1,e._autoFixY-n)):(e._autoFixY=e.layoutRect().y,e._autoFixY<n&&(e.fixed(!0).layoutRect({y:0}).repaint(),t(!0,n-e._autoFixY))))}function f(e,t){var n,r=C.zIndex||65535,o;if(e)y.push(t);else for(n=y.length;n--;)y[n]===t&&y.splice(n,1);if(y.length)for(n=0;n<y.length;n++)y[n].modal&&(r++,o=y[n]),y[n].getEl().style.zIndex=r,y[n].zIndex=r,r++;var a=i("#"+t.classPrefix+"modal-block",t.getContainerElm())[0];o?i(a).css("z-index",o.zIndex-1):a&&(a.parentNode.removeChild(a),b=!1),C.currentZIndex=r}function p(e){var t;for(t=v.length;t--;)v[t]===e&&v.splice(t,1);for(t=y.length;t--;)y[t]===e&&y.splice(t,1)}var h,m,g,v=[],y=[],b,C=e.extend({Mixins:[t,n],init:function(e){var t=this;t._super(e),t._eventsRoot=t,t.classes.add("floatpanel"
;),e.autohide&&(l(),c(),v.push(t)),e.autofix&&(u(),t.on("move",function(){d(this)})),t.on("postrender show",function(e){if(e.control==t){var n,r=t.classPrefix;t.modal&&!b&&(n=i("#"+r+"modal-block",t.getContainerElm()),n[0]||(n=i('<div id="'+r+'modal-block" class="'+r+"reset "+r+'fade"></div>').appendTo(t.getContainerElm())),o.setTimeout(function(){n.addClass(r+"in"),i(t.getEl()).addClass(r+"in")}),b=!0),f(!0,t)}}),t.on("show",function(){t.parents().each(function(e){if(e.state.get("fixed"))return t.fixed(!0),!1})}),e.popover&&(t._preBodyHtml='<div class="'+t.classPrefix+'arrow"></div>',t.classes.add("popover").add("bottom").add(t.isRtl()?"end":"start")),t.aria("label",e.ariaLabel),t.aria("labelledby",t._id),t.aria("describedby",t.desc
ribedBy||t._id+"-none")},fixed:function(e){var t=this;if(t.state.get("fixed")!=e){if(t.state.get("rendered")){var n=r.getViewPort();e?t.layoutRect().y-=n.y:t.layoutRect().y+=n.y}t.classes.toggle("fixed",e),t.state.set("fixed",e)}return t},show:function(){var e=this,t,n=e._super();for(t=v.length;t--&&v[t]!==e;);return t===-1&&v.push(e),n},hide:function(){return p(this),f(!1,this),this._super()},hideAll:function(){C.hideAll()},close:function(){var e=this;return e.fire("close").isDefaultPrevented()||(e.remove(),f(!1,e)),e},remove:function(){p(this),this._super()},postRender:function(){var e=this;return e.settings.bodyRole&&this.getEl("body").setAttribute("role",e.settings.bodyRole),e._super()}});return C.hideAll=function(){for(var e=v.length;e--;){var t=v[e];t&&t.settings.autohide&&(t.hide(),v.splice(e,1))}},C}),r(Be,[Ae,ke,ve,g,_e,ye,d,c],function(e,t,n,r,i,o,a,s){fu
nction l(e){var t="width=device-width,initial-scale=1.0,user-scalable=0,minimum-scale=1.0,maximum-scale=1.0",n=r("meta[name=viewport]")[0],i;a.overrideViewPort!==!1&&(n||(n=document.createElement("meta"),n.setAttribute("name","viewport"),document.getElementsByTagName("head")[0].appendChild(n)),i=n.getAttribute("content"),i&&"undefined"!=typeof p&&(p=i),n.setAttribute("content",e?t:p))}function u(e,t){c()&&t===!1&&r([document.documentElement,document.body]).removeClass(e+"fullscreen")}function c(){for(var e=0;e<f.length;e++)if(f[e]._fullscreen)return!0;return!1}function d(){function e(){var e,t=n.getWindowSize(),r;for(e=0;e<f.length;e++)r=f[e].layoutRect(),f[e].moveTo(f[e].settings.x||Math.max(0,t.w/2-r.w/2),f[e].settings.y||Math.max(0,t.h/2-r.h/2))}if(!a.desktop){var t={w:window.innerWidth,h:window.innerHeight};s.setInterval(function(){var
e=window.innerWidth,n=window.innerHeight;t.w==e&&t.h==n||(t={w:e,h:n},r(window).trigger("resize"))},100)}r(window).on("resize",e)}var f=[],p="",h=e.extend({modal:!0,Defaults:{border:1,layout:"flex",containerCls:"panel",role:"dialog",callbacks:{submit:function(){this.fire("submit",{data:this.toJSON()})},close:function(){this.close()}}},init:function(e){var r=this;r._super(e),r.isRtl()&&r.classes.add("rtl"),r.classes.add("window"),r.bodyClasses.add("window-body"),r.state.set("fixed",!0),e.buttons&&(r.statusbar=new t({layout:"flex",border:"1 0 0 0",spacing:3,padding:10,align:"center",pack:r.isRtl()?"start":"end",defaults:{type:"button"},items:e.buttons}),r.statusbar.classes.add("foot"),r.statusbar.parent(r)),r.on("click",function(e){var t=r.classPrefix+"close";(n.h
asClass(e.target,t)||n.hasClass(e.target.parentNode,t))&&r.close()}),r.on("cancel",function(){r.close()}),r.aria("describedby",r.describedBy||r._id+"-none"),r.aria("label",e.title),r._fullscreen=!1},recalc:function(){var e=this,t=e.statusbar,r,i,o,a;e._fullscreen&&(e.layoutRect(n.getWindowSize()),e.layoutRect().contentH=e.layoutRect().innerH),e._super(),r=e.layoutRect(),e.settings.title&&!e._fullscreen&&(i=r.headerW,i>r.w&&(o=r.x-Math.max(0,i/2),e.layoutRect({w:i,x:o}),a=!0)),t&&(t.layoutRect({w:e.layoutRect().innerW}).recalc(),i=t.layoutRect().minW+r.deltaW,i>r.w&&(o=r.x-Math.max(0,i-r.w),e.layoutRect({w:i,x:o}),a=!0)),a&&e.recalc()},initLayoutRect:function(){var e=this,t=e._super(),r=0,i;if(e.settings.title&&!e._fullscreen){i=e.getEl("head");var o=n.getSize(i);t.headerW=o.width,t.headerH=o.height,r+=t.headerH}e.statusbar&&(r+=e.statusbar.layoutRec
t().h),t.deltaH+=r,t.minH+=r,t.h+=r;var a=n.getWindowSize();return t.x=e.settings.x||Math.max(0,a.w/2-t.w/2),t.y=e.settings.y||Math.max(0,a.h/2-t.h/2),t},renderHtml:function(){var e=this,t=e._layout,n=e._id,r=e.classPrefix,i=e.settings,o="",a="",s=i.html;return e.preRender(),t.preRender(e),i.title&&(o='<div id="'+n+'-head" class="'+r+'window-head"><div id="'+n+'-title" class="'+r+'title">'+e.encode(i.title)+'</div><div id="'+n+'-dragh" class="'+r+'dragh"></div><button type="button" class="'+r+'close" aria-hidden="true"><i class="mce-ico mce-i-remove"></i></button></div>'),i.url&&(s='<iframe src="'+i.url+'" tabindex="-1"></iframe>'),"undefined"==typeof s&&(s=t.renderHtml(e)),e.statusbar&&(a=e.statusbar.renderHtml()),'<div id="
'+n+'" class="'+e.classes+'" hidefocus="1"><div class="'+e.classPrefix+'reset" role="application">'+o+'<div id="'+n+'-body" class="'+e.bodyClasses+'">'+s+"</div>"+a+"</div></div>"},fullscreen:function(e){var t=this,i=document.documentElement,a,l=t.classPrefix,u;if(e!=t._fullscreen)if(r(window).on("resize",function(){var e;if(t._fullscreen)if(a)t._timer||(t._timer=s.setTimeout(function(){var e=n.getWindowSize();t.moveTo(0,0).resizeTo(e.w,e.h),t._timer=0},50));else{e=(new Date).getTime();var r=n.getWindowSize();t.moveTo(0,0).resizeTo(r.w,r.h),(new Date).getTime()-e>50&&(a=!0)}}),u=t.layoutRect(),t._fullscreen=e,e){t._initial={x:u.x,y:u.y,w:u.w,h:u.h},t.borderBox=o.parseBox("0"),t.getEl("head").style.display="none",u.deltaH-=u.headerH+2,r([i,document.body]).addClass(l+"fullscreen"),t.classes.add("fullscre
en");var c=n.getWindowSize();t.moveTo(0,0).resizeTo(c.w,c.h)}else t.borderBox=o.parseBox(t.settings.border),t.getEl("head").style.display="",u.deltaH+=u.headerH,r([i,document.body]).removeClass(l+"fullscreen"),t.classes.remove("fullscreen"),t.moveTo(t._initial.x,t._initial.y).resizeTo(t._initial.w,t._initial.h);return t.reflow()},postRender:function(){var e=this,t;setTimeout(function(){e.classes.add("in"),e.fire("open")},0),e._super(),e.statusbar&&e.statusbar.postRender(),e.focus(),this.dragHelper=new i(e._id+"-dragh",{start:function(){t={x:e.layoutRect().x,y:e.layoutRect().y}},drag:function(n){e.moveTo(t.x+n.deltaX,t.y+n.deltaY)}}),e.on("submit",function(t){t.isDefaultPrevented()||e.close()}),f.push(e),l(!0)},submit:function(){return this.fire("submit",{data:this.toJSON()})},remove:function(){var e=this,t;for(e.dragHelper.destroy(),e._super(),e.statusbar&&this.statusbar.re
move(),u(e.classPrefix,!1),t=f.length;t--;)f[t]===e&&f.splice(t,1);l(f.length>0)},getContentWindow:function(){var e=this.getEl().getElementsByTagName("iframe")[0];return e?e.contentWindow:null}});return d(),h}),r(De,[Be],function(e){var t=e.extend({init:function(e){e={border:1,padding:20,layout:"flex",pack:"center",align:"center",containerCls:"panel",autoScroll:!0,buttons:{type:"button",text:"Ok",action:"ok"},items:{type:"label",multiline:!0,maxWidth:500,maxHeight:200}},this._super(e)},Statics:{OK:1,OK_CANCEL:2,YES_NO:3,YES_NO_CANCEL:4,msgBox:function(n){function r(e,t,n){return{type:"button",text:e,subtype:n?"primary":"",onClick:function(e){e.control.parents()[1].close(),o(t)}}}var i,o=n.callback||function(){};
-switch(n.buttons){case t.OK_CANCEL:i=[r("Ok",!0,!0),r("Cancel",!1)];break;case t.YES_NO:case t.YES_NO_CANCEL:i=[r("Yes",1,!0),r("No",0)],n.buttons==t.YES_NO_CANCEL&&i.push(r("Cancel",-1));break;default:i=[r("Ok",!0,!0)]}return new e({padding:20,x:n.x,y:n.y,minWidth:300,minHeight:100,layout:"flex",pack:"center",align:"center",buttons:i,title:n.title,role:"alertdialog",items:{type:"label",multiline:!0,maxWidth:500,maxHeight:200,text:n.text},onPostRender:function(){this.aria("describedby",this.items()[0]._id)},onClose:n.onClose,onCancel:function(){o(!1)}}).renderTo(document.body).reflow()},alert:function(e,n){return"string"==typeof e&&(e={text:e}),e.callback=n,t.msgBox(e)},confirm:function(e,n){return"string"==typeof e&&(e={text:e}),e.callback=n,e.buttons=t.OK_CANCEL,t.msgBox(e)}}});return t}),r(Le,[Be,De],function(e,t){retu
rn function(n){function r(){if(s.length)return s[s.length-1]}function i(e){n.fire("OpenWindow",{win:e})}function o(e){n.fire("CloseWindow",{win:e})}var a=this,s=[];a.windows=s,n.on("remove",function(){for(var e=s.length;e--;)s[e].close()}),a.open=function(t,r){var a;return n.editorManager.setActive(n),t.title=t.title||" ",t.url=t.url||t.file,t.url&&(t.width=parseInt(t.width||320,10),t.height=parseInt(t.height||240,10)),t.body&&(t.items={defaults:t.defaults,type:t.bodyType||"form",items:t.body,data:t.data,callbacks:t.commands}),t.url||t.buttons||(t.buttons=[{text:"Ok",subtype:"primary",onclick:function(){a.find("form")[0].submit()}},{text:"Cancel",onclick:function(){a.close()}}]),a=new e(t),s.push(a),a.on("close",function(){for(var e=s.length;e--;)s[e]===a&&s.splice(e,1);s.length||n.focus(),o(a)}),t.data&&a.on("postRender",function(){this.find(
"*").each(function(e){var n=e.name();n in t.data&&e.value(t.data[n])})}),a.features=t||{},a.params=r||{},1===s.length&&n.nodeChanged(),a=a.renderTo().reflow(),i(a),a},a.alert=function(e,r,a){var s;s=t.alert(e,function(){r?r.call(a||this):n.focus()}),s.on("close",function(){o(s)}),i(s)},a.confirm=function(e,n,r){var a;a=t.confirm(e,function(e){n.call(r||this,e)}),a.on("close",function(){o(a)}),i(a)},a.close=function(){r()&&r().close()},a.getParams=function(){return r()?r().params:null},a.setParams=function(e){r()&&(r().params=e)},a.getWindows=function(){return s}}}),r(Me,[xe,Te],function(e,t){return e.extend({Mixins:[t],Defaults:{classes:"widget tooltip tooltip-n"},renderHtml:function(){var e=this,t=e.classPrefix;return'<div id="'+e._id+'" class="'+e.classes+'" role="presentation"><div class="'+t+'tooltip-arrow"></div><div class="'+t+'tooltip-inner
">'+e.encode(e.state.get("text"))+"</div></div>"},bindStates:function(){var e=this;return e.state.on("change:text",function(t){e.getEl().lastChild.innerHTML=e.encode(t.value)}),e._super()},repaint:function(){var e=this,t,n;t=e.getEl().style,n=e._layoutRect,t.left=n.x+"px",t.top=n.y+"px",t.zIndex=131070}})}),r(Pe,[xe,Me],function(e,t){var n,r=e.extend({init:function(e){var t=this;t._super(e),e=t.settings,t.canFocus=!0,e.tooltip&&r.tooltips!==!1&&(t.on("mouseenter",function(n){var r=t.tooltip().moveTo(-65535);if(n.control==t){var i=r.text(e.tooltip).show().testMoveRel(t.getEl(),["bc-tc","bc-tl","bc-tr"]);r.classes.toggle("tooltip-n","bc-tc"==i),r.classes.toggle("tooltip-nw","bc-tl"==i),r.classes.toggle("tooltip-ne","bc-tr"==i),r.moveRel(t.getEl(),i)}else r.hide()}),t.on("mouseleave mousedown click
",function(){t.tooltip().hide()})),t.aria("label",e.ariaLabel||e.tooltip)},tooltip:function(){return n||(n=new t({type:"tooltip"}),n.renderTo()),n},postRender:function(){var e=this,t=e.settings;e._super(),e.parent()||!t.width&&!t.height||(e.initLayoutRect(),e.repaint()),t.autofocus&&e.focus()},bindStates:function(){function e(e){n.aria("disabled",e),n.classes.toggle("disabled",e)}function t(e){n.aria("pressed",e),n.classes.toggle("active",e)}var n=this;return n.state.on("change:disabled",function(t){e(t.value)}),n.state.on("change:active",function(e){t(e.value)}),n.state.get("disabled")&&e(!0),n.state.get("active")&&t(!0),n._super()},remove:function(){this._super(),n&&(n.remove(),n=null)}});return r}),r(Oe,[Pe],function(e){return e.extend({Defaults:{value:0},init:function(e){var t=this;t._super(e),t.classes.add("progress"),t.setti
ngs.filter||(t.settings.filter=function(e){return Math.round(e)})},renderHtml:function(){var e=this,t=e._id,n=this.classPrefix;return'<div id="'+t+'" class="'+e.classes+'"><div class="'+n+'bar-container"><div class="'+n+'bar"></div></div><div class="'+n+'text">0%</div></div>'},postRender:function(){var e=this;return e._super(),e.value(e.settings.value),e},bindStates:function(){function e(e){e=t.settings.filter(e),t.getEl().lastChild.innerHTML=e+"%",t.getEl().firstChild.firstChild.style.width=e+"%"}var t=this;return t.state.on("change:value",function(t){e(t.value)}),e(t.state.get("value")),t._super()}})}),r(He,[xe,Te,Oe,c],function(e,t,n,r){return e.extend({Mixins:[t],Defaults:{classes:"widget notification"},init:function(e){var t=this;t._super(e),e.text&&t.text(e.text),e.icon&&(t.icon=e.icon),e.color&&(t.color=e.c
olor),e.type&&t.classes.add("notification-"+e.type),e.timeout&&(e.timeout<0||e.timeout>0)&&!e.closeButton?t.closeButton=!1:(t.classes.add("has-close"),t.closeButton=!0),e.progressBar&&(t.progressBar=new n),t.on("click",function(e){e.target.className.indexOf(t.classPrefix+"close")!=-1&&t.close()})},renderHtml:function(){var e=this,t=e.classPrefix,n="",r="",i="",o="";return e.icon&&(n='<i class="'+t+"ico "+t+"i-"+e.icon+'"></i>'),e.color&&(o=' style="background-color: '+e.color+'"'),e.closeButton&&(r='<button type="button" class="'+t+'close" aria-hidden="true">\xd7</button>'),e.progressBar&&(i=e.progressBar.renderHtml()),'<div id="'+e._id+'" class="'+e.classes+'"'+o+' role="presentation">'+n+'<div c
lass="'+t+'notification-inner">'+e.state.get("text")+"</div>"+i+r+"</div>"},postRender:function(){var e=this;return r.setTimeout(function(){e.$el.addClass(e.classPrefix+"in")}),e._super()},bindStates:function(){var e=this;return e.state.on("change:text",function(t){e.getEl().childNodes[1].innerHTML=t.value}),e.progressBar&&e.progressBar.bindStates(),e._super()},close:function(){var e=this;return e.fire("close").isDefaultPrevented()||e.remove(),e},repaint:function(){var e=this,t,n;t=e.getEl().style,n=e._layoutRect,t.left=n.x+"px",t.top=n.y+"px",t.zIndex=65534}})}),r(Ie,[He,c,m],function(e,t,n){return function(r){function i(){if(f.length)return f[f.length-1]}function o(){t.requestAnimationFrame(function(){a(),s()})}function a(){for(var e=0;e<f.length;e++)f[e].moveTo(0,0)}function s(){if(f.length>0){var e=f.slice(0,1)[0],t=r.inline?r.getElement():r.getContentAreaContai
ner();if(e.moveRel(t,"tc-tc"),f.length>1)for(var n=1;n<f.length;n++)f[n].moveRel(f[n-1].getEl(),"bc-tc")}}function l(e,t){if(!c(t))return null;var r=n.grep(e,function(e){return u(t,e)});return 0===r.length?null:r[0]}function u(e,t){return e.type===t.settings.type&&e.text===t.settings.text}function c(e){return!e.progressBar&&!e.timeout}var d=this,f=[];d.notifications=f,r.on("remove",function(){for(var e=f.length;e--;)f[e].close()}),r.on("ResizeEditor",s),r.on("ResizeWindow",o),d.open=function(t){if(!r.removed){var n;r.editorManager.setActive(r);var i=l(f,t);return null===i?(n=new e(t),f.push(n),t.timeout>0&&(n.timer=setTimeout(function(){n.close()},t.timeout)),n.on("close",function(){var e=f.length;for(n.timer&&r.getWin().clearTimeout(n.timer);e--;)f[e]===n&&f.splice(e,1);s()}),n.renderTo(),s()):n=i,n}},d.close=function(){i()&&i().close()},d.getNotifications=function()
{return f},r.on("SkinLoaded",function(){var e=r.settings.service_message;e&&r.notificationManager.open({text:e,type:"warning",timeout:0,icon:""})})}}),r(Fe,[w],function(e){function t(t,n,r){for(var i=[];n&&n!=t;n=n.parentNode)i.push(e.nodeIndex(n,r));return i}function n(e,t){var n,r,i;for(r=e,n=t.length-1;n>=0;n--){if(i=r.childNodes,t[n]>i.length-1)return null;r=i[t[n]]}return r}return{create:t,resolve:n}}),r(ze,[I,T,y,Fe,A,C,d,m,c,k,$,oe],function(e,t,n,r,i,o,a,s,l,u,c,d){return function(f){function p(e,t){try{f.getDoc().execCommand(e,!1,t)}catch(n){}}function h(){var e=f.getDoc().documentMode;return e?e:6}function m(e){return e.isDefaultPrevented()}function g(e){var t,n;e.dataTransfer&&(f.selection.isCollapsed()&&"IMG"==e.target.tagName&&re.select(e.target),t=f.selection.getContent(),t.length>0&&(n=ce+escape(f.id)+","+escape(t),e.dataTransfer.setData(de,n)))}function v(e){var
t;return e.dataTransfer&&(t=e.dataTransfer.getData(de),t&&t.indexOf(ce)>=0)?(t=t.substr(ce.length).split(","),{id:unescape(t[0]),html:unescape(t[1])}):null}function y(e){f.queryCommandSupported("mceInsertClipboardContent")?f.execCommand("mceInsertClipboardContent",!1,{content:e}):f.execCommand("mceInsertContent",!1,e)}function b(){function i(e){var t=x.schema.getBlockElements(),n=f.getBody();if("BR"!=e.nodeName)return!1;for(;e!=n&&!t[e.nodeName];e=e.parentNode)if(e.nextSibling)return!1;return!0}function o(e,t){var n;for(n=e.nextSibling;n&&n!=t;n=n.nextSibling)if((3!=n.nodeType||0!==Z.trim(n.data).length)&&n!==t)return!1;return n===t}function a(e,t,r){var o,a,s;if(x.isChildOf(e,f.getBody()))for(s=x.schema.getNonEmptyElements(),o=new n(r||e,e);a=o[t?"next":"prev"]();){if(s[a.nodeName]&&!i(a))return a;if(3==a.nodeType&&a.data.length>0)return a}}function u
(e){var n,r,i,o,s;if(!e.collapsed&&(n=x.getParent(t.getNode(e.startContainer,e.startOffset),x.isBlock),r=x.getParent(t.getNode(e.endContainer,e.endOffset),x.isBlock),s=f.schema.getTextBlockElements(),n!=r&&s[n.nodeName]&&s[r.nodeName]&&"false"!==x.getContentEditable(n)&&"false"!==x.getContentEditable(r)))return e.deleteContents(),i=a(n,!1),o=a(r,!0),x.isEmpty(r)||Z(n).append(r.childNodes),Z(r).remove(),i?1==i.nodeType?"BR"==i.nodeName?(e.setStartBefore(i),e.setEndBefore(i)):(e.setStartAfter(i),e.setEndAfter(i)):(e.setStart(i,i.data.length),e.setEnd(i,i.data.length)):o&&(1==o.nodeType?(e.setStartBefore(o),e.setEndBefore(o)):(e.setStart(o,0),e.setEnd(o,0))),w.setRng(e),!0}function c(e,n){var r,i,s,l,u,c;if(!e.collapsed)return e;if(u=e.startContainer,c=e.startOffset,3==u.nodeType)if(n){if(c<u.data.length)return e}else if(c>0)return e;r=t.getNode(u,c),s=x.getParent(r,x.isBlock),i=a(f.getBody(),n,r),l=x.g
etParent(i,x.isBlock);var d=1===u.nodeType&&c>u.childNodes.length-1;if(!r||!i)return e;if(l&&s!=l)if(n){if(!o(s,l))return e;1==r.nodeType?"BR"==r.nodeName?e.setStartBefore(r):e.setStartAfter(r):e.setStart(r,r.data.length),1==i.nodeType?e.setEnd(i,0):e.setEndBefore(i)}else{if(!o(l,s))return e;1==i.nodeType?"BR"==i.nodeName?e.setStartBefore(i):e.setStartAfter(i):e.setStart(i,i.data.length),1==r.nodeType&&d?e.setEndAfter(r):e.setEndBefore(r)}return e}function d(e){var t=w.getRng();if(t=c(t,e),u(t))return!0}function p(e,t){function n(e,n){return m=Z(n).parents().filter(function(e,t){return!!f.schema.getTextInlineElements()[t.nodeName]}),l=e.cloneNode(!1),m=s.map(m,function(e){return e=e.cloneNode(!1),l.hasChildNodes()?(e.appendChild(l.firstChild),l.appendChild(e)):l.appendChild(e),l.appendChild(e),e}),m.length?(h=x.create("br"),m[0].appendChild(h),x.replace(l,e),t.setStartBefore(h),t.setEndBefore(h),f.selection.setRng(t),h):null}f
unction i(e){return e&&f.schema.getTextBlockElements()[e.tagName]}var o,a,l,u,c,d,p,h,m;if(t.collapsed&&(d=t.startContainer,p=t.startOffset,a=x.getParent(d,x.isBlock),i(a)))if(1==d.nodeType){if(d=d.childNodes[p],d&&"BR"!=d.tagName)return;if(c=e?a.nextSibling:a.previousSibling,x.isEmpty(a)&&i(c)&&x.isEmpty(c)&&n(a,d))return x.remove(c),!0}else if(3==d.nodeType){if(o=r.create(a,d),u=a.cloneNode(!0),d=r.resolve(u,o),e){if(p>=d.data.length)return;d.deleteData(p,1)}else{if(p<=0)return;d.deleteData(p-1,1)}if(x.isEmpty(u))return n(a,d)}}function h(e){var t,n,r;d(e)||(s.each(f.getBody().getElementsByTagName("*"),function(e){"SPAN"==e.tagName&&e.setAttribute("mce-data-marked",1),!e.hasAttribute("data-mce-style")&&e.hasAttribute("style")&&f.dom.setAttrib(e,"style",f.dom.getAttrib(e,"style"))}),t=new E(function(){}),t.observe(f.getDoc(),{
childList:!0,attributes:!0,subtree:!0,attributeFilter:["style"]}),f.getDoc().execCommand(e?"ForwardDelete":"Delete",!1,null),n=f.selection.getRng(),r=n.startContainer.parentNode,s.each(t.takeRecords(),function(e){if(x.isChildOf(e.target,f.getBody())){if("style"==e.attributeName){var t=e.target.getAttribute("data-mce-style");t?e.target.setAttribute("style",t):e.target.removeAttribute("style")}s.each(e.addedNodes,function(e){if("SPAN"==e.nodeName&&!e.getAttribute("mce-data-marked")){var t,i;e==r&&(t=n.startOffset,i=e.firstChild),x.remove(e,!0),i&&(n.setStart(i,t),n.setEnd(i,t),f.selection.setRng(n))}})}}),t.disconnect(),s.each(f.dom.select("span[mce-data-marked]"),function(e){e.removeAttribute("mce-data-marked")}))}function b(e){f.undoManager.transact(function(){h(e)})}var C=f.getDoc(),x=f.dom,w=f.selection,E=window.MutationObserver,N,_;E||(N=!0,E=funct
ion(){function e(e){var t=e.relatedNode||e.target;n.push({target:t,addedNodes:[t]})}function t(e){var t=e.relatedNode||e.target;n.push({target:t,attributeName:e.attrName})}var n=[],r;this.observe=function(n){r=n,r.addEventListener("DOMSubtreeModified",e,!1),r.addEventListener("DOMNodeInsertedIntoDocument",e,!1),r.addEventListener("DOMNodeInserted",e,!1),r.addEventListener("DOMAttrModified",t,!1)},this.disconnect=function(){r.removeEventListener("DOMSubtreeModified",e,!1),r.removeEventListener("DOMNodeInsertedIntoDocument",e,!1),r.removeEventListener("DOMNodeInserted",e,!1),r.removeEventListener("DOMAttrModified",t,!1)},this.takeRecords=function(){return n}}),f.on("keydown",function(e){var t=e.keyCode==te,n=e.ctrlKey||e.metaKey;if(!m(e)&&(t||e.keyCode==ee)){var r=f.selection.getRng(),i=r.startContainer,o=r.startOffset;if(t&&e.shiftKey)return;if(p(t,r))return void e.preventDefault
();if(!n&&r.collapsed&&3==i.nodeType&&(t?o<i.data.length:o>0))return;e.preventDefault(),n&&f.selection.getSel().modify("extend",t?"forward":"backward",e.metaKey?"lineboundary":"word"),h(t)}}),f.on("keypress",function(t){if(!m(t)&&!w.isCollapsed()&&t.charCode>31&&!e.metaKeyPressed(t)){var n,r,i,o,a,s;n=f.selection.getRng(),s=String.fromCharCode(t.charCode),t.preventDefault(),r=Z(n.startContainer).parents().filter(function(e,t){return!!f.schema.getTextInlineElements()[t.nodeName]}),h(!0),r=r.filter(function(e,t){return!Z.contains(f.getBody(),t)}),r.length?(i=x.createFragment(),r.each(function(e,t){t=t.cloneNode(!1),i.hasChildNodes()?(t.appendChild(i.firstChild),i.appendChild(t)):(a=t,i.appendChild(t)),i.appendChild(t)}),a.appendChild(f.getDoc().createTextNode(s)),o=x.getParent(n.startContainer,x.isBlock),x.isEmpty(o)?Z(o).empty().append(i):n.insertNode(i),n.setS
tart(a.firstChild,1),n.setEnd(a.firstChild,1),f.selection.setRng(n)):f.selection.setContent(s)}}),f.addCommand("Delete",function(){h()}),f.addCommand("ForwardDelete",function(){h(!0)}),N||(f.on("dragstart",function(e){_=w.getRng(),g(e)}),f.on("drop",function(e){if(!m(e)){var n=v(e);n&&(e.preventDefault(),l.setEditorTimeout(f,function(){var r=t.getCaretRangeFromPoint(e.x,e.y,C);_&&(w.setRng(_),_=null,b()),w.setRng(r),y(n.html)}))}}),f.on("cut",function(e){m(e)||!e.clipboardData||f.selection.isCollapsed()||(e.preventDefault(),e.clipboardData.clearData(),e.clipboardData.setData("text/html",f.selection.getContent()),e.clipboardData.setData("text/plain",f.selection.getContent({format:"text"})),l.setEditorTimeout(f,function(){b(!0)}))}))}function C(){function e(e){var t=ne.create("body"),n=e.cloneContents();return t.appendChild(n),re.serializer.serialize(t,{format:"html"})}f
unction n(n){if(!n.setStart){if(n.item)return!1;var r=n.duplicate();return r.moveToElementText(f.getBody()),t.compareRanges(n,r)}var i=e(n),o=ne.createRng();o.selectNode(f.getBody());var a=e(o);return i===a}f.on("keydown",function(e){var t=e.keyCode,r,i;if(!m(e)&&(t==te||t==ee)){if(r=f.selection.isCollapsed(),i=f.getBody(),r&&!ne.isEmpty(i))return;if(!r&&!n(f.selection.getRng()))return;e.preventDefault(),f.setContent(""),i.firstChild&&ne.isBlock(i.firstChild)?f.selection.setCursorLocation(i.firstChild,0):f.selection.setCursorLocation(i,0),f.nodeChanged()}})}function x(){f.shortcuts.add("meta+a",null,"SelectAll")}function w(){f.settings.content_editable||ne.bind(f.getDoc(),"mousedown mouseup",function(e){var t;if(e.target==f.getDoc().documentElement)if(t=re.getRng(),f.getBody().focus(),"mousedown"==e.type){if(u.isCaretContainer(t.startContainer))return;re.placeCaretAt(e.clientX,e.clientY)}else
re.setRng(t)})}function E(){f.on("keydown",function(e){if(!m(e)&&e.keyCode===ee){if(!f.getBody().getElementsByTagName("hr").length)return;if(re.isCollapsed()&&0===re.getRng(!0).startOffset){var t=re.getNode(),n=t.previousSibling;if("HR"==t.nodeName)return ne.remove(t),void e.preventDefault();n&&n.nodeName&&"hr"===n.nodeName.toLowerCase()&&(ne.remove(n),e.preventDefault())}}})}function N(){window.Range.prototype.getClientRects||f.on("mousedown",function(e){if(!m(e)&&"HTML"===e.target.nodeName){var t=f.getBody();t.blur(),l.setEditorTimeout(f,function(){t.focus()})}})}function _(){f.on("click",function(e){var t=e.target;/^(IMG|HR)$/.test(t.nodeName)&&"false"!==ne.getContentEditableParent(t)&&(e.preventDefault(),re.select(t),f.nodeChanged()),"A"==t.nodeName&&ne.hasClass(t,"mce-item-anchor")&&(e.preventDefault
(),re.select(t))})}function S(){function e(){var e=ne.getAttribs(re.getStart().cloneNode(!1));return function(){var t=re.getStart();t!==f.getBody()&&(ne.setAttrib(t,"style",null),Q(e,function(e){t.setAttributeNode(e.cloneNode(!0))}))}}function t(){return!re.isCollapsed()&&ne.getParent(re.getStart(),ne.isBlock)!=ne.getParent(re.getEnd(),ne.isBlock)}f.on("keypress",function(n){var r;if(!m(n)&&(8==n.keyCode||46==n.keyCode)&&t())return r=e(),f.getDoc().execCommand("delete",!1,null),r(),n.preventDefault(),!1}),ne.bind(f.getDoc(),"cut",function(n){var r;!m(n)&&t()&&(r=e(),l.setEditorTimeout(f,function(){r()}))})}function k(){document.body.setAttribute("role","application")}function T(){f.on("keydown",function(e){if(!m(e)&&e.keyCode===ee&&re.isCollapsed()&&0===re.getRng(!0).startOffset){var t=re.getNode().previousSibling;if(t&&t.nodeName&
&"table"===t.nodeName.toLowerCase())return e.preventDefault(),!1}})}function R(){h()>7||(p("RespectVisibilityInDesign",!0),f.contentStyles.push(".mceHideBrInPre pre br {display: none}"),ne.addClass(f.getBody(),"mceHideBrInPre"),oe.addNodeFilter("pre",function(e){for(var t=e.length,n,r,o,a;t--;)for(n=e[t].getAll("br"),r=n.length;r--;)o=n[r],a=o.prev,a&&3===a.type&&"\n"!=a.value.charAt(a.value-1)?a.value+="\n":o.parent.insert(new i("#text",3),o,!0).value="\n"}),ae.addNodeFilter("pre",function(e){for(var t=e.length,n,r,i,o;t--;)for(n=e[t].getAll("br"),r=n.length;r--;)i=n[r],o=i.prev,o&&3==o.type&&(o.value=o.value.replace(/\r?\n$/,""))}))}function A(){ne.bind(f.getBody(),"mouseup",function(){var e,t=re.getNode();"IMG"==t.nodeName&&((e=ne.getStyle(t,"width"))&&(ne.setAttrib(t,
"width",e.replace(/[^0-9%]+/g,"")),ne.setStyle(t,"width","")),(e=ne.getStyle(t,"height"))&&(ne.setAttrib(t,"height",e.replace(/[^0-9%]+/g,"")),ne.setStyle(t,"height","")))})}function B(){f.on("keydown",function(t){var n,r,i,o,a;if(!m(t)&&t.keyCode==e.BACKSPACE&&(n=re.getRng(),r=n.startContainer,i=n.startOffset,o=ne.getRoot(),a=r,n.collapsed&&0===i)){for(;a&&a.parentNode&&a.parentNode.firstChild==a&&a.parentNode!=o;)a=a.parentNode;"BLOCKQUOTE"===a.tagName&&(f.formatter.toggle("blockquote",null,a),n=ne.createRng(),n.setStart(r,0),n.setEnd(r,0),re.setRng(n))}})}function D(){function e(){K(),p("StyleWithCSS",!1),p("enableInlineTableEditing",!1),ie.object_resizing||p("enableObjectResizing",!1)}ie.readonly||f.on("BeforeExecCommand MouseDown",e)}function L(){function e(
){Q(ne.select("a"),function(e){var t=e.parentNode,n=ne.getRoot();if(t.lastChild===e){for(;t&&!ne.isBlock(t);){if(t.parentNode.lastChild!==t||t===n)return;t=t.parentNode}ne.add(t,"br",{"data-mce-bogus":1})}})}f.on("SetContent ExecCommand",function(t){"setcontent"!=t.type&&"mceInsertLink"!==t.command||e()})}function M(){ie.forced_root_block&&f.on("init",function(){p("DefaultParagraphSeparator",ie.forced_root_block)})}function P(){f.on("keydown",function(e){var t;m(e)||e.keyCode!=ee||(t=f.getDoc().selection.createRange(),t&&t.item&&(e.preventDefault(),f.undoManager.beforeChange(),ne.remove(t.item(0)),f.undoManager.add()))})}function O(){var e;h()>=10&&(e="",Q("p div h1 h2 h3 h4 h5 h6".split(" "),function(t,n){e+=(n>0?",":"")+t+":empty"}),f.contentStyles.push(e+"{padding-right: 1px
!important}"))}function H(){h()<9&&(oe.addNodeFilter("noscript",function(e){for(var t=e.length,n,r;t--;)n=e[t],r=n.firstChild,r&&n.attr("data-mce-innertext",r.value)}),ae.addNodeFilter("noscript",function(e){for(var t=e.length,n,r,a;t--;)n=e[t],r=e[t].firstChild,r?r.value=o.decode(r.value):(a=n.attributes.map["data-mce-innertext"],a&&(n.attr("data-mce-innertext",null),r=new i("#text",3),r.value=a,r.raw=!0,n.append(r)))}))}function I(){function e(e,t){var n=i.createTextRange();try{n.moveToPoint(e,t)}catch(r){n=null}return n}function t(t){var r;t.button?(r=e(t.x,t.y),r&&(r.compareEndPoints("StartToStart",a)>0?r.setEndPoint("StartToStart",a):r.setEndPoint("EndToEnd",a),r.select())):n()}function n(){var e=r.selection.createRange();a&&!e.item&&0===e.compareEndPoints("StartToEnd",e)&&a.select(),ne.unbind(r,"mouseup&quo
t;,n),ne.unbind(r,"mousemove",t),a=o=0}var r=ne.doc,i=r.body,o,a,s;r.documentElement.unselectable=!0,ne.bind(r,"mousedown contextmenu",function(i){if("HTML"===i.target.nodeName){if(o&&n(),s=r.documentElement,s.scrollHeight>s.clientHeight)return;o=1,a=e(i.x,i.y),a&&(ne.bind(r,"mouseup",n),ne.bind(r,"mousemove",t),ne.getRoot().focus(),a.select())}})}function F(){f.on("keyup focusin mouseup",function(t){65==t.keyCode&&e.metaKeyPressed(t)||re.normalize()},!0)}function z(){f.contentStyles.push("img:-moz-broken {-moz-force-broken-image-icon:1;min-width:24px;min-height:24px}")}function U(){f.inline||f.on("keydown",function(){document.activeElement==document.body&&f.getWin().focus()})}function W(){f.inline||(f.contentStyles.push("body {min-height: 150px}"),f.on("click",function(e){var t;if("HTML"==e.target.nodeName){if(a.ie>11)return void f.getB
ody().focus();t=f.selection.getRng(),f.getBody().focus(),f.selection.setRng(t),f.selection.normalize(),f.nodeChanged()}}))}function V(){a.mac&&f.on("keydown",function(t){!e.metaKeyPressed(t)||t.shiftKey||37!=t.keyCode&&39!=t.keyCode||(t.preventDefault(),f.selection.getSel().modify("move",37==t.keyCode?"backward":"forward","lineboundary"))})}function $(){p("AutoUrlDetect",!1)}function q(){f.on("click",function(e){var t=e.target;do if("A"===t.tagName)return void e.preventDefault();while(t=t.parentNode)}),f.contentStyles.push(".mce-content-body {-webkit-touch-callout: none}")}function j(){f.on("init",function(){f.dom.bind(f.getBody(),"submit",function(e){e.preventDefault()})})}function Y(){oe.addNodeFilter("br",function(e){for(var t=e.length;t--;)"Apple-interchange-newline"==e[t].attr("class")&&e[t].remove()})}function X(){f
.on("dragstart",function(e){g(e)}),f.on("drop",function(e){if(!m(e)){var n=v(e);if(n&&n.id!=f.id){e.preventDefault();var r=t.getCaretRangeFromPoint(e.x,e.y,f.getDoc());re.setRng(r),y(n.html)}}})}function K(){}function G(){var e;return se?(e=f.selection.getSel(),!e||!e.rangeCount||0===e.rangeCount):0}function J(){function t(e){var t=new d(e.getBody()),n=e.selection.getRng(),r=c.fromRangeStart(n),i=c.fromRangeEnd(n),o=t.prev(r),a=t.next(i);return!e.selection.isCollapsed()&&(!o||o.isAtStart()&&r.isEqual(o))&&(!a||a.isAtEnd()&&r.isEqual(a))}f.on("keypress",function(n){!m(n)&&!re.isCollapsed()&&n.charCode>31&&!e.metaKeyPressed(n)&&t(f)&&(n.preventDefault(),f.setContent(String.fromCharCode(n.charCode)),f.selection.select(f.getBody(),!0),f.selection.collapse(!1),f.nodeChanged())}),f.on("keydown",function(e){var n=e.keyCode;m(e)||n!=te&&n!=ee||t(f)&&(e.p
reventDefault(),f.setContent(""),f.nodeChanged())})}var Q=s.each,Z=f.$,ee=e.BACKSPACE,te=e.DELETE,ne=f.dom,re=f.selection,ie=f.settings,oe=f.parser,ae=f.serializer,se=a.gecko,le=a.ie,ue=a.webkit,ce="data:text/mce-internal,",de=le?"Text":"URL";return B(),C(),a.windowsPhone||F(),ue&&(J(),b(),w(),_(),M(),j(),T(),Y(),a.iOS?(U(),W(),q()):x()),le&&a.ie<11&&(E(),k(),R(),A(),P(),O(),H(),I()),a.ie>=11&&(W(),T()),a.ie&&(x(),$(),X()),se&&(J(),E(),N(),S(),D(),L(),z(),V(),T()),{refreshContentEditable:K,isHidden:G}}}),r(Ue,[pe,w,m],function(e,t,n){function r(e,t){return"selectionchange"==t?e.getDoc():!e.inline&&/^mouse|touch|click|contextmenu|drop|dragover|dragend/.test(t)?e.getDoc().documentElement:e.settings.event_root?(e.eventRoot||(e.eventRoot=o.select(e.settings.event_root)[0]),e.eventRoot):e.getBody()}function i(e,t){function n(e){return!e.hidden&&!e.readonly}var i=r(e,t),
s;if(e.delegates||(e.delegates={}),!e.delegates[t])if(e.settings.event_root){if(a||(a={},e.editorManager.on("removeEditor",function(){var t;if(!e.editorManager.activeEditor&&a){for(t in a)e.dom.unbind(r(e,t));a=null}})),a[t])return;s=function(r){for(var i=r.target,a=e.editorManager.editors,s=a.length;s--;){var l=a[s].getBody();(l===i||o.isChildOf(i,l))&&n(a[s])&&a[s].fire(t,r)}},a[t]=s,o.bind(i,t,s)}else s=function(r){n(e)&&e.fire(t,r)},o.bind(i,t,s),e.delegates[t]=s}var o=t.DOM,a,s={bindPendingEventDelegates:function(){var e=this;n.each(e._pendingNativeEvents,function(t){i(e,t)})},toggleNativeEvent:function(e,t){var n=this;"focus"!=e&&"blur"!=e&&(t?n.initialized?i(n,e):n._pendingNativeEvents?n._pendingNativeEvents.push(e):n._pendingNativeEvents=[e]:n.initialized&&(n.dom.unbind(r(n,e),e,n.delegates[e]),delete n.delegates[e]))},unbindAllNativeEvents:function(){var e=this,t;if(e.delegates){for(t in e
.delegates)e.dom.unbind(r(e,t),t,e.delegates[t]);delete e.delegates}e.inline||(e.getBody().onload=null,e.dom.unbind(e.getWin()),e.dom.unbind(e.getDoc())),e.dom.unbind(e.getBody()),e.dom.unbind(e.getContainer())}};return s=n.extend({},e,s)}),r(We,[],function(){function e(e,t,n){try{e.getDoc().execCommand(t,!1,n)}catch(r){}}function t(e){var t,n;return t=e.getBody(),n=function(t){e.dom.getParents(t.target,"a").length>0&&t.preventDefault()},e.dom.bind(t,"click",n),{unbind:function(){e.dom.unbind(t,"click",n)}}}function n(n,r){n._clickBlocker&&(n._clickBlocker.unbind(),n._clickBlocker=null),r?(n._clickBlocker=t(n),n.selection.controlSelection.hideResizeRect(),n.readonly=!0,n.getBody().contentEditable=!1):(n.readonly=!1,n.getBody().contentEditable=!0,e(n,"StyleWithCSS",!1),e(n,"enableInlineTableEditing",!1),e(n,"enableObjectResizing",!1),n.focus(),n.nodeChanged())}function r(e,t){var r=e.readonly?"readonl
y":"design";t!=r&&(e.initialized?n(e,"readonly"==t):e.on("init",function(){n(e,"readonly"==t)}),e.fire("SwitchMode",{mode:t}))}return{setMode:r}}),r(Ve,[m,d],function(e,t){var n=e.each,r=e.explode,i={f9:120,f10:121,f11:122},o=e.makeMap("alt,ctrl,shift,meta,access");return function(a){function s(e){var a,s,l={};n(r(e,"+"),function(e){e in o?l[e]=!0:/^[0-9]{2,}$/.test(e)?l.keyCode=parseInt(e,10):(l.charCode=e.charCodeAt(0),l.keyCode=i[e]||e.toUpperCase().charCodeAt(0))}),a=[l.keyCode];for(s in o)l[s]?a.push(s):l[s]=!1;return l.id=a.join(","),l.access&&(l.alt=!0,t.mac?l.ctrl=!0:l.shift=!0),l.meta&&(t.mac?l.meta=!0:(l.ctrl=!0,l.meta=!1)),l}function l(t,n,i,o){var l;return l=e.map(r(t,">"),s),l[l.length-1]=e.extend(l[l.length-1],{func:i,scope:o||a}),e.extend(l[0],{desc:a.translate(n),subpatterns:l.slice(1)})}function u(e){return e.altKey||e.ctrlKey||e.metaKey}function
c(e){return"keydown"===e.type&&e.keyCode>=112&&e.keyCode<=123}function d(e,t){return!!t&&(t.ctrl==e.ctrlKey&&t.meta==e.metaKey&&(t.alt==e.altKey&&t.shift==e.shiftKey&&(!!(e.keyCode==t.keyCode||e.charCode&&e.charCode==t.charCode)&&(e.preventDefault(),!0))))}function f(e){return e.func?e.func.call(e.scope):null}var p=this,h={},m=[];a.on("keyup keypress keydown",function(e){!u(e)&&!c(e)||e.isDefaultPrevented()||(n(h,function(t){if(d(e,t))return m=t.subpatterns.slice(0),"keydown"==e.type&&f(t),!0}),d(e,m[0])&&(1===m.length&&"keydown"==e.type&&f(m[0]),m.shift()))}),p.add=function(t,i,o,s){var u;return u=o,"string"==typeof o?o=function(){a.execCommand(u,!1,null)}:e.isArray(u)&&(o=function(){a.execCommand(u[0],u[1],u[2])}),n(r(e.trim(t.toLowerCase())),function(e){var t=l(e,i,o,s);h[t.id]=t}),!0},p.remove=function(e)
{var t=l(e);return!!h[t.id]&&(delete h[t.id],!0)}}}),r($e,[u,m,z],function(e,t,n){return function(r,i){function o(e){var t,n;return n={"image/jpeg":"jpg","image/jpg":"jpg","image/gif":"gif","image/png":"png"},t=n[e.blob().type.toLowerCase()]||"dat",e.filename()+"."+t}function a(e,t){return e?e.replace(/\/$/,"")+"/"+t.replace(/^\//,""):t}function s(e){return{id:e.id,blob:e.blob,base64:e.base64,filename:n.constant(o(e))}}function l(e,t,n,r){var o,s;o=new XMLHttpRequest,o.open("POST",i.url),o.withCredentials=i.credentials,o.upload.onprogress=function(e){r(e.loaded/e.total*100)},o.onerror=function(){n("Image upload failed due to a XHR Transport error. Code: "+o.status)},o.onload=function(){var e;return 200!=o.status?void n("HTTP Error: "+o.status):(e=JSON.parse(o.responseText),e&&"string"==typeof e.locat
ion?void t(a(i.basePath,e.location)):void n("Invalid JSON: "+o.responseText))},s=new FormData,s.append("file",e.blob(),e.filename()),o.send(s)}function u(){return new e(function(e){e([])})}function c(e,t){return{url:t,blobInfo:e,status:!0}}function d(e,t){return{url:"",blobInfo:e,status:!1,error:t}}function f(e,n){t.each(y[e],function(e){e(n)}),delete y[e]}function p(t,n,i){return r.markPending(t.blobUri()),new e(function(e){var o,a,l=function(){};try{var u=function(){o&&(o.close(),a=l)},p=function(n){u(),r.markUploaded(t.blobUri(),n),f(t.blobUri(),c(t,n)),e(c(t,n))},h=function(n){u(),r.removeFailed(t.blobUri()),f(t.blobUri(),d(t,n)),e(d(t,n))};a=function(e){e<0||e>100||(o||(o=i()),o.progressBar.value(e))},n(s(t),p,h,a)}catch(m){e(d(t,m.message))}})}function h(e){return e===l}function m(t){var n=t.blobUri();return new e(function(e){y[n]=y[n]||[],y[n].push(e)})}function g(n,o){return n=t.grep(n,function(e){return!r.isUploaded(e.blobUri())})
,e.all(t.map(n,function(e){return r.isPending(e.blobUri())?m(e):p(e,i.handler,o)}))}function v(e,t){return!i.url&&h(i.handler)?u():g(e,t)}var y={};return i=t.extend({credentials:!1,handler:l},i),{upload:v}}}),r(qe,[u],function(e){function t(t){return new e(function(e){var n=new XMLHttpRequest;n.open("GET",t,!0),n.responseType="blob",n.onload=function(){200==this.status&&e(this.response)},n.send()})}function n(e){var t,n;return e=decodeURIComponent(e).split(","),n=/data:([^;]+)/.exec(e[0]),n&&(t=n[1]),{type:t,data:e[1]}}function r(t){return new e(function(e){var r,i,o;t=n(t);try{r=atob(t.data)}catch(a){return void e(new Blob([]))}for(i=new Uint8Array(r.length),o=0;o<i.length;o++)i[o]=r.charCodeAt(o);e(new Blob([i],{type:t.type}))})}function i(e){return 0===e.indexOf("blob:")?t(e):0===e.indexOf("data:")?r(e):null}function o(t){return new e(function(e){var n=new FileReader;n.onloadend=function(){e(n.result)},n
.readAsDataURL(t)})}return{uriToBlob:i,blobToDataUri:o,parseDataUri:n}}),r(je,[u,h,z,qe,d],function(e,t,n,r,i){var o=0,a=function(e){return(e||"blobid")+o++};return function(o,s){function l(l,c){function d(e,t){var n,i;return 0===e.src.indexOf("blob:")?(i=s.getByUri(e.src),void(i?t({image:e,blobInfo:i}):r.uriToBlob(e.src).then(function(o){r.blobToDataUri(o).then(function(l){n=r.parseDataUri(l).data,i=s.create(a(),o,n),s.add(i),t({image:e,blobInfo:i})})}))):(n=r.parseDataUri(e.src).data,i=s.findFirst(function(e){return e.base64()===n}),void(i?t({image:e,blobInfo:i}):r.uriToBlob(e.src).then(function(r){i=s.create(a(),r,n),s.add(i),t({image:e,blobInfo:i})})))}var f,p;return c||(c=n.constant(!0)),f=t.filter(l.getElementsByTagName("img"),function(e){var t=e.src;return!!i.fileApi&&(!e.hasAttribute("data-mce-bogus")&&(!e.hasAttribute("data-mce-placeholder")&&(!(!t||t==i.transparentSrc)&&(0===t.indexOf("b
lob:")?!o.isUploaded(t):0===t.indexOf("data:")&&c(e)))))}),p=t.map(f,function(t){var n;return u[t.src]?new e(function(e){u[t.src].then(function(n){e({image:t,blobInfo:n.blobInfo})})}):(n=new e(function(e){d(t,e)}).then(function(e){return delete u[e.image.src],e})["catch"](function(e){return delete u[t.src],
-e}),u[t.src]=n,n)}),e.all(p)}var u={};return{findAll:l}}}),r(Ye,[h,z],function(e,t){return function(){function n(e,t,n,r){return{id:c(e),filename:c(r||e),blob:c(t),base64:c(n),blobUri:c(URL.createObjectURL(t))}}function r(e){i(e.id())||u.push(e)}function i(e){return o(function(t){return t.id()===e})}function o(t){return e.filter(u,t)[0]}function a(e){return o(function(t){return t.blobUri()==e})}function s(t){u=e.filter(u,function(e){return e.blobUri()!==t||(URL.revokeObjectURL(e.blobUri()),!1)})}function l(){e.each(u,function(e){URL.revokeObjectURL(e.blobUri())}),u=[]}var u=[],c=t.constant;return{create:n,add:r,get:i,getByUri:a,findFirst:o,removeByUri:s,destroy:l}}}),r(Xe,[],function(){return function(){function e(e,t){return{status:e,resultUri:t}}function t(e){return e in d}function n(e){var t=d[e];return t?t.resultUri:null}function r(e){return!!t(e)&&d[e].status===u}function i(e){return!!t(e)&&d[e].status===c}function o(t){d[t]=e(u,null)}function a(t,n){d[t]=e(c,n)
}function s(e){delete d[e]}function l(){d={}}var u=1,c=2,d={};return{hasBlobUri:t,getResultUri:n,isPending:r,isUploaded:i,markPending:o,markUploaded:a,removeFailed:s,destroy:l}}}),r(Ke,[N],function(e){var t=e.PluginManager,n=function(e,n){for(var r in t.urls){var i=t.urls[r]+"/plugin"+n+".js";if(i===e)return r}return null},r=function(e,t){var r=n(t,e.suffix);return r?"Failed to load plugin: "+r+" from url "+t:"Failed to load plugin url: "+t},i=function(e,t){e.notificationManager.open({type:"error",text:t})},o=function(e,t){e._skinLoaded?i(e,t):e.on("SkinLoaded",function(){i(e,t)})},a=function(e,t){o(e,"Failed to upload image: "+t)},s=function(e,t){o(e,r(e,t))};return{pluginLoadError:s,uploadError:a}}),r(Ge,[h,$e,je,Ye,Xe,Ke],function(e,t,n,r,i,o){return function(a){function s(e){return function(t){return a.selection?e(t):[]}}function l(){return"?"+(new Date).getTime()}function u(e,t,n){var r=0;
do r=e.indexOf(t,r),r!==-1&&(e=e.substring(0,r)+n+e.substr(r+t.length),r+=n.length-t.length+1);while(r!==-1);return e}function c(e,t,n){return e=u(e,'src="'+t+'"','src="'+n+'"'),e=u(e,'data-mce-src="'+t+'"','data-mce-src="'+n+'"')}function d(t,n){e.each(a.undoManager.data,function(r){"fragmented"===r.type?r.fragments=e.map(r.fragments,function(e){return c(e,t,n)}):r.content=c(r.content,t,n)})}function f(){return a.notificationManager.open({text:a.translate("Image uploading..."),type:"info",timeout:-1,progressBar:!0})}function p(e,t){C.removeByUri(e.src),d(e.src,t),a.$(e).attr({src:E.images_reuse_filename?t+l():t,"data-mce-src":a.convertURL(t,"src")})}function h(n){return x||(x=new t(N,{url:E.images_upload_url,basePath:E.images_upload_base_path,credentials:E.images_upload_credentials,handler:E.images_upload_handler})),v().then(s(function(t){var r;return r=e.map(t,function(e){return e.blo
bInfo}),x.upload(r,f).then(s(function(r){return r=e.map(r,function(e,n){var r=t[n].image;return e.status&&a.settings.images_replace_blob_uris!==!1?p(r,e.url):e.error&&o.uploadError(a,e.error),{element:r,status:e.status}}),n&&n(r),r}))}))}function m(e){if(E.automatic_uploads!==!1)return h(e)}function g(e){return!E.images_dataimg_filter||E.images_dataimg_filter(e)}function v(){return w||(w=new n(N,C)),w.findAll(a.getBody(),g).then(s(function(t){return e.each(t,function(e){d(e.image.src,e.blobInfo.blobUri()),e.image.src=e.blobInfo.blobUri(),e.image.removeAttribute("data-mce-src")}),t}))}function y(){C.destroy(),N.destroy(),w=x=null}function b(t){return t.replace(/src="(blob:[^"]+)"/g,function(t,n){var r=N.getResultUri(n);if(r)return'src="'+r+'"';var i=C.getByUri(n);return i||(i=e.reduce(a.editorManager.editors,function(e,t){return e||t.editorUpload.blobCache.getByUri(n)},null)),i?'src="data:'+i.blob().type+";base64,&q
uot;+i.base64()+'"':t})}var C=new r,x,w,E=a.settings,N=new i;return a.on("setContent",function(){a.settings.automatic_uploads!==!1?m():v()}),a.on("RawSaveContent",function(e){e.content=b(e.content)}),a.on("getContent",function(e){e.source_view||"raw"==e.format||(e.content=b(e.content))}),a.on("PostRender",function(){a.parser.addNodeFilter("img",function(t){e.each(t,function(e){var t=e.attr("src");if(!C.getByUri(t)){var n=N.getResultUri(t);n&&e.attr("src",n)}})})}),{blobCache:C,uploadImages:h,uploadImagesAuto:m,scanForImages:v,destroy:y}}}),r(Je,[k,$,_,T,g,W,c],function(e,t,n,r,i,o,a){var s=n.isContentEditableFalse;return function(t,n){function r(e,n){var r=o.collapse(e.getBoundingClientRect(),n),i,a,s,l,u;return"BODY"==t.tagName?(i=t.ownerDocument.documentElement,a=t.scrollLeft||i.scrollLeft,s=t.scrollTop||i.scrollTop):(u=t.getBoundingClientRect(),a=t.scrollLeft-u.left,s=t.scrollTo
p-u.top),r.left+=a,r.right+=a,r.top+=s,r.bottom+=s,r.width=1,l=e.offsetWidth-e.clientWidth,l>0&&(n&&(l*=-1),r.left+=l,r.right+=l),r}function l(){var n,r,o,a,s;for(n=i("*[contentEditable=false]",t),a=0;a<n.length;a++)r=n[a],o=r.previousSibling,e.endsWithCaretContainer(o)&&(s=o.data,1==s.length?o.parentNode.removeChild(o):o.deleteData(s.length-1,1)),o=r.nextSibling,e.startsWithCaretContainer(o)&&(s=o.data,1==s.length?o.parentNode.removeChild(o):o.deleteData(0,1));return null}function u(o,a){var l,u;return c(),n(a)?(g=e.insertBlock("p",a,o),l=r(a,o),i(g).css("top",l.top),m=i('<div class="mce-visual-caret" data-mce-bogus="all"></div>').css(l).appendTo(t),o&&m.addClass("mce-visual-caret-before"),d(),u=a.ownerDocument.createRange(),u.setStart(g,0),u.setEnd(g,0),u):(g=e.insertInline(a,o),u=a.ownerDocument.createRange(),s(g.nextSibling)?(u.setStart(g,0),u.setEnd(g,0)):(u.set
Start(g,1),u.setEnd(g,1)),u)}function c(){l(),g&&(e.remove(g),g=null),m&&(m.remove(),m=null),clearInterval(h)}function d(){h=a.setInterval(function(){i("div.mce-visual-caret",t).toggleClass("mce-visual-caret-hidden")},500)}function f(){a.clearInterval(h)}function p(){return".mce-visual-caret {position: absolute;background-color: black;background-color: currentcolor;}.mce-visual-caret-hidden {display: none;}*[data-mce-caret] {position: absolute;left: -1000px;right: auto;top: 0;margin: 0;padding: 0;}"}var h,m,g;return{show:u,hide:c,getCss:p,destroy:f}}}),r(Qe,[h,_,W],function(e,t,n){function r(i){function o(t){return e.map(t,function(e){return e=n.clone(e),e.node=i,e})}if(e.isArray(i))return e.reduce(i,function(e,t){return e.concat(r(t))},[]);if(t.isElement(i))return o(i.getClientRects());if(t.isText(i)){var a=i.ownerDocument.createRange();return a.setStart(i,0),a.setEnd(i,i.data.length),o(a.getClientRects())}}return{getClientRects:r}}),r(
Ze,[z,h,Qe,U,ie,oe,$,W],function(e,t,n,r,i,o,a,s){function l(e,t,n,o){for(;o=i.findNode(o,e,r.isEditableCaretCandidate,t);)if(n(o))return}function u(e,r,i,o,a,s){function u(o){var s,l,u;for(u=n.getClientRects(o),e==-1&&(u=u.reverse()),s=0;s<u.length;s++)if(l=u[s],!i(l,p)){if(f.length>0&&r(l,t.last(f))&&c++,l.line=c,a(l))return!0;f.push(l)}}var c=0,d,f=[],p;return(p=t.last(s.getClientRects()))?(d=s.getNode(),u(d),l(e,o,u,d),f):f}function c(e,t){return t.line>e}function d(e,t){return t.line===e}function f(e,n,r,i){function l(n){return 1==e?t.last(n.getClientRects()):t.last(n.getClientRects())}var u=new o(n),c,d,f,p,h=[],m=0,g,v;1==e?(c=u.next,d=s.isBelow,f=s.isAbove,p=a.after(i)):(c=u.prev,d=s.isAbove,f=s.isBelow,p=a.before(i)),v=l(p);do if(p.isVisible()&&(g=l(p),!f(g,v))){if(h.length>0&&d(g,t.last(h))&&m++,g=s.clone(g),g.position=p,g.line=m,r(g))return h;h.push(g)}while(p=c(p));return h}var p=e.curry,h=p(u,-1,s.isAbove,s.isB
elow),m=p(u,1,s.isBelow,s.isAbove);return{upUntil:h,downUntil:m,positionsUntil:f,isAboveLine:p(c),isLine:p(d)}}),r(et,[z,h,_,Qe,W,ie,U],function(e,t,n,r,i,o,a){function s(e,t){return Math.abs(e.left-t)}function l(e,t){return Math.abs(e.right-t)}function u(e,n){function r(e,t){return e>=t.left&&e<=t.right}return t.reduce(e,function(e,t){var i,o;return i=Math.min(s(e,n),l(e,n)),o=Math.min(s(t,n),l(t,n)),r(n,t)?t:r(n,e)?e:o==i&&m(t.node)?t:o<i?t:e})}function c(e,t,n,r){for(;r=g(r,e,a.isEditableCaretCandidate,t);)if(n(r))return}function d(e,n){function o(e,i){var o;return o=t.filter(r.getClientRects(i),function(t){return!e(t,n)}),a=a.concat(o),0===o.length}var a=[];return a.push(n),c(-1,e,v(o,i.isAbove),n.node),c(1,e,v(o,i.isBelow),n.node),a}function f(e){return t.filter(t.toArray(e.getElementsByTagName("*")),m)}function p(e,t){return{node:e.node,before:s(e,t)<l(e,t)}}function h(e,n,i){var o,a;return o=r.getClientRects(f(e)),o=t.filter(o,function(e)
{return i>=e.top&&i<=e.bottom}),a=u(o,n),a&&(a=u(d(e,a),n),a&&m(a.node))?p(a,n):null}var m=n.isContentEditableFalse,g=o.findNode,v=e.curry;return{findClosestClientRect:u,findLineNodeRects:d,closestCaret:h}}),r(tt,[],function(){var e=function(e){var t,n,r,i;return i=e.getBoundingClientRect(),t=e.ownerDocument,n=t.documentElement,r=t.defaultView,{top:i.top+r.pageYOffset-n.clientTop,left:i.left+r.pageXOffset-n.clientLeft}},t=function(t){return t.inline?e(t.getBody()):{left:0,top:0}},n=function(e){var t=e.getBody();return e.inline?{left:t.scrollLeft,top:t.scrollTop}:{left:0,top:0}},r=function(e){var t=e.getBody(),n=e.getDoc().documentElement,r={left:t.scrollLeft,top:t.scrollTop},i={left:t.scrollLeft||n.scrollLeft,top:t.scrollTop||n.scrollTop};return e.inline?r:i},i=function(t,n){if(n.target.ownerDocument!==t.getDoc()){var i=e(t.getContentAreaContainer()),o=r(t);return{left:n.pageX-i.left+o.left,top:n.pageY-i.top+o.top}}return{left:n.pageX,top:n.pageY}},o=fu
nction(e,t,n){return{pageX:n.left-e.left+t.left,pageY:n.top-e.top+t.top}},a=function(e,r){return o(t(e),n(e),i(e,r))};return{calc:a}}),r(nt,[_,h,z,c,w,tt],function(e,t,n,r,i,o){var a=e.isContentEditableFalse,s=e.isContentEditableTrue,l=function(e,t){return a(t)&&t!==e},u=function(e,t,n){return t!==n&&!e.dom.isChildOf(t,n)&&!a(t)},c=function(e){var t=e.cloneNode(!0);return t.removeAttribute("data-mce-selected"),t},d=function(e,t,n,r){var i=t.cloneNode(!0);e.dom.setStyles(i,{width:n,height:r}),e.dom.setAttrib(i,"data-mce-selected",null);var o=e.dom.create("div",{"class":"mce-drag-container","data-mce-bogus":"all",unselectable:"on",contenteditable:"false"});return e.dom.setStyles(o,{position:"absolute",opacity:.5,overflow:"hidden",border:0,padding:0,margin:0,width:n,height:r}),e.dom.setStyles(i,{margin:0,boxSizing:"border-box"}),o.appendChild(i
),o},f=function(e,t){e.parentNode!==t&&t.appendChild(e)},p=function(e,t,n,r,i,o){var a=0,s=0;e.style.left=t.pageX+"px",e.style.top=t.pageY+"px",t.pageX+n>i&&(a=t.pageX+n-i),t.pageY+r>o&&(s=t.pageY+r-o),e.style.width=n-a+"px",e.style.height=r-s+"px"},h=function(e){e&&e.parentNode&&e.parentNode.removeChild(e)},m=function(e){return 0===e.button},g=function(e){return e.element},v=function(e,t){return{pageX:t.pageX-e.relX,pageY:t.pageY+5}},y=function(e,r){return function(i){if(m(i)){var o=t.find(r.dom.getParents(i.target),n.or(a,s));if(l(r.getBody(),o)){var u=r.dom.getPos(o),c=r.getBody(),f=r.getDoc().documentElement;e.element=o,e.screenX=i.screenX,e.screenY=i.screenY,e.maxX=(r.inline?c.scrollWidth:f.offsetWidth)-2,e.maxY=(r.inline?c.scrollHeight:f.offsetHeight)-2,e.relX=i.pageX-u.x,e.relY=i.pageY-u.y,e.width=o.offsetWidth,e.height=o.offsetHeight,e.ghost=d(r,o,e.width,e.height)}}}},b=function(e,t){var n
=r.throttle(function(e,n){t._selectionOverrides.hideFakeCaret(),t.selection.placeCaretAt(e,n)},0);return function(r){var i=Math.max(Math.abs(r.screenX-e.screenX),Math.abs(r.screenY-e.screenY));if(g(e)&&!e.dragging&&i>10){var a=t.fire("dragstart",{target:e.element});if(a.isDefaultPrevented())return;e.dragging=!0,t.focus()}if(e.dragging){var s=v(e,o.calc(t,r));f(e.ghost,t.getBody()),p(e.ghost,s,e.width,e.height,e.maxX,e.maxY),n(r.clientX,r.clientY)}}},C=function(e){var t=e.getSel().getRangeAt(0),n=t.startContainer;return 3===n.nodeType?n.parentNode:n},x=function(e,t){return function(n){if(e.dragging&&u(t,C(t.selection),e.element)){var r=c(e.element),i=t.fire("drop",{targetClone:r,clientX:n.clientX,clientY:n.clientY});i.isDefaultPrevented()||(r=i.targetClone,t.undoManager.transact(function(){h(e.element),t.insertContent(t.dom.getOuterHTML(r)),t._selectionOverrides.hideFakeCaret()}))}E(e)}},w=function(e,t){return function(){E(e),e.dragging&
amp;&t.fire("dragend")}},E=function(e){e.dragging=!1,e.element=null,h(e.ghost)},N=function(e){var t={},n,r,o,a,s,l;n=i.DOM,l=document,r=y(t,e),o=b(t,e),a=x(t,e),s=w(t,e),e.on("mousedown",r),e.on("mousemove",o),e.on("mouseup",a),n.bind(l,"mousemove",o),n.bind(l,"mouseup",s),e.on("remove",function(){n.unbind(l,"mousemove",o),n.unbind(l,"mouseup",s)})},_=function(e){e.on("drop",function(t){var n="undefined"!=typeof t.clientX?e.getDoc().elementFromPoint(t.clientX,t.clientY):null;(a(n)||a(e.dom.getContentEditableParent(n)))&&t.preventDefault()})},S=function(e){N(e),_(e)};return{init:S}}),r(rt,[d,oe,$,k,ie,Je,Ze,et,_,T,W,I,z,h,c,nt],function(e,t,n,r,i,o,a,s,l,u,c,d,f,p,h,m){function g(e,t){for(;t=e(t);)if(t.isVisible())return t;return t}function v(u){function v(e){return u.dom.hasClass(e,"mce-offscreen-selection")}function _(){var e=u.dom.get(le);return e?e.g
etElementsByTagName("*")[0]:e}function S(e){return u.dom.isBlock(e)}function k(e){e&&u.selection.setRng(e)}function T(){return u.selection.getRng()}function R(e,t){u.selection.scrollIntoView(e,t)}function A(e,t,n){var r;return r=u.fire("ShowCaret",{target:t,direction:e,before:n}),r.isDefaultPrevented()?null:(R(t,e===-1),se.show(n,t))}function B(e){var t;return t=u.fire("BeforeObjectSelected",{target:e}),t.isDefaultPrevented()?null:D(e)}function D(e){var t=e.ownerDocument.createRange();return t.selectNode(e),t}function L(e,t){var n=i.isInSameBlock(e,t);return!(n||!l.isBr(e.getNode()))||n}function M(e,t){return t=i.normalizeRange(e,re,t),e==-1?n.fromRangeStart(t):n.fromRangeEnd(t)}function P(e){return r.isCaretContainerBlock(e.startContainer)}function O(e,t,n,r){var i,o,a,s;return!r.collapsed&&(i=N(r),C(i))?A(e,i,e==-1):(s=P(r),o=M(e,r),n(o)?B(o.getNode(e==-1)):(o=t(o))?n(o)?A(e,o.getNode(e==-1),1==e):(a=t(o),n(a)&&L(o,a)?A(e,a.get
Node(e==-1),1==e):s?$(o.toRange()):null):s?r:null)}function H(e,t,n){var r,i,o,l,u,c,d,f,h;if(h=N(n),r=M(e,n),i=t(re,a.isAboveLine(1),r),o=p.filter(i,a.isLine(1)),u=p.last(r.getClientRects()),E(r)&&(h=r.getNode()),w(r)&&(h=r.getNode(!0)),!u)return null;if(c=u.left,l=s.findClosestClientRect(o,c),l&&C(l.node))return d=Math.abs(c-l.left),f=Math.abs(c-l.right),A(e,l.node,d<f);if(h){var m=a.positionsUntil(e,re,a.isAboveLine(1),h);if(l=s.findClosestClientRect(p.filter(m,a.isLine(1)),c))return $(l.position.toRange());if(l=p.last(p.filter(m,a.isLine(0))))return $(l.position.toRange())}}function I(t,r){function i(){var t=u.dom.create(u.settings.forced_root_block);return(!e.ie||e.ie>=11)&&(t.innerHTML='<br data-mce-bogus="1">'),t}var o,a,s;if(r.collapsed&&u.settings.forced_root_block){if(o=u.dom.getParent(r.startContainer,"PRE"),!o)return;a=1==t?oe(n.fromRangeStart(r)):ae(n.fromRangeStart(r)),a||(s=i(),1==t?u.$(o).after(s
):u.$(o).before(s),u.selection.select(s,!0),u.selection.collapse())}}function F(e,t,n,r){var i;return(i=O(e,t,n,r))?i:(i=I(e,r),i?i:null)}function z(e,t,n){var r;return(r=H(e,t,n))?r:(r=I(e,n),r?r:null)}function U(){return ce("*[data-mce-caret]")[0]}function W(e){e.hasAttribute("data-mce-caret")&&(r.showCaretContainerBlock(e),k(T()),R(e[0]))}function V(e){var t,r;return e=i.normalizeRange(1,re,e),t=n.fromRangeStart(e),C(t.getNode())?A(1,t.getNode(),!t.isAtEnd()):C(t.getNode(!0))?A(1,t.getNode(!0),!1):(r=u.dom.getParent(t.getNode(),f.or(C,b)),C(r)?A(1,r,!1):null)}function $(e){var t;return e&&e.collapsed?(t=V(e),t?t:e):e}function q(e){var t,i,o,a;return C(e)?(C(e.previousSibling)&&(o=e.previousSibling),i=ae(n.before(e)),i||(t=oe(n.after(e))),t&&x(t.getNode())&&(a=t.getNode()),r.remove(e.previousSibling),r.remove(e.nextSibling),u.dom.remove(e),u.dom.isEmpty(u.getBody())?(u.setContent(""),void u.focus()):o?n.after(o)
.toRange():a?n.before(a).toRange():i?i.toRange():t?t.toRange():null):null}function j(e){var t=u.schema.getTextBlockElements();return e.nodeName in t}function Y(e){return u.dom.isEmpty(e)}function X(e,t,r){var i=u.dom,o,a,s,l;if(o=i.getParent(t.getNode(),i.isBlock),a=i.getParent(r.getNode(),i.isBlock),e===-1){if(l=r.getNode(!0),w(r)&&S(l))return j(o)?(Y(o)&&i.remove(o),n.after(l).toRange()):q(r.getNode(!0))}else if(l=t.getNode(),E(t)&&S(l))return j(a)?(Y(a)&&i.remove(a),n.before(l).toRange()):q(t.getNode());if(o===a||!j(o)||!j(a))return null;for(;s=o.firstChild;)a.appendChild(s);return u.dom.remove(o),r.toRange()}function K(e,t,n,i){var o,a,s,l;return!i.collapsed&&(o=N(i),C(o))?$(q(o)):(a=M(e,i),n(a)&&r.isCaretContainerBlock(i.startContainer)?(l=e==-1?ie.prev(a):ie.next(a),l?$(l.toRange()):i):t(a)?$(q(a.getNode(e==-1))):(s=e==-1?ie.prev(a):ie.next(a),t(s)?e===-1?X(e,a,s):X(e,s,a):void 0))}function G(){function i(e,t){var n=t(T());n&
&!e.isDefaultPrevented()&&(e.preventDefault(),k(n))}function o(e){for(var t=u.getBody();e&&e!=t;){if(b(e)||C(e))return e;e=e.parentNode}return null}function l(e,t,n){return!n.collapsed&&p.reduce(n.getClientRects(),function(n,r){return n||c.containsXY(r,e,t)},!1)}function f(e){var t=!1;e.on("touchstart",function(){t=!1}),e.on("touchmove",function(){t=!0}),e.on("touchend",function(e){var n=o(e.target);C(n)&&(t||(e.preventDefault(),Z(B(n))))})}function g(){var e,t=o(u.selection.getNode());b(t)&&S(t)&&u.dom.isEmpty(t)&&(e=u.dom.create("br",{"data-mce-bogus":"1"}),u.$(t).empty().append(e),u.selection.setRng(n.before(e).toRange()))}function x(e){var t=U();if(t)return"compositionstart"==e.type?(e.preventDefault(),e.stopPropagation(),void W(t)):void(r.hasContent(t)&&W(t))}function N(e){var t;switch(e.keyCode){case d.DELETE:t=g();break;case d.BACKSPACE:t=g
()}t&&e.preventDefault()}var R=y(F,1,oe,E),D=y(F,-1,ae,w),L=y(K,1,E,w),M=y(K,-1,w,E),P=y(z,-1,a.upUntil),O=y(z,1,a.downUntil);u.on("mouseup",function(){var e=T();e.collapsed&&k(V(e))}),u.on("click",function(e){var t;t=o(e.target),t&&(C(t)&&(e.preventDefault(),u.focus()),b(t)&&u.dom.isChildOf(t,u.selection.getNode())&&ee())}),u.on("blur NewBlock",function(){ee(),ne()});var H=function(e){var r=new t(e);if(!e.firstChild)return!1;var i=n.before(e.firstChild),o=r.next(i);return o&&!E(o)&&!w(o)},I=function(e,t){var n=u.dom.getParent(e,u.dom.isBlock),r=u.dom.getParent(t,u.dom.isBlock);return n===r},j=function(e){return!(e.keyCode>=112&&e.keyCode<=123)},Y=function(e,t){var n=u.dom.getParent(e,u.dom.isBlock),r=u.dom.getParent(t,u.dom.isBlock);return n&&!I(n,r)&&H(n)};f(u),u.on("mousedown",function(e){var t;if(t=o(e.target))C(t)?(e.preventDefault(),Z(B(t))):l(e
.clientX,e.clientY,u.selection.getRng())||u.selection.placeCaretAt(e.clientX,e.clientY);else{ee(),ne();var n=s.closestCaret(re,e.clientX,e.clientY);n&&(Y(e.target,n.node)||(e.preventDefault(),u.getBody().focus(),k(A(1,n.node,n.before))))}}),u.on("keydown",function(e){if(!d.modifierPressed(e))switch(e.keyCode){case d.RIGHT:i(e,R);break;case d.DOWN:i(e,O);break;case d.LEFT:i(e,D);break;case d.UP:i(e,P);break;case d.DELETE:i(e,L);break;case d.BACKSPACE:i(e,M);break;default:C(u.selection.getNode())&&j(e)&&e.preventDefault()}}),u.on("keyup compositionstart",function(e){x(e),N(e)},!0),u.on("cut",function(){var e=u.selection.getNode();C(e)&&h.setEditorTimeout(u,function(){k($(q(e)))})}),u.on("getSelectionRange",function(e){var t=e.range;if(ue){if(!ue.parentNode)return void(ue=null);t=t.cloneRange(),t.selectNode(ue),e.range=t}}),u.on("setSelectionRange",function(e){var t;t=Z(e.range),t&&(e.range=t)}),u
.on("AfterSetSelectionRange",function(e){var t=e.range;Q(t)||ne(),v(t.startContainer.parentNode)||ee()}),u.on("focus",function(){h.setEditorTimeout(u,function(){u.selection.setRng($(u.selection.getRng()))},0)}),u.on("copy",function(t){var n=t.clipboardData;if(!t.isDefaultPrevented()&&t.clipboardData&&!e.ie){var r=_();r&&(t.preventDefault(),n.clearData(),n.setData("text/html",r.outerHTML),n.setData("text/plain",r.outerText))}}),m.init(u)}function J(){var e=u.contentStyles,t=".mce-content-body";e.push(se.getCss()),e.push(t+" .mce-offscreen-selection {position: absolute;left: -9999999999px;max-width: 1000000px;}"+t+" *[contentEditable=false] {cursor: default;}"+t+" *[contentEditable=true] {cursor: text;}")}function Q(e){return r.isCaretContainer(e.startContainer)||r.isCaretContainer(e.endContainer)}function Z(t){var n,r=u.$,i=u.dom,o,a,s,l,c,d,f,p,h;if(!t)return null;if(t.c
ollapsed){if(!Q(t)){if(f=M(1,t),C(f.getNode()))return A(1,f.getNode(),!f.isAtEnd());if(C(f.getNode(!0)))return A(1,f.getNode(!0),!1)}return null}return s=t.startContainer,l=t.startOffset,c=t.endOffset,3==s.nodeType&&0==l&&C(s.parentNode)&&(s=s.parentNode,l=i.nodeIndex(s),s=s.parentNode),1!=s.nodeType?null:(c==l+1&&(n=s.childNodes[l]),C(n)?(p=h=n.cloneNode(!0),d=u.fire("ObjectSelected",{target:n,targetClone:p}),d.isDefaultPrevented()?null:(p=d.targetClone,o=r("#"+le),0===o.length&&(o=r('<div data-mce-bogus="all" class="mce-offscreen-selection"></div>').attr("id",le),o.appendTo(u.getBody())),t=u.dom.createRng(),p===h&&e.ie?(o.empty().append('<p style="font-size: 0" data-mce-bogus="all">\xa0</p>').append(p),t.setStartAfter(o[0].firstChild.firstChild),t.setEndAfter(p)):(o.empty().append("\xa0").append(p).append("\xa0"),t.setSta
rt(o[0].firstChild,1),t.setEnd(o[0].lastChild,0)),o.css({top:i.getPos(n,u.getBody()).y}),o[0].focus(),a=u.selection.getSel(),a.removeAllRanges(),a.addRange(t),u.$("*[data-mce-selected]").removeAttr("data-mce-selected"),n.setAttribute("data-mce-selected",1),ue=n,ne(),t)):null)}function ee(){ue&&(ue.removeAttribute("data-mce-selected"),u.$("#"+le).remove(),ue=null)}function te(){se.destroy(),ue=null}function ne(){se.hide()}var re=u.getBody(),ie=new t(re),oe=y(g,ie.next),ae=y(g,ie.prev),se=new o(u.getBody(),S),le="sel-"+u.dom.uniqueId(),ue,ce=u.$;return e.ceFalse&&(G(),J()),{showBlockCaretContainer:W,hideFakeCaret:ne,destroy:te}}var y=f.curry,b=l.isContentEditableTrue,C=l.isContentEditableFalse,x=l.isElement,w=i.isAfterContentEditableFalse,E=i.isBeforeContentEditableFalse,N=u.getSelectedNode;return v}),r(it,[],function(){var e=0,t=function(){var e=function(){return Math.round(4294967295*Math.random()).toString(
36)},t=(new Date).getTime();return"s"+t.toString(36)+e()+e()+e()},n=function(n){return n+e++ +t()};return{uuid:n}}),r(ot,[],function(){var e=function(e,t,n){var r=e.sidebars?e.sidebars:[];r.push({name:t,settings:n}),e.sidebars=r};return{add:e}}),r(at,[w,g,N,R,A,O,P,Y,J,te,ne,re,le,ue,E,f,Le,Ie,B,L,ze,d,m,c,Ue,We,Ve,Ge,rt,it,ot,Ke],function(e,n,r,i,o,a,s,l,u,c,d,f,p,h,m,g,v,y,b,C,x,w,E,N,_,S,k,T,R,A,B,D){function L(e,t,i){var o=this,a,s,l;a=o.documentBaseUrl=i.documentBaseURL,s=i.baseURI,l=i.defaultSettings,t=H({id:e,theme:"modern",delta_width:0,delta_height:0,popup_css:"",plugins:"",document_base_url:a,add_form_submit_trigger:!0,submit_patch:!0,add_unload_trigger:!0,convert_urls:!0,relative_urls:!0,remove_script_host:!0,object_resizing:!0,doctype:"<!DOCTYPE html>",visual:!0,font_size_style_values:"xx-small,x-small,small,medium,large,x-large,xx-large",font_size_legacy_values:"xx-small,small,medium,large,x-large,xx
-large,300%",forced_root_block:"p",hidden_input:!0,padd_empty_editor:!0,render_ui:!0,indentation:"30px",inline_styles:!0,convert_fonts_to_spans:!0,indent:"simple",indent_before:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,figcaption,option,optgroup,datalist",indent_after:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,figcaption,option,optgroup,datalist",validate:!0,entity_encoding:"named",url_converter:o.convertURL,url_converter_scope:o,ie7_compat:!0},l,t),l&&l.external_plugins&&t.external_plugins&&(t.external_plugins=H({},l.external_plugins,t.external_plugins)),o.settings=t,r.language=t.language||"en",r.languageLoad=t.language_load,r.baseURL=i.baseURL,o.id=t.id=e,o.setDirty(!1),
o.plugins={},o.documentBaseURI=new h(t.document_base_url||a,{base_uri:s}),o.baseURI=s,o.contentCSS=[],o.contentStyles=[],o.shortcuts=new k(o),o.loadedCSS={},o.editorCommands=new p(o),o.suffix=i.suffix,o.editorManager=i,o.inline=t.inline,o.settings.content_editable=o.inline,t.cache_suffix&&(w.cacheSuffix=t.cache_suffix.replace(/^[\?\&]+/,"")),t.override_viewport===!1&&(w.overrideViewPort=!1),i.fire("SetupEditor",o),o.execCallback("setup",o),o.$=n.overrideDefaults(function(){return{context:o.inline?o.getBody():o.getDoc(),element:o.getBody()}})}var M=e.DOM,P=r.ThemeManager,O=r.PluginManager,H=E.extend,I=E.each,F=E.explode,z=E.inArray,U=E.trim,W=E.resolve,V=g.Event,$=w.gecko,q=w.ie;return L.prototype={render:function(){function e(){M.unbind(window,"ready",e),n.render()}function t(){var e=m.ScriptLoader;if(r.language&&"en"!=r.language&&!r.language_url&&(r.language_url=n.editorManager.baseURL+&qu
ot;/langs/"+r.language+".js"),r.language_url&&e.add(r.language_url),r.theme&&"function"!=typeof r.theme&&"-"!=r.theme.charAt(0)&&!P.urls[r.theme]){var t=r.theme_url;t=t?n.documentBaseURI.toAbsolute(t):"themes/"+r.theme+"/theme"+o+".js",P.load(r.theme,t)}E.isArray(r.plugins)&&(r.plugins=r.plugins.join(" ")),I(r.external_plugins,function(e,t){O.load(t,e),r.plugins+=" "+t}),I(r.plugins.split(/[ ,]/),function(e){if(e=U(e),e&&!O.urls[e])if("-"==e.charAt(0)){e=e.substr(1,e.length);var t=O.dependencies(e);I(t,function(e){var t={prefix:"plugins/",resource:e,suffix:"/plugin"+o+".js"};e=O.createUrl(t,e),O.load(e.resource,e)})}else O.load(e,{prefix:"plugins/",resource:e,suffix:"/plugin"+o+".js"})}),e.loadQueue(function(){n.removed||n.init()},n,function(e){D.pluginLoadError(n,e[0]),n.removed||n.
init()})}var n=this,r=n.settings,i=n.id,o=n.suffix;if(!V.domLoaded)return void M.bind(window,"ready",e);if(n.getElement()&&w.contentEditable){r.inline?n.inline=!0:(n.orgVisibility=n.getElement().style.visibility,n.getElement().style.visibility="hidden");var a=n.getElement().form||M.getParent(i,"form");a&&(n.formElement=a,r.hidden_input&&!/TEXTAREA|INPUT/i.test(n.getElement().nodeName)&&(M.insertAfter(M.create("input",{type:"hidden",name:i}),i),n.hasHiddenInput=!0),n.formEventDelegate=function(e){n.fire(e.type,e)},M.bind(a,"submit reset",n.formEventDelegate),n.on("reset",function(){n.setContent(n.startContent,{format:"raw"})}),!r.submit_patch||a.submit.nodeType||a.submit.length||a._mceOldSubmit||(a._mceOldSubmit=a.submit,a.submit=function(){return n.editorManager.triggerSave(),n.setDirty(!1),a._mceOldSubmit(a)})),n.windowManager=new v(n),n.notificationManager=new y(n),"
;xml"==r.encoding&&n.on("GetContent",function(e){e.save&&(e.content=M.encode(e.content))}),r.add_form_submit_trigger&&n.on("submit",function(){n.initialized&&n.save()}),r.add_unload_trigger&&(n._beforeUnload=function(){!n.initialized||n.destroyed||n.isHidden()||n.save({format:"raw",no_events:!0,set_dirty:!1})},n.editorManager.on("BeforeUnload",n._beforeUnload)),n.editorManager.add(n),t()}},init:function(){function e(n){var r=O.get(n),i,o;if(i=O.urls[n]||t.documentBaseUrl.replace(/\/$/,""),n=U(n),r&&z(m,n)===-1){if(I(O.dependencies(n),function(t){e(t)}),t.plugins[n])return;o=new r(t,i,t.$),t.plugins[n]=o,o.init&&(o.init(t,i),m.push(n))}}var t=this,n=t.settings,r=t.getElement(),i,o,a,s,l,u,c,d,f,p,h,m=[];if(t.rtl=n.rtl_ui||t.editorManager.i18n.rtl,t.editorManager.i18n.setCode(n.language),n.aria_label=n.aria_label||M.getAttrib(r,"aria-label",t.getLang("aria.rich
_text_area")),t.fire("ScriptsLoaded"),n.theme&&("function"!=typeof n.theme?(n.theme=n.theme.replace(/-/,""),u=P.get(n.theme),t.theme=new u(t,P.urls[n.theme]),t.theme.init&&t.theme.init(t,P.urls[n.theme]||t.documentBaseUrl.replace(/\/$/,""),t.$)):t.theme=n.theme),I(n.plugins.replace(/\-/g,"").split(/[ ,]/),e),n.render_ui&&t.theme&&(t.orgDisplay=r.style.display,"function"!=typeof n.theme?(i=n.width||r.style.width||r.offsetWidth,o=n.height||r.style.height||r.offsetHeight,a=n.min_height||100,p=/^[0-9\.]+(|px)$/i,p.test(""+i)&&(i=Math.max(parseInt(i,10),100)),p.test(""+o)&&(o=Math.max(parseInt(o,10),a)),l=t.theme.renderUI({targetNode:r,width:i,height:o,deltaWidth:n.delta_width,deltaHeight:n.delta_height}),n.content_editable||(o=(l.iframeHeight||o)+("number"==typeof o?l.deltaHeight||0:""),o<a&&(o=a))):(l=n.theme(t,r),l.editorCo
ntainer.nodeType&&(l.editorContainer.id=l.editorContainer.id||t.id+"_parent"),l.iframeContainer.nodeType&&(l.iframeContainer.id=l.iframeContainer.id||t.id+"_iframecontainer"),o=l.iframeHeight||r.offsetHeight),t.editorContainer=l.editorContainer),n.content_css&&I(F(n.content_css),function(e){t.contentCSS.push(t.documentBaseURI.toAbsolute(e))}),n.content_style&&t.contentStyles.push(n.content_style),n.content_editable)return r=s=l=null,t.initContentBody();if(t.iframeHTML=n.doctype+"<html><head>",n.document_base_url!=t.documentBaseUrl&&(t.iframeHTML+='<base href="'+t.documentBaseURI.getURI()+'" />'),!w.caretAfter&&n.ie7_compat&&(t.iframeHTML+='<meta http-equiv="X-UA-Compatible" content="IE=7" />'),t.iframeHTML+='<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />',!/#$/.test(document.location.href))for(h=0
;h<t.contentCSS.length;h++){var g=t.contentCSS[h];t.iframeHTML+='<link type="text/css" rel="stylesheet" href="'+E._addCacheSuffix(g)+'" />',t.loadedCSS[g]=!0}d=n.body_id||"tinymce",d.indexOf("=")!=-1&&(d=t.getParam("body_id","","hash"),d=d[t.id]||d),f=n.body_class||"",f.indexOf("=")!=-1&&(f=t.getParam("body_class","","hash"),f=f[t.id]||""),n.content_security_policy&&(t.iframeHTML+='<meta http-equiv="Content-Security-Policy" content="'+n.content_security_policy+'" />'),t.iframeHTML+='</head><body id="'+d+'" class="mce-content-body '+f+'" data-id="'+t.id+'"><br></body></html>';var v='javascript:(function(){document.open();document.domain="'+document.domain+'";var ed = window.parent.tinymce.get("'+t.id+'");docum
ent.write(ed.iframeHTML);document.close();ed.initContentBody(true);})()';document.domain!=location.hostname&&w.ie&&w.ie<12&&(c=v);var y=M.create("iframe",{id:t.id+"_ifr",frameBorder:"0",allowTransparency:"true",title:t.editorManager.translate("Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help"),style:{width:"100%",height:o,display:"block"}});if(y.onload=function(){y.onload=null,t.fire("load")},M.setAttrib(y,"src",c||'javascript:""'),t.contentAreaContainer=l.iframeContainer,t.iframeElement=y,s=M.add(l.iframeContainer,y),q)try{t.getDoc()}catch(b){s.src=c=v}l.editorContainer&&(M.get(l.editorContainer).style.display=t.orgDisplay,t.hidden=M.isHidden(l.editorContainer)),t.getElement().style.display="none",M.setAttrib(t.id,"aria-hidden",!0),c||t.initContentBody(),r=s=l=null},initContentBody:function(t
){var n=this,r=n.settings,s=n.getElement(),p=n.getDoc(),h,m;r.inline||(n.getElement().style.visibility=n.orgVisibility),t||r.content_editable||(p.open(),p.write(n.iframeHTML),p.close()),r.content_editable&&(n.on("remove",function(){var e=this.getBody();M.removeClass(e,"mce-content-body"),M.removeClass(e,"mce-edit-focus"),M.setAttrib(e,"contentEditable",null)}),M.addClass(s,"mce-content-body"),n.contentDocument=p=r.content_document||document,n.contentWindow=r.content_window||window,n.bodyElement=s,r.content_document=r.content_window=null,r.root_name=s.nodeName.toLowerCase()),h=n.getBody(),h.disabled=!0,n.readonly=r.readonly,n.readonly||(n.inline&&"static"==M.getStyle(h,"position",!0)&&(h.style.position="relative"),h.contentEditable=n.getParam("content_editable_state",!0)),h.disabled=!1,n.editorUpload=new T(n),n.schema=new b(r),n.dom=new e(p,{keep_values:!0,url_converter:n
.convertURL,url_converter_scope:n,hex_colors:r.force_hex_style_colors,class_filter:r.class_filter,update_styles:!0,root_element:n.inline?n.getBody():null,collect:r.content_editable,schema:n.schema,onSetAttrib:function(e){n.fire("SetAttrib",e)}}),n.parser=new C(r,n.schema),n.parser.addAttributeFilter("src,href,style,tabindex",function(e,t){for(var r=e.length,i,o=n.dom,a,s;r--;)if(i=e[r],a=i.attr(t),s="data-mce-"+t,!i.attributes.map[s]){if(0===a.indexOf("data:")||0===a.indexOf("blob:"))continue;"style"===t?(a=o.serializeStyle(o.parseStyle(a),i.name),a.length||(a=null),i.attr(s,a),i.attr(t,a)):"tabindex"===t?(i.attr(s,a),i.attr(t,null)):i.attr(s,n.convertURL(a,t,i.name))}}),n.parser.addNodeFilter("script",function(e){for(var t=e.length,n,r;t--;)n=e[t],
-r=n.attr("type")||"no/type",0!==r.indexOf("mce-")&&n.attr("type","mce-"+r)}),n.parser.addNodeFilter("#cdata",function(e){for(var t=e.length,n;t--;)n=e[t],n.type=8,n.name="#comment",n.value="[CDATA["+n.value+"]]"}),n.parser.addNodeFilter("p,h1,h2,h3,h4,h5,h6,div",function(e){for(var t=e.length,r,i=n.schema.getNonEmptyElements();t--;)r=e[t],r.isEmpty(i)&&0===r.getAll("br").length&&(r.append(new o("br",1)).shortEnded=!0)}),n.serializer=new a(r,n),n.selection=new l(n.dom,n.getWin(),n.serializer,n),n.formatter=new u(n),n.undoManager=new c(n),n.forceBlocks=new f(n),n.enterKey=new d(n),n._nodeChangeDispatcher=new i(n),n._selectionOverrides=new R(n),n.fire("PreInit"),r.browser_spellcheck||r.gecko_spellcheck||(p.body.spellcheck=!1,M.setAttrib(h,"spellcheck","false")),n.quirks=new x(n),n.fire("PostRender"),r.dir
ectionality&&(h.dir=r.directionality),r.nowrap&&(h.style.whiteSpace="nowrap"),r.protect&&n.on("BeforeSetContent",function(e){I(r.protect,function(t){e.content=e.content.replace(t,function(e){return"<!--mce:protected "+escape(e)+"-->"})})}),n.on("SetContent",function(){n.addVisual(n.getBody())}),r.padd_empty_editor&&n.on("PostProcess",function(e){e.content=e.content.replace(/^(<p[^>]*>( | |\s|\u00a0|<br \/>|)<\/p>[\r\n]*|<br \/>[\r\n]*)$/,"")}),n.load({initial:!0,format:"html"}),n.startContent=n.getContent({format:"raw"}),n.initialized=!0,n.bindPendingEventDelegates(),n.fire("init"),n.focus(!0),n.nodeChanged({initial:!0}),n.execCallback("init_instance_callback",n),n.on("compositionstart compositionend",function(e){n.composing="compositionstart"===e.type}),n.contentStyles.len
gth>0&&(m="",I(n.contentStyles,function(e){m+=e+"\r\n"}),n.dom.addStyle(m)),I(n.contentCSS,function(e){n.loadedCSS[e]||(n.dom.loadCSS(e),n.loadedCSS[e]=!0)}),r.auto_focus&&N.setEditorTimeout(n,function(){var e;e=r.auto_focus===!0?n:n.editorManager.get(r.auto_focus),e.destroyed||e.focus()},100),s=p=h=null},focus:function(e){function t(e){return n.dom.getParent(e,function(e){return"true"===n.dom.getContentEditable(e)})}var n=this,r=n.selection,i=n.settings.content_editable,o,a,s=n.getDoc(),l=n.getBody(),u;if(!e){if(o=r.getRng(),o.item&&(a=o.item(0)),n.quirks.refreshContentEditable(),u=t(r.getNode()),n.$.contains(l,u))return u.focus(),r.normalize(),void n.editorManager.setActive(n);if(i||(w.opera||n.getBody().focus(),n.getWin().focus()),$||i){if(l.setActive)try{l.setActive()}catch(c){l.focus()}else l.focus();i&&r.normalize()}a&&a.ownerDocument==s&&(o=s.body.createControlRange(),o.addElement(a),o.select())}
n.editorManager.setActive(n)},execCallback:function(e){var t=this,n=t.settings[e],r;if(n)return t.callbackLookup&&(r=t.callbackLookup[e])&&(n=r.func,r=r.scope),"string"==typeof n&&(r=n.replace(/\.\w+$/,""),r=r?W(r):0,n=W(n),t.callbackLookup=t.callbackLookup||{},t.callbackLookup[e]={func:n,scope:r}),n.apply(r||t,Array.prototype.slice.call(arguments,1))},translate:function(e){var t=this.settings.language||"en",n=this.editorManager.i18n;return e?(e=n.data[t+"."+e]||e.replace(/\{\#([^\}]+)\}/g,function(e,r){return n.data[t+"."+r]||"{#"+r+"}"}),this.editorManager.translate(e)):""},getLang:function(e,n){return this.editorManager.i18n.data[(this.settings.language||"en")+"."+e]||(n!==t?n:"{#"+e+"}")},getParam:function(e,t,n){var r=e in this.settings?this.settings[e]:t,i;return"hash"===n?(i={},"string"==typeof r?I(r.indexOf("
=")>0?r.split(/[;,](?![^=;,]*(?:[;,]|$))/):r.split(","),function(e){e=e.split("="),e.length>1?i[U(e[0])]=U(e[1]):i[U(e[0])]=U(e)}):i=r,i):r},nodeChanged:function(e){this._nodeChangeDispatcher.nodeChanged(e)},addButton:function(e,t){var n=this;t.cmd&&(t.onclick=function(){n.execCommand(t.cmd)}),t.text||t.icon||(t.icon=e),n.buttons=n.buttons||{},t.tooltip=t.tooltip||t.title,n.buttons[e]=t},addSidebar:function(e,t){return B.add(this,e,t)},addMenuItem:function(e,t){var n=this;t.cmd&&(t.onclick=function(){n.execCommand(t.cmd)}),n.menuItems=n.menuItems||{},n.menuItems[e]=t},addContextToolbar:function(e,t){var n=this,r;n.contextToolbars=n.contextToolbars||[],"string"==typeof e&&(r=e,e=function(e){return n.dom.is(e,r)}),n.contextToolbars.push({id:A.uuid("mcet"),predicate:e,items:t})},addCommand:function(e,t,n){this.editorCommands.addCommand(e,t,n)},addQueryStateHandler:function(e,t,n){this.editorCommands.addQueryStat
eHandler(e,t,n)},addQueryValueHandler:function(e,t,n){this.editorCommands.addQueryValueHandler(e,t,n)},addShortcut:function(e,t,n,r){this.shortcuts.add(e,t,n,r)},execCommand:function(e,t,n,r){return this.editorCommands.execCommand(e,t,n,r)},queryCommandState:function(e){return this.editorCommands.queryCommandState(e)},queryCommandValue:function(e){return this.editorCommands.queryCommandValue(e)},queryCommandSupported:function(e){return this.editorCommands.queryCommandSupported(e)},show:function(){var e=this;e.hidden&&(e.hidden=!1,e.inline?e.getBody().contentEditable=!0:(M.show(e.getContainer()),M.hide(e.id)),e.load(),e.fire("show"))},hide:function(){var e=this,t=e.getDoc();e.hidden||(q&&t&&!e.inline&&t.execCommand("SelectAll"),e.save(),e.inline?(e.getBody().contentEditable=!1,e==e.editorManager.focusedEditor&&(e.editorManager.focusedEditor=null)):(M.hide(e.getContainer()),M.setStyle(e.id,"display",e.orgDisplay)),e
.hidden=!0,e.fire("hide"))},isHidden:function(){return!!this.hidden},setProgressState:function(e,t){this.fire("ProgressState",{state:e,time:t})},load:function(e){var n=this,r=n.getElement(),i;if(r)return e=e||{},e.load=!0,i=n.setContent(r.value!==t?r.value:r.innerHTML,e),e.element=r,e.no_events||n.fire("LoadContent",e),e.element=r=null,i},save:function(e){var t=this,n=t.getElement(),r,i;if(n&&t.initialized)return e=e||{},e.save=!0,e.element=n,r=e.content=t.getContent(e),e.no_events||t.fire("SaveContent",e),"raw"==e.format&&t.fire("RawSaveContent",e),r=e.content,/TEXTAREA|INPUT/i.test(n.nodeName)?n.value=r:(t.inline||(n.innerHTML=r),(i=M.getParent(t.id,"form"))&&I(i.elements,function(e){if(e.name==t.id)return e.value=r,!1})),e.element=n=null,e.set_dirty!==!1&&t.setDirty(!1),r},setContent:function(e,t){var n=this,r=n.getBody(),i,o;return t=t||{},t.format=t.format||"html",t.s
et=!0,t.content=e,t.no_events||n.fire("BeforeSetContent",t),e=t.content,0===e.length||/^\s+$/.test(e)?(o=q&&q<11?"":'<br data-mce-bogus="1">',"TABLE"==r.nodeName?e="<tr><td>"+o+"</td></tr>":/^(UL|OL)$/.test(r.nodeName)&&(e="<li>"+o+"</li>"),i=n.settings.forced_root_block,i&&n.schema.isValidChild(r.nodeName.toLowerCase(),i.toLowerCase())?(e=o,e=n.dom.createHTML(i,n.settings.forced_root_block_attrs,e)):q||e||(e='<br data-mce-bogus="1">'),n.dom.setHTML(r,e),n.fire("SetContent",t)):("raw"!==t.format&&(e=new s({validate:n.validate},n.schema).serialize(n.parser.parse(e,{isRootContent:!0}))),t.content=U(e),n.dom.setHTML(r,t.content),t.no_events||n.fire("SetContent",t)),t.content},getContent:function(e){var t=this,n,r=t.getBody();return e=e||{},e.format=e.format||"html",e.get=!0,e.
getInner=!0,e.no_events||t.fire("BeforeGetContent",e),n="raw"==e.format?E.trim(t.serializer.getTrimmedContent()):"text"==e.format?r.innerText||r.textContent:t.serializer.serialize(r,e),"text"!=e.format?e.content=U(n):e.content=n,e.no_events||t.fire("GetContent",e),e.content},insertContent:function(e,t){t&&(e=H({content:e},t)),this.execCommand("mceInsertContent",!1,e)},isDirty:function(){return!this.isNotDirty},setDirty:function(e){var t=!this.isNotDirty;this.isNotDirty=!e,e&&e!=t&&this.fire("dirty")},setMode:function(e){S.setMode(this,e)},getContainer:function(){var e=this;return e.container||(e.container=M.get(e.editorContainer||e.id+"_parent")),e.container},getContentAreaContainer:function(){return this.contentAreaContainer},getElement:function(){return this.targetElm||(this.targetElm=M.get(this.id)),this.targetElm},getWin:function(){var e=this,t;return e.contentWindow||(t=e.ifr
ameElement,t&&(e.contentWindow=t.contentWindow)),e.contentWindow},getDoc:function(){var e=this,t;return e.contentDocument||(t=e.getWin(),t&&(e.contentDocument=t.document)),e.contentDocument},getBody:function(){var e=this.getDoc();return this.bodyElement||(e?e.body:null)},convertURL:function(e,t,n){var r=this,i=r.settings;return i.urlconverter_callback?r.execCallback("urlconverter_callback",e,n,!0,t):!i.convert_urls||n&&"LINK"==n.nodeName||0===e.indexOf("file:")||0===e.length?e:i.relative_urls?r.documentBaseURI.toRelative(e):e=r.documentBaseURI.toAbsolute(e,i.remove_script_host)},addVisual:function(e){var n=this,r=n.settings,i=n.dom,o;e=e||n.getBody(),n.hasVisual===t&&(n.hasVisual=r.visual),I(i.select("table,a",e),function(e){var t;switch(e.nodeName){case"TABLE":return o=r.visual_table_class||"mce-item-table",t=i.getAttrib(e,"border"),void(t&&"0"!=t||!n.hasVisual?i.
removeClass(e,o):i.addClass(e,o));case"A":return void(i.getAttrib(e,"href",!1)||(t=i.getAttrib(e,"name")||e.id,o=r.visual_anchor_class||"mce-item-anchor",t&&n.hasVisual?i.addClass(e,o):i.removeClass(e,o)))}}),n.fire("VisualAid",{element:e,hasVisual:n.hasVisual})},remove:function(){var e=this;e.removed||(e.save(),e.removed=1,e.unbindAllNativeEvents(),e.hasHiddenInput&&M.remove(e.getElement().nextSibling),e.inline||(q&&q<10&&e.getDoc().execCommand("SelectAll",!1,null),M.setStyle(e.id,"display",e.orgDisplay),e.getBody().onload=null),e.fire("remove"),e.editorManager.remove(e),M.remove(e.getContainer()),e._selectionOverrides.destroy(),e.editorUpload.destroy(),e.destroy())},destroy:function(e){var t=this,n;if(!t.destroyed){if(!e&&!t.removed)return void t.remove();e||(t.editorManager.off("beforeunload",t._beforeUnload),t.theme&&t.theme.destroy&&am
p;t.theme.destroy(),t.selection.destroy(),t.dom.destroy()),n=t.formElement,n&&(n._mceOldSubmit&&(n.submit=n._mceOldSubmit,n._mceOldSubmit=null),M.unbind(n,"submit reset",t.formEventDelegate)),t.contentAreaContainer=t.formElement=t.container=t.editorContainer=null,t.bodyElement=t.contentDocument=t.contentWindow=null,t.iframeElement=t.targetElm=null,t.selection&&(t.selection=t.selection.win=t.selection.dom=t.selection.dom.doc=null),t.destroyed=1}},uploadImages:function(e){return this.editorUpload.uploadImages(e)},_scanForImages:function(){return this.editorUpload.scanForImages()}},H(L.prototype,_),L}),r(st,[m],function(e){var t={},n="en";return{setCode:function(e){e&&(n=e,this.rtl=!!this.data[e]&&"rtl"===this.data[e]._dir)},getCode:function(){return n},rtl:!1,add:function(e,n){var r=t[e];r||(t[e]=r={});for(var i in n)r[i]=n[i];this.setCode(e)},translate:function(r){function i(t){return e.is(t,"function")?O
bject.prototype.toString.call(t):o(t)?"":""+t}function o(t){return""===t||null===t||e.is(t,"undefined")}function a(t){return t=i(t),e.hasOwn(s,t)?i(s[t]):t}var s=t[n]||{};if(o(r))return"";if(e.is(r,"object")&&e.hasOwn(r,"raw"))return i(r.raw);if(e.is(r,"array")){var l=r.slice(1);r=a(r[0]).replace(/\{([0-9]+)\}/g,function(t,n){return e.hasOwn(l,n)?i(l[n]):t})}return a(r).replace(/{context:\w+}$/,"")},data:t}}),r(lt,[w,c,d],function(e,t,n){function r(e){function r(){try{return document.activeElement}catch(e){return document.body}}function u(e,t){if(t&&t.startContainer){if(!e.isChildOf(t.startContainer,e.getRoot())||!e.isChildOf(t.endContainer,e.getRoot()))return;return{startContainer:t.startContainer,startOffset:t.startOffset,endContainer:t.endContainer,endOffset:t.endOffset}}return t}function c(e,t){var n;return t.startContainer?(n=e.getDoc().createRange(),n.setStart(t.startConta
iner,t.startOffset),n.setEnd(t.endContainer,t.endOffset)):n=t,n}function d(d){var f=d.editor;f.on("init",function(){(f.inline||n.ie)&&("onbeforedeactivate"in document&&n.ie<9?f.dom.bind(f.getBody(),"beforedeactivate",function(e){if(e.target==f.getBody())try{f.lastRng=f.selection.getRng()}catch(t){}}):f.on("nodechange mouseup keyup",function(e){var t=r();"nodechange"==e.type&&e.selectionChange||(t&&t.id==f.id+"_ifr"&&(t=f.getBody()),f.dom.isChildOf(t,f.getBody())&&(f.lastRng=f.selection.getRng()))}),n.webkit&&!i&&(i=function(){var t=e.activeEditor;if(t&&t.selection){var n=t.selection.getRng();n&&!n.collapsed&&(f.lastRng=n)}},s.bind(document,"selectionchange",i)))}),f.on("setcontent",function(){f.lastRng=null}),f.on("mousedown",function(){f.selection.lastFocusBookmark=null}),f.on("focusin",functio
n(){var t=e.focusedEditor,n;f.selection.lastFocusBookmark&&(n=c(f,f.selection.lastFocusBookmark),f.selection.lastFocusBookmark=null,f.selection.setRng(n)),t!=f&&(t&&t.fire("blur",{focusedEditor:f}),e.setActive(f),e.focusedEditor=f,f.fire("focus",{blurredEditor:t}),f.focus(!0)),f.lastRng=null}),f.on("focusout",function(){t.setEditorTimeout(f,function(){var t=e.focusedEditor;l(f,r())||t!=f||(f.fire("blur",{focusedEditor:null}),e.focusedEditor=null,f.selection&&(f.selection.lastFocusBookmark=null))})}),o||(o=function(t){var n=e.activeEditor,r;r=t.target,n&&r.ownerDocument==document&&(n.selection&&r!=n.getBody()&&(n.selection.lastFocusBookmark=u(n.dom,n.lastRng)),r==document.body||l(n,r)||e.focusedEditor!=n||(n.fire("blur",{focusedEditor:null}),e.focusedEditor=null))},s.bind(document,"focusin",o)),f.inline&&!a&&(a=function(t){var n=e.activeEditor,r=
n.dom;if(n.inline&&r&&!r.isChildOf(t.target,n.getBody())){var i=n.selection.getRng();i.collapsed||(n.lastRng=i)}},s.bind(document,"mouseup",a))}function f(t){e.focusedEditor==t.editor&&(e.focusedEditor=null),e.activeEditor||(s.unbind(document,"selectionchange",i),s.unbind(document,"focusin",o),s.unbind(document,"mouseup",a),i=o=a=null)}e.on("AddEditor",d),e.on("RemoveEditor",f)}var i,o,a,s=e.DOM,l=function(e,t){var n=e?e.settings.custom_ui_selector:"",i=s.getParent(t,function(t){return r.isEditorUIElement(t)||!!n&&e.dom.is(t,n)});return null!==i};return r.isEditorUIElement=function(e){return e.className.toString().indexOf("mce-")!==-1},r._isUIElement=l,r}),r(ut,[at,g,w,ue,d,m,u,pe,st,lt,N],function(e,t,n,r,i,o,a,s,l,u,c){function d(e){v(x.editors,function(t){"scroll"===e.type?t.fire("ScrollWindow",e):t.fire("ResizeWindow",e)})}function f(e,n){
n!==w&&(n?t(window).on("resize scroll",d):t(window).off("resize scroll",d),w=n)}function p(e){var t=x.editors,n;delete t[e.id];for(var r=0;r<t.length;r++)if(t[r]==e){t.splice(r,1),n=!0;break}return x.activeEditor==e&&(x.activeEditor=t[0]),x.focusedEditor==e&&(x.focusedEditor=null),n}function h(e){return e&&e.initialized&&!(e.getContainer()||e.getBody()).parentNode&&(p(e),e.unbindAllNativeEvents(),e.destroy(!0),e.removed=!0,e=null),e}var m=n.DOM,g=o.explode,v=o.each,y=o.extend,b=0,C,x,w=!1;return x={$:t,majorVersion:"4",minorVersion:"5.6",releaseDate:"2017-03-30",editors:[],i18n:l,activeEditor:null,setup:function(){var e=this,t,n,i="",o,a;if(n=r.getDocumentBaseUrl(document.location),/^[^:]+:\/\/\/?[^\/]+\//.test(n)&&(n=n.replace(/[\?#].*$/,"").replace(/[\/\\][^\/]+$/,""),/[\/\\]$/.test(n)||(n+="/")),o=window.tinymce||window.tinyMCEPreIni
t)t=o.base||o.baseURL,i=o.suffix;else{for(var s=document.getElementsByTagName("script"),l=0;l<s.length;l++){a=s[l].src;var c=a.substring(a.lastIndexOf("/"));if(/tinymce(\.full|\.jquery|)(\.min|\.dev|)\.js/.test(a)){c.indexOf(".min")!=-1&&(i=".min"),t=a.substring(0,a.lastIndexOf("/"));break}}!t&&document.currentScript&&(a=document.currentScript.src,a.indexOf(".min")!=-1&&(i=".min"),t=a.substring(0,a.lastIndexOf("/")))}e.baseURL=new r(n).toAbsolute(t),e.documentBaseURL=n,e.baseURI=new r(e.baseURL),e.suffix=i,e.focusManager=new u(e)},overrideDefaults:function(e){var t,n;t=e.base_url,t&&(this.baseURL=new r(this.documentBaseURL).toAbsolute(t.replace(/\/+$/,"")),this.baseURI=new r(this.baseURL)),n=e.suffix,e.suffix&&(this.suffix=n),this.defaultSettings=e;var i=e.plugin_base_urls;for(var o in i)c.PluginManager.urls[o]=i[o]},init:function(n){function r
(e,t){return e.inline&&t.tagName.toLowerCase()in C}function i(e,t){window.console&&!window.test&&window.console.log(e,t)}function s(e){var t=e.id;return t||(t=e.name,t=t&&!m.get(t)?e.name:m.uniqueId(),e.setAttribute("id",t)),t}function l(e){var t=n[e];if(t)return t.apply(f,Array.prototype.slice.call(arguments,2))}function u(e,t){return t.constructor===RegExp?t.test(e.className):m.hasClass(e,t)}function c(e){var t,n=[];if(e.types)return v(e.types,function(e){n=n.concat(m.select(e.selector))}),n;if(e.selector)return m.select(e.selector);if(e.target)return[e.target];switch(e.mode){case"exact":t=e.elements||"",t.length>0&&v(g(t),function(e){var t;(t=m.get(e))?n.push(t):v(document.forms,function(t){v(t.elements,function(t){t.name===e&&(e="mce_editor_"+b++,m.setAttrib(t,"id",e),n.push(t))})})});break;case"textareas":case"specific_textareas":v(m.select("textarea&quo
t;),function(t){e.editor_deselector&&u(t,e.editor_deselector)||e.editor_selector&&!u(t,e.editor_selector)||n.push(t)})}return n}function d(){function a(t,n,r){var i=new e(t,n,f);p.push(i),i.on("init",function(){++u===g.length&&x(p)}),i.targetElm=i.targetElm||r,i.render()}var u=0,p=[],g;return m.unbind(window,"ready",d),l("onpageload"),g=t.unique(c(n)),n.types?void v(n.types,function(e){o.each(g,function(t){return!m.is(t,e.selector)||(a(s(t),y({},n,e),t),!1)})}):(o.each(g,function(e){h(f.get(e.id))}),g=o.grep(g,function(e){return!f.get(e.id)}),void v(g,function(e){r(n,e)?i("Could not initialize inline editor on invalid inline target element",e):a(s(e),n,e)}))}var f=this,p,C;C=o.makeMap("area base basefont br col frame hr img input isindex link meta param embed source wbr track colgroup option tbody tfoot thead tr script noscript style textarea video audio iframe object menu"," ");var x=function(e){p=e
};return f.settings=n,m.bind(window,"ready",d),new a(function(e){p?e(p):x=function(t){e(t)}})},get:function(e){return arguments.length?e in this.editors?this.editors[e]:null:this.editors},add:function(e){var t=this,n=t.editors;return n[e.id]=e,n.push(e),f(n,!0),t.activeEditor=e,t.fire("AddEditor",{editor:e}),C||(C=function(){t.fire("BeforeUnload")},m.bind(window,"beforeunload",C)),e},createEditor:function(t,n){return this.add(new e(t,n,this))},remove:function(e){var t=this,n,r=t.editors,i;{if(e)return"string"==typeof e?(e=e.selector||e,void v(m.select(e),function(e){i=r[e.id],i&&t.remove(i)})):(i=e,r[i.id]?(p(i)&&t.fire("RemoveEditor",{editor:i}),r.length||m.unbind(window,"beforeunload",C),i.remove(),f(r,r.length>0),i):null);for(n=r.length-1;n>=0;n--)t.remove(r[n])}},execCommand:function(t,n,r){var i=this,o=i.get(r);switch(t){case"mceAddEditor":return i.get(r)||new e(r,i.settings,i)
.render(),!0;case"mceRemoveEditor":return o&&o.remove(),!0;case"mceToggleEditor":return o?(o.isHidden()?o.show():o.hide(),!0):(i.execCommand("mceAddEditor",0,r),!0)}return!!i.activeEditor&&i.activeEditor.execCommand(t,n,r)},triggerSave:function(){v(this.editors,function(e){e.save()})},addI18n:function(e,t){l.add(e,t)},translate:function(e){return l.translate(e)},setActive:function(e){var t=this.activeEditor;this.activeEditor!=e&&(t&&t.fire("deactivate",{relatedTarget:e}),e.fire("activate",{relatedTarget:t})),this.activeEditor=e}},y(x,s),x.setup(),window.tinymce=window.tinyMCE=x,x}),r(ct,[ut,m],function(e,t){var n=t.each,r=t.explode;e.on("AddEditor",function(e){var t=e.editor;t.on("preInit",function(){function e(e,t){n(t,function(t,n){t&&s.setStyle(e,n,t)}),s.rename(e,"span")}function i(e){s=t.dom,l.convert_fonts_to_spans&&n(s.select("font,u,strike"
;,e.node),function(e){o[e.nodeName.toLowerCase()](s,e)})}var o,a,s,l=t.settings;l.inline_styles&&(a=r(l.font_size_legacy_values),o={font:function(t,n){e(n,{backgroundColor:n.style.backgroundColor,color:n.color,fontFamily:n.face,fontSize:a[parseInt(n.size,10)-1]})},u:function(n,r){"html4"===t.settings.schema&&e(r,{textDecoration:"underline"})},strike:function(t,n){e(n,{textDecoration:"line-through"})}},t.on("PreProcess SetContent",i))})})}),r(dt,[pe,m],function(e,t){var n={send:function(e){function r(){!e.async||4==i.readyState||o++>1e4?(e.success&&o<1e4&&200==i.status?e.success.call(e.success_scope,""+i.responseText,i,e):e.error&&e.error.call(e.error_scope,o>1e4?"TIMED_OUT":"GENERAL",i,e),i=null):setTimeout(r,10)}var i,o=0;if(e.scope=e.scope||this,e.success_scope=e.success_scope||e.scope,e.error_scope=e.error_scope||e.scope,e.async=e.async!==!1,e.data=e.data||"
",n.fire("beforeInitialize",{settings:e}),i=new XMLHttpRequest){if(i.overrideMimeType&&i.overrideMimeType(e.content_type),i.open(e.type||(e.data?"POST":"GET"),e.url,e.async),e.crossDomain&&(i.withCredentials=!0),e.content_type&&i.setRequestHeader("Content-Type",e.content_type),e.requestheaders&&t.each(e.requestheaders,function(e){i.setRequestHeader(e.key,e.value)}),i.setRequestHeader("X-Requested-With","XMLHttpRequest"),i=n.fire("beforeSend",{xhr:i,settings:e}).xhr,i.send(e.data),!e.async)return r();setTimeout(r,10)}}};return t.extend(n,e),n}),r(ft,[],function(){function e(t,n){var r,i,o,a;if(n=n||'"',null===t)return"null";if(o=typeof t,"string"==o)return i="\bb\tt\nn\ff\rr\"\"''\\\\",n+t.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g,function(e,t){return'"'===n&&"'"===e?e:(r=i.indexOf(t),r+1?"\\"+i
.charAt(r+1):(e=t.charCodeAt().toString(16),"\\u"+"0000".substring(e.length)+e))})+n;if("object"==o){if(t.hasOwnProperty&&"[object Array]"===Object.prototype.toString.call(t)){for(r=0,i="[";r<t.length;r++)i+=(r>0?",":"")+e(t[r],n);return i+"]"}i="{";for(a in t)t.hasOwnProperty(a)&&(i+="function"!=typeof t[a]?(i.length>1?","+n:n)+a+n+":"+e(t[a],n):"");return i+"}"}return""+t}return{serialize:e,parse:function(e){try{return window[String.fromCharCode(101)+"val"]("("+e+")")}catch(t){}}}}),r(pt,[ft,dt,m],function(e,t,n){function r(e){this.settings=i({},e),this.count=0}var i=n.extend;return r.sendRPC=function(e){return(new r).send(e)},r.prototype={send:function(n){var r=n.error,o=n.success;n=i(this.settings,n),n.success=function(t,i){t=e.parse(t),"undefined"==typeof t&&
(t={error:"JSON Parse error."}),t.error?r.call(n.error_scope||n.scope,t.error,i):o.call(n.success_scope||n.scope,t.result)},n.error=function(e,t){r&&r.call(n.error_scope||n.scope,e,t)},n.data=e.serialize({id:n.id||"c"+this.count++,method:n.method,params:n.params}),n.content_type="application/json",t.send(n)}},r}),r(ht,[w],function(e){return{callbacks:{},count:0,send:function(n){var r=this,i=e.DOM,o=n.count!==t?n.count:r.count,a="tinymce_jsonp_"+o;r.callbacks[o]=function(e){i.remove(a),delete r.callbacks[o],n.callback(e)},i.add(i.doc.body,"script",{id:a,src:n.url,type:"text/javascript"}),r.count++}}}),r(mt,[],function(){function e(){s=[];for(var e in a)s.push(e);i.length=s.length}function n(){function n(e){var n,r;return r=e!==t?c+e:i.indexOf(",",c),r===-1||r>i.length?null:(n=i.substring(c,r),c=r+1,n)}var r,i,s,c=0;if(a={},u){o.load(l),i=o.getAttribute(l)||"";do{var d=n();if(null===d)break;if(r
=n(parseInt(d,32)||0),null!==r){if(d=n(),null===d)break;s=n(parseInt(d,32)||0),r&&(a[r]=s)}}while(null!==r);e()}}function r(){var t,n="";if(u){for(var r in a)t=a[r],n+=(n?",":"")+r.length.toString(32)+","+r+","+t.length.toString(32)+","+t;o.setAttribute(l,n);try{o.save(l)}catch(i){}e()}}var i,o,a,s,l,u;try{if(window.localStorage)return localStorage}catch(c){}return l="tinymce",o=document.documentElement,u=!!o.addBehavior,u&&o.addBehavior("#default#userData"),i={key:function(e){return s[e]},getItem:function(e){return e in a?a[e]:null},setItem:function(e,t){a[e]=""+t,r()},removeItem:function(e){delete a[e],r()},clear:function(){a={},r()}},n(),i}),r(gt,[w,f,E,N,m,d],function(e,t,n,r,i,o){var a=window.tinymce;return a.DOM=e.DOM,a.ScriptLoader=n.ScriptLoader,a.PluginManager=r.PluginManager,a.ThemeManager=r.ThemeManager,a.dom=a.dom||{},a.dom.Event=t.Event,i.each("trim isArray is
toArray makeMap each map grep inArray extend create walk createNS resolve explode _addCacheSuffix".split(" "),function(e){a[e]=i[e]}),i.each("isOpera isWebKit isIE isGecko isMac".split(" "),function(e){a[e]=o[e.substr(2).toLowerCase()]}),{}}),r(vt,[ce,m],function(e,t){return e.extend({Defaults:{firstControlClass:"first",lastControlClass:"last"},init:function(e){this.settings=t.extend({},this.Defaults,e)},preRender:function(e){e.bodyClasses.add(this.settings.containerClass)},applyClasses:function(e){var t=this,n=t.settings,r,i,o,a;r=n.firstControlClass,i=n.lastControlClass,e.each(function(e){e.classes.remove(r).remove(i).add(n.controlClass),e.visible()&&(o||(o=e),a=e)}),o&&o.classes.add(r),a&&a.classes.add(i)},renderHtml:function(e){var t=this,n="";return t.applyClasses(e.items()),e.items().each(function(e){n+=e.renderHtml()}),n},recalc:function(){},postRender:function(){},isNative:function(){ret
urn!1}})}),r(yt,[vt],function(e){return e.extend({Defaults:{containerClass:"abs-layout",controlClass:"abs-layout-item"},recalc:function(e){e.items().filter(":visible").each(function(e){var t=e.settings;e.layoutRect({x:t.x,y:t.y,w:t.w,h:t.h}),e.recalc&&e.recalc()})},renderHtml:function(e){return'<div id="'+e._id+'-absend" class="'+e.classPrefix+'abs-end"></div>'+this._super(e)}})}),r(bt,[Pe],function(e){return e.extend({Defaults:{classes:"widget btn",role:"button"},init:function(e){var t=this,n;t._super(e),e=t.settings,n=t.settings.size,t.on("click mousedown",function(e){e.preventDefault()}),t.on("touchstart",function(e){t.fire("click",e),e.preventDefault()}),e.subtype&&t.classes.add(e.subtype),n&&t.classes.add("btn-"+n),e.icon&&t.icon(e.icon)},icon:function(e){return arguments.length?(this.state.set("icon",e),this):this.s
tate.get("icon")},repaint:function(){var e=this.getEl().firstChild,t;e&&(t=e.style,t.width=t.height="100%"),this._super()},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix,r=e.state.get("icon"),i,o=e.state.get("text"),a="";return i=e.settings.image,i?(r="none","string"!=typeof i&&(i=window.getSelection?i[0]:i[1]),i=" style=\"background-image: url('"+i+"')\""):i="",o&&(e.classes.add("btn-has-text"),a='<span class="'+n+'txt">'+e.encode(o)+"</span>"),r=r?n+"ico "+n+"i-"+r:"",'<div id="'+t+'" class="'+e.classes+'" tabindex="-1" aria-labelledby="'+t+'"><button role="presentation" type="button" tabindex="-1">'+(r?'<i class="'+r+'"'+i+"></i>":"")+a+"<
;/button></div>"},bindStates:function(){function e(e){var i=n("span."+r,t.getEl());e?(i[0]||(n("button:first",t.getEl()).append('<span class="'+r+'"></span>'),i=n("span."+r,t.getEl())),i.html(t.encode(e))):i.remove(),t.classes.toggle("btn-has-text",!!e)}var t=this,n=t.$,r=t.classPrefix+"txt";return t.state.on("change:text",function(t){e(t.value)}),t.state.on("change:icon",function(n){var r=n.value,i=t.classPrefix;t.settings.icon=r,r=r?i+"ico "+i+"i-"+t.settings.icon:"";var o=t.getEl().firstChild,a=o.getElementsByTagName("i")[0];r?(a&&a==o.firstChild||(a=document.createElement("i"),o.insertBefore(a,o.firstChild)),a.className=r):a&&o.removeChild(a),e(t.state.get("text"))}),t._super()}})}),r(Ct,[Ne],function(e){return e.extend({Defaults:{defaultType:"button",role:"group"},renderHtml:func
tion(){var e=this,t=e._layout;return e.classes.add("btn-group"),e.preRender(),t.preRender(e),'<div id="'+e._id+'" class="'+e.classes+'"><div id="'+e._id+'-body">'+(e.settings.html||"")+t.renderHtml(e)+"</div></div>"}})}),r(xt,[Pe],function(e){return e.extend({Defaults:{classes:"checkbox",role:"checkbox",checked:!1},init:function(e){var t=this;t._super(e),t.on("click mousedown",function(e){e.preventDefault()}),t.on("click",function(e){e.preventDefault(),t.disabled()||t.checked(!t.checked())}),t.checked(t.settings.checked)},checked:function(e){return arguments.length?(this.state.set("checked",e),this):this.state.get("checked")},value:function(e){return arguments.length?this.checked(e):this.checked()},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix;return'<div id="'+t+'" class="'+e.classes+'" unselectable="o
n" aria-labelledby="'+t+'-al" tabindex="-1"><i class="'+n+"ico "+n+'i-checkbox"></i><span id="'+t+'-al" class="'+n+'label">'+e.encode(e.state.get("text"))+"</span></div>"},bindStates:function(){function e(e){t.classes.toggle("checked",e),t.aria("checked",e)}var t=this;return t.state.on("change:text",function(e){t.getEl("al").firstChild.data=t.translate(e.value)}),t.state.on("change:checked change:value",function(n){t.fire("change"),e(n.value)}),t.state.on("change:icon",function(e){var n=e.value,r=t.classPrefix;if("undefined"==typeof n)return t.settings.icon;t.settings.icon=n,n=n?r+"ico "+r+"i-"+t.settings.icon:"";var i=t.getEl().firstChild,o=i.getElementsByTagName("i")[0];n?(o&&o==i.firstChild||(o=document.createElement("i"),i.inse
rtBefore(o,i.firstChild)),o.className=n):o&&i.removeChild(o)}),t.state.get("checked")&&e(!0),t._super()}})}),r(wt,[Pe,we,ve,g,I,m],function(e,t,n,r,i,o){return e.extend({init:function(e){var t=this;t._super(e),e=t.settings,t.classes.add("combobox"),t.subinput=!0,t.ariaTarget="inp",e.menu=e.menu||e.values,e.menu&&(e.icon="caret"),t.on("click",function(n){var i=n.target,o=t.getEl();if(r.contains(o,i)||i==o)for(;i&&i!=o;)i.id&&i.id.indexOf("-open")!=-1&&(t.fire("action"),e.menu&&(t.showMenu(),n.aria&&t.menu.items()[0].focus())),i=i.parentNode}),t.on("keydown",function(e){var n;13==e.keyCode&&"INPUT"===e.target.nodeName&&(e.preventDefault(),t.parents().reverse().each(function(e){if(e.toJSON)return n=e,!1}),t.fire("submit",{data:n.toJSON()}))}),t.on("keyup",function(e){if("INPUT"==e.target.n
odeName){var n=t.state.get("value"),r=e.target.value;r!==n&&(t.state.set("value",r),t.fire("autocomplete",e))}}),t.on("mouseover",function(e){var n=t.tooltip().moveTo(-65535);if(t.statusLevel()&&e.target.className.indexOf(t.classPrefix+"status")!==-1){var r=t.statusMessage()||"Ok",i=n.text(r).show().testMoveRel(e.target,["bc-tc","bc-tl","bc-tr"]);n.classes.toggle("tooltip-n","bc-tc"==i),n.classes.toggle("tooltip-nw","bc-tl"==i),n.classes.toggle("tooltip-ne","bc-tr"==i),n.moveRel(e.target,i)}})},statusLevel:function(e){return arguments.length>0&&this.state.set("statusLevel",e),this.state.get("statusLevel")},statusMessage:function(e){return arguments.length>0&&this.state.set("statusMessage",e),this.state.get("statusMessage")},showMenu:function(){var e=this,n=e.
settings,r;e.menu||(r=n.menu||[],r.length?r={type:"menu",items:r}:r.type=r.type||"menu",e.menu=t.create(r).parent(e).renderTo(e.getContainerElm()),e.fire("createmenu"),e.menu.reflow(),e.menu.on("cancel",function(t){t.control===e.menu&&e.focus()}),e.menu.on("show hide",function(t){t.control.items().each(function(t){t.active(t.value()==e.value())})}).fire("show"),e.menu.on("select",function(t){e.value(t.control.value())}),e.on("focusin",function(t){"INPUT"==t.target.tagName.toUpperCase()&&e.menu.hide()}),e.aria("expanded",!0)),e.menu.show(),e.menu.layoutRect({w:e.layoutRect().w}),e.menu.moveRel(e.getEl(),e.isRtl()?["br-tr","tr-br"]:["bl-tl","tl-bl"])},focus:function(){this.getEl("inp").focus()},repaint:function(){var e=this,t=e.getEl(),i=e.getEl("open"),o=e.layoutRect(),a,s,l=0,u=t.firstChild;e.statusLevel()&
;&"none"!==e.statusLevel()&&(l=parseInt(n.getRuntimeStyle(u,"padding-right"),10)-parseInt(n.getRuntimeStyle(u,"padding-left"),10)),a=i?o.w-n.getSize(i).width-10:o.w-10;var c=document;return c.all&&(!c.documentMode||c.documentMode<=8)&&(s=e.layoutRect().h-2+"px"),r(u).css({width:a-l,lineHeight:s}),e._super(),e},postRender:function(){var e=this;return r(this.getEl("inp")).on("change",function(t){e.state.set("value",t.target.value),e.fire("change",t)}),e._super()},renderHtml:function(){var e=this,t=e._id,n=e.settings,r=e.classPrefix,i=e.state.get("value")||"",o,a,s="",l="",u="";return"spellcheck"in n&&(l+=' spellcheck="'+n.spellcheck+'"'),n.maxLength&&(l+=' maxlength="'+n.maxLength+'"'),n.size&&(l+=' size="'+n.size+'"'),n.subtype&&(l+=' type="'+n.subty
pe+'"'),u='<i id="'+t+'-status" class="mce-status mce-ico" style="display: none"></i>',e.disabled()&&(l+=' disabled="disabled"'),o=n.icon,o&&"caret"!=o&&(o=r+"ico "+r+"i-"+n.icon),a=e.state.get("text"),(o||a)&&(s='<div id="'+t+'-open" class="'+r+"btn "+r+'open" tabIndex="-1" role="button"><button id="'+t+'-action" type="button" hidefocus="1" tabindex="-1">'+("caret"!=o?'<i class="'+o+'"></i>':'<i class="'+r+'caret"></i>')+(a?(o?" ":"")+a:"")+"</button></div>",e.classes.add("has-open")),'<div id="'+t+'" class="'+e.classes+'"><input id="'+t+'-inp" class="'+r+'textbox" value="'+e.encode(i,!1)
+'" hidefocus="1"'+l+' placeholder="'+e.encode(n.placeholder)+'" />'+u+s+"</div>"},value:function(e){return arguments.length?(this.state.set("value",e),this):(this.state.get("rendered")&&this.state.set("value",this.getEl("inp").value),
-this.state.get("value"))},showAutoComplete:function(e,n){var r=this;if(0===e.length)return void r.hideMenu();var i=function(e,t){return function(){r.fire("selectitem",{title:t,value:e})}};r.menu?r.menu.items().remove():r.menu=t.create({type:"menu",classes:"combobox-menu",layout:"flow"}).parent(r).renderTo(),o.each(e,function(e){r.menu.add({text:e.title,url:e.previewUrl,match:n,classes:"menu-item-ellipsis",onclick:i(e.value,e.title)})}),r.menu.renderNew(),r.hideMenu(),r.menu.on("cancel",function(e){e.control.parent()===r.menu&&(e.stopPropagation(),r.focus(),r.hideMenu())}),r.menu.on("select",function(){r.focus()});var a=r.layoutRect().w;r.menu.layoutRect({w:a,minW:0,maxW:a}),r.menu.reflow(),r.menu.show(),r.menu.moveRel(r.getEl(),r.isRtl()?["br-tr","tr-br"]:["bl-tl","tl-bl"])},hideMenu:function(){this.menu&&this.menu.hide()},bindStates:function(){var
e=this;e.state.on("change:value",function(t){e.getEl("inp").value!=t.value&&(e.getEl("inp").value=t.value)}),e.state.on("change:disabled",function(t){e.getEl("inp").disabled=t.value}),e.state.on("change:statusLevel",function(t){var r=e.getEl("status"),i=e.classPrefix,o=t.value;n.css(r,"display","none"===o?"none":""),n.toggleClass(r,i+"i-checkmark","ok"===o),n.toggleClass(r,i+"i-warning","warn"===o),n.toggleClass(r,i+"i-error","error"===o),e.classes.toggle("has-status","none"!==o),e.repaint()}),n.on(e.getEl("status"),"mouseleave",function(){e.tooltip().hide()}),e.on("cancel",function(t){e.menu&&e.menu.visible()&&(t.stopPropagation(),e.hideMenu())});var t=function(e,t){t&&t.items().length>0&&t.items().eq(e)[0].focus()};return
e.on("keydown",function(n){var r=n.keyCode;"INPUT"===n.target.nodeName&&(r===i.DOWN?(n.preventDefault(),e.fire("autocomplete"),t(0,e.menu)):r===i.UP&&(n.preventDefault(),t(-1,e.menu)))}),e._super()},remove:function(){r(this.getEl("inp")).off(),this.menu&&this.menu.remove(),this._super()}})}),r(Et,[wt],function(e){return e.extend({init:function(e){var t=this;e.spellcheck=!1,e.onaction&&(e.icon="none"),t._super(e),t.classes.add("colorbox"),t.on("change keyup postrender",function(){t.repaintColor(t.value())})},repaintColor:function(e){var t=this.getEl("open"),n=t?t.getElementsByTagName("i")[0]:null;if(n)try{n.style.background=e}catch(r){}},bindStates:function(){var e=this;return e.state.on("change:value",function(t){e.state.get("rendered")&&e.repaintColor(t.value)}),e._super()}})}),r(Nt,[bt,Ae],function(e,t){return e.extend({showPanel:fun
ction(){var e=this,n=e.settings;if(e.active(!0),e.panel)e.panel.show();else{var r=n.panel;r.type&&(r={layout:"grid",items:r}),r.role=r.role||"dialog",r.popover=!0,r.autohide=!0,r.ariaRoot=!0,e.panel=new t(r).on("hide",function(){e.active(!1)}).on("cancel",function(t){t.stopPropagation(),e.focus(),e.hidePanel()}).parent(e).renderTo(e.getContainerElm()),e.panel.fire("show"),e.panel.reflow()}e.panel.moveRel(e.getEl(),n.popoverAlign||(e.isRtl()?["bc-tr","bc-tc"]:["bc-tl","bc-tc"]))},hidePanel:function(){var e=this;e.panel&&e.panel.hide()},postRender:function(){var e=this;return e.aria("haspopup",!0),e.on("click",function(t){t.control===e&&(e.panel&&e.panel.visible()?e.hidePanel():(e.showPanel(),e.panel.focus(!!t.aria)))}),e._super()},remove:function(){return this.panel&&(this.panel.remove(),this.panel=null),this._super()}})}),r(_t,[Nt,w],f
unction(e,t){var n=t.DOM;return e.extend({init:function(e){this._super(e),this.classes.add("colorbutton")},color:function(e){return e?(this._color=e,this.getEl("preview").style.backgroundColor=e,this):this._color},resetColor:function(){return this._color=null,this.getEl("preview").style.backgroundColor=null,this},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix,r=e.state.get("text"),i=e.settings.icon?n+"ico "+n+"i-"+e.settings.icon:"",o=e.settings.image?" style=\"background-image: url('"+e.settings.image+"')\"":"",a="";return r&&(e.classes.add("btn-has-text"),a='<span class="'+n+'txt">'+e.encode(r)+"</span>"),'<div id="'+t+'" class="'+e.classes+'" role="button" tabindex="-1" aria-haspopup="true"><button role="presentation" hidefocus="1
" type="button" tabindex="-1">'+(i?'<i class="'+i+'"'+o+"></i>":"")+'<span id="'+t+'-preview" class="'+n+'preview"></span>'+a+'</button><button type="button" class="'+n+'open" hidefocus="1" tabindex="-1"> <i class="'+n+'caret"></i></button></div>'},postRender:function(){var e=this,t=e.settings.onclick;return e.on("click",function(r){r.aria&&"down"==r.aria.key||r.control!=e||n.getParent(r.target,"."+e.classPrefix+"open")||(r.stopImmediatePropagation(),t.call(e,r))}),delete e.settings.onclick,e._super()}})}),r(St,[],function(){function e(e){function i(e,i,o){var a,s,l,u,c,d;return a=0,s=0,l=0,e/=255,i/=255,o/=255,c=t(e,t(i,o)),d=n(e,n(i,o)),c==d?(l=c,{h:0,s:0,v:100*l}):(u=e==c?i-o:o==c?e-i:o-e,a=e==c?3:o==c?1:5,a=60*(a-u/(d-c)),s=(d-c)/d,l=d,{h:r(a),s:r
(100*s),v:r(100*l)})}function o(e,i,o){var a,s,l,u;if(e=(parseInt(e,10)||0)%360,i=parseInt(i,10)/100,o=parseInt(o,10)/100,i=n(0,t(i,1)),o=n(0,t(o,1)),0===i)return void(d=f=p=r(255*o));switch(a=e/60,s=o*i,l=s*(1-Math.abs(a%2-1)),u=o-s,Math.floor(a)){case 0:d=s,f=l,p=0;break;case 1:d=l,f=s,p=0;break;case 2:d=0,f=s,p=l;break;case 3:d=0,f=l,p=s;break;case 4:d=l,f=0,p=s;break;case 5:d=s,f=0,p=l;break;default:d=f=p=0}d=r(255*(d+u)),f=r(255*(f+u)),p=r(255*(p+u))}function a(){function e(e){return e=parseInt(e,10).toString(16),e.length>1?e:"0"+e}return"#"+e(d)+e(f)+e(p)}function s(){return{r:d,g:f,b:p}}function l(){return i(d,f,p)}function u(e){var t;return"object"==typeof e?"r"in e?(d=e.r,f=e.g,p=e.b):"v"in e&&o(e.h,e.s,e.v):(t=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)[^\)]*\)/gi.exec(e))?(d=parseInt(t[1],10),f=parseInt(t[2],10),p=parseInt(t[3],10)):(t=/#([0-F]{2})([0-F]{2})([0-F]{2})/gi.exec(e))?(d=parseInt(t[1],16),f=pa
rseInt(t[2],16),p=parseInt(t[3],16)):(t=/#([0-F])([0-F])([0-F])/gi.exec(e))&&(d=parseInt(t[1]+t[1],16),f=parseInt(t[2]+t[2],16),p=parseInt(t[3]+t[3],16)),d=d<0?0:d>255?255:d,f=f<0?0:f>255?255:f,p=p<0?0:p>255?255:p,c}var c=this,d=0,f=0,p=0;e&&u(e),c.toRgb=s,c.toHsv=l,c.toHex=a,c.parse=u}var t=Math.min,n=Math.max,r=Math.round;return e}),r(kt,[Pe,_e,ve,St],function(e,t,n,r){return e.extend({Defaults:{classes:"widget colorpicker"},init:function(e){this._super(e)},postRender:function(){function e(e,t){var r=n.getPos(e),i,o;return i=t.pageX-r.x,o=t.pageY-r.y,i=Math.max(0,Math.min(i/e.clientWidth,1)),o=Math.max(0,Math.min(o/e.clientHeight,1)),{x:i,y:o}}function i(e,t){var i=(360-e.h)/360;n.css(d,{top:100*i+"%"}),t||n.css(p,{left:e.s+"%",top:100-e.v+"%"}),f.style.background=new r({s:100,v:100,h:e.h}).toHex(),s.color().parse({s:e.s,v:e.v,h:e.h})}function o(t){var n;n=e(f,t),u.s=100*n.x,u.v=100*(1-n.y),i(u),s.fire("
;change")}function a(t){var n;n=e(c,t),u=l.toHsv(),u.h=360*(1-n.y),i(u,!0),s.fire("change")}var s=this,l=s.color(),u,c,d,f,p;c=s.getEl("h"),d=s.getEl("hp"),f=s.getEl("sv"),p=s.getEl("svp"),s._repaint=function(){u=l.toHsv(),i(u)},s._super(),s._svdraghelper=new t(s._id+"-sv",{start:o,drag:o}),s._hdraghelper=new t(s._id+"-h",{start:a,drag:a}),s._repaint()},rgb:function(){return this.color().toRgb()},value:function(e){var t=this;return arguments.length?(t.color().parse(e),void(t._rendered&&t._repaint())):t.color().toHex()},color:function(){return this._color||(this._color=new r),this._color},renderHtml:function(){function e(){var e,t,n="",i,a;for(i="filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr=",a=o.split(","),e=0,t=a.length-1;e<t;e++)n+='<div class="'+r+'colorpicker-h-chunk" style="height:'+100/t+"%;"+i+a[e]+&q
uot;,endColorstr="+a[e+1]+");-ms-"+i+a[e]+",endColorstr="+a[e+1]+')"></div>';return n}var t=this,n=t._id,r=t.classPrefix,i,o="#ff0000,#ff0080,#ff00ff,#8000ff,#0000ff,#0080ff,#00ffff,#00ff80,#00ff00,#80ff00,#ffff00,#ff8000,#ff0000",a="background: -ms-linear-gradient(top,"+o+");background: linear-gradient(to bottom,"+o+");";return i='<div id="'+n+'-h" class="'+r+'colorpicker-h" style="'+a+'">'+e()+'<div id="'+n+'-hp" class="'+r+'colorpicker-h-marker"></div></div>','<div id="'+n+'" class="'+t.classes+'"><div id="'+n+'-sv" class="'+r+'colorpicker-sv"><div class="'+r+'colorpicker-overlay1"><div class="'+r+'colorpicker-overlay2"><div id="'+n+'-svp" class="'+r+'colorpicker-selector1"><div class="'+r+'colorpicker-selector2&q
uot;></div></div></div></div></div>'+i+"</div>"}})}),r(Tt,[Pe],function(e){return e.extend({init:function(e){var t=this;e.delimiter||(e.delimiter="\xbb"),t._super(e),t.classes.add("path"),t.canFocus=!0,t.on("click",function(e){var n,r=e.target;(n=r.getAttribute("data-index"))&&t.fire("select",{value:t.row()[n],index:n})}),t.row(t.settings.row)},focus:function(){var e=this;return e.getEl().firstChild.focus(),e},row:function(e){return arguments.length?(this.state.set("row",e),this):this.state.get("row")},renderHtml:function(){var e=this;return'<div id="'+e._id+'" class="'+e.classes+'">'+e._getDataPathHtml(e.state.get("row"))+"</div>"},bindStates:function(){var e=this;return e.state.on("change:row",function(t){e.innerHtml(e._getDataPathHtml(t.value))}),e._super()},_getDataPathHtml:function(e){var t=t
his,n=e||[],r,i,o="",a=t.classPrefix;for(r=0,i=n.length;r<i;r++)o+=(r>0?'<div class="'+a+'divider" aria-hidden="true"> '+t.settings.delimiter+" </div>":"")+'<div role="button" class="'+a+"path-item"+(r==i-1?" "+a+"last":"")+'" data-index="'+r+'" tabindex="-1" id="'+t._id+"-"+r+'" aria-level="'+(r+1)+'">'+n[r].name+"</div>";return o||(o='<div class="'+a+'path-item">\xa0</div>'),o}})}),r(Rt,[Tt],function(e){return e.extend({postRender:function(){function e(e){if(1===e.nodeType){if("BR"==e.nodeName||e.getAttribute("data-mce-bogus"))return!0;if("bookmark"===e.getAttribute("data-mce-type"))return!0}return!1}var t=this,n=t.settings.editor;return n.settings.elementpath!==!1&&(t.on("select",function(e){n.focus(),n.s
election.select(this.row()[e.index].element),n.nodeChanged()}),n.on("nodeChange",function(r){for(var i=[],o=r.parents,a=o.length;a--;)if(1==o[a].nodeType&&!e(o[a])){var s=n.fire("ResolveName",{name:o[a].nodeName.toLowerCase(),target:o[a]});if(s.isDefaultPrevented()||i.push({name:s.name,element:o[a]}),s.isPropagationStopped())break}t.row(i)})),t._super()}})}),r(At,[Ne],function(e){return e.extend({Defaults:{layout:"flex",align:"center",defaults:{flex:1}},renderHtml:function(){var e=this,t=e._layout,n=e.classPrefix;return e.classes.add("formitem"),t.preRender(e),'<div id="'+e._id+'" class="'+e.classes+'" hidefocus="1" tabindex="-1">'+(e.settings.title?'<div id="'+e._id+'-title" class="'+n+'title">'+e.settings.title+"</div>":"")+'<div id="'+e._id+'-body" class="'+e.bodyClasses+'">'+(e.settings.html||"&
quot;)+t.renderHtml(e)+"</div></div>"}})}),r(Bt,[Ne,At,m],function(e,t,n){return e.extend({Defaults:{containerCls:"form",layout:"flex",direction:"column",align:"stretch",flex:1,padding:20,labelGap:30,spacing:10,callbacks:{submit:function(){this.submit()}}},preRender:function(){var e=this,r=e.items();e.settings.formItemDefaults||(e.settings.formItemDefaults={layout:"flex",autoResize:"overflow",defaults:{flex:1}}),r.each(function(r){var i,o=r.settings.label;o&&(i=new t(n.extend({items:{type:"label",id:r._id+"-l",text:o,flex:0,forId:r._id,disabled:r.disabled()}},e.settings.formItemDefaults)),i.type="formitem",r.aria("labelledby",r._id+"-l"),"undefined"==typeof r.settings.flex&&(r.settings.flex=1),e.replace(r,i),i.add(r))})},submit:function(){return this.fire("submit",{data:this.toJSON()})},postRender:function(){var e=thi
s;e._super(),e.fromJSON(e.settings.data)},bindStates:function(){function e(){var e=0,n=[],r,i,o;if(t.settings.labelGapCalc!==!1)for(o="children"==t.settings.labelGapCalc?t.find("formitem"):t.items(),o.filter("formitem").each(function(t){var r=t.items()[0],i=r.getEl().clientWidth;e=i>e?i:e,n.push(r)}),i=t.settings.labelGap||0,r=n.length;r--;)n[r].settings.minWidth=e+i}var t=this;t._super(),t.on("show",e),e()}})}),r(Dt,[Bt],function(e){return e.extend({Defaults:{containerCls:"fieldset",layout:"flex",direction:"column",align:"stretch",flex:1,padding:"25 15 5 15",labelGap:30,spacing:10,border:1},renderHtml:function(){var e=this,t=e._layout,n=e.classPrefix;return e.preRender(),t.preRender(e),'<fieldset id="'+e._id+'" class="'+e.classes+'" hidefocus="1" tabindex="-1">'+(e.settings.title?'<legend id="'+e._id+'-title" class="'+n+'fields
et-title">'+e.settings.title+"</legend>":"")+'<div id="'+e._id+'-body" class="'+e.bodyClasses+'">'+(e.settings.html||"")+t.renderHtml(e)+"</div></fieldset>"}})}),r(Lt,[w,z,h,it,m,_],function(e,t,n,r,i,o){var a=i.trim,s=function(e,t,n,r,i){return{type:e,title:t,url:n,level:r,attach:i}},l=function(e){for(;e=e.parentNode;){var t=e.contentEditable;if(t&&"inherit"!==t)return o.isContentEditableTrue(e)}return!1},u=function(t,n){return e.DOM.select(t,n)},c=function(e){return e.innerText||e.textContent},d=function(e){return e.id?e.id:r.uuid("h")},f=function(e){return e&&"A"===e.nodeName&&(e.id||e.name)},p=function(e){return f(e)&&m(e)},h=function(e){return e&&/^(H[1-6])$/.test(e.nodeName)},m=function(e){return l(e)&&!o.isContentEditableFalse(e)},g=function(e){return h(e)&&m(e)},v=function(e){return h(e)?parseInt(e.n
odeName.substr(1),10):0},y=function(e){var t=d(e),n=function(){e.id=t};return s("header",c(e),"#"+t,v(e),n)},b=function(e){var n=e.id||e.name,r=c(e);return s("anchor",r?r:"#"+n,"#"+n,0,t.noop)},C=function(e){return n.map(n.filter(e,g),y)},x=function(e){return n.map(n.filter(e,p),b)},w=function(e){var t=u("h1,h2,h3,h4,h5,h6,a:not([href])",e);return t},E=function(e){return a(e.title).length>0},N=function(e){var t=w(e);return n.filter(C(t).concat(x(t)),E)};return{find:N}}),r(Mt,[wt,m,h,z,I,Lt],function(e,t,n,r,i,o){var a={},s=5,l=function(e){return{title:e.title,value:{title:{raw:e.title},url:e.url,attach:e.attach}}},u=function(e){return t.map(e,l)},c=function(e,t){return{title:e,value:{title:e,url:t,attach:r.noop}}},d=function(e,t){var r=n.find(t,function(t){return t.url===e});return!r},f=function(e,t,n){var r=t in e?e[t]:n;return r===!1?null:r},p=function(e,i,o,s){var l={title:"-"},p=function(e){var a=n.filter(e
[o],function(e){return d(e,i)});return t.map(a,function(e){return{title:e,value:{title:e,url:e,attach:r.noop}}})},h=function(e){var t=n.filter(i,function(t){return t.type==e});return u(t)},g=function(){var e=h("anchor"),t=f(s,"anchor_top","#top"),n=f(s,"anchor_bottom","#bottom");return null!==t&&e.unshift(c("<top>",t)),null!==n&&e.push(c("<bottom>",n)),e},v=function(e){return n.reduce(e,function(e,t){var n=0===e.length||0===t.length;return n?e.concat(t):e.concat(l,t)},[])};return s.typeahead_urls===!1?[]:"file"===o?v([m(e,p(a)),m(e,h("header")),m(e,g())]):m(e,p(a))},h=function(e,t){var r=a[t];/^https?/.test(e)&&(r?n.indexOf(r,e)===-1&&(a[t]=r.slice(0,s).concat(e)):a[t]=[e])},m=function(e,n){var r=e.toLowerCase(),i=t.grep(n,function(e){return e.title.toLowerCase().indexOf(r)!==-1});return 1===i.length&&i[0].title===e?[]:i},g=function(e){var t=e
.title;return t.raw?t.raw:t},v=function(e,t,n,r){var i=function(i){var a=o.find(n),s=p(i,a,r,t);e.showAutoComplete(s,i)};e.on("autocomplete",function(){i(e.value())}),e.on("selectitem",function(t){var n=t.value;e.value(n.url);var i=g(n);"image"===r?e.fire("change",{meta:{alt:i,attach:n.attach}}):e.fire("change",{meta:{text:i,attach:n.attach}}),e.focus()}),e.on("click",function(t){0===e.value().length&&"INPUT"===t.target.nodeName&&i("")}),e.on("PostRender",function(){e.getRoot().on("submit",function(t){t.isDefaultPrevented()||h(e.value(),r)})})},y=function(e){var t=e.status,n=e.message;return"valid"===t?{status:"ok",message:n}:"unknown"===t?{status:"warn",message:n}:"invalid"===t?{status:"warn",message:n}:{status:"none",message:""}},b=function(e,t,n){var r=t.filepicker_validator_handler;if(r
){var i=function(t){return 0===t.length?void e.statusLevel("none"):void r({url:t,type:n},function(t){var n=y(t);e.statusMessage(n.message),e.statusLevel(n.status)})};e.state.on("change:value",function(e){i(e.value)})}};return e.extend({init:function(e){var n=this,r=tinymce.activeEditor,i=r.settings,o,a,s,l=e.filetype;e.spellcheck=!1,s=i.file_picker_types||i.file_browser_callback_types,s&&(s=t.makeMap(s,/[, ]/)),s&&!s[l]||(a=i.file_picker_callback,!a||s&&!s[l]?(a=i.file_browser_callback,!a||s&&!s[l]||(o=function(){a(n.getEl("inp").id,n.value(),l,window)})):o=function(){var e=n.fire("beforecall").meta;e=t.extend({filetype:l},e),a.call(r,function(e,t){n.value(e).fire("change",{meta:t})},n.value(),e)}),o&&(e.icon="browse",e.onaction=o),n._super(e),v(n,i,r.getBody(),l),b(n,i,l)}})}),r(Pt,[yt],function(e){return e.extend({recalc:function(e){var t=e.layoutRect(),n=e.paddingBox;e.items().filt
er(":visible").each(function(e){e.layoutRect({x:n.left,y:n.top,w:t.innerW-n.right-n.left,h:t.innerH-n.top-n.bottom}),e.recalc&&e.recalc()})}})}),r(Ot,[yt],function(e){return e.extend({recalc:function(e){var t,n,r,i,o,a,s,l,u,c,d,f,p,h,m,g,v=[],y,b,C,x,w,E,N,_,S,k,T,R,A,B,D,L,M,P,O,H,I,F,z=Math.max,U=Math.min;for(r=e.items().filter(":visible"),i=e.layoutRect(),o=e.paddingBox,a=e.settings,f=e.isRtl()?a.direction||"row-reversed":a.direction,s=a.align,l=e.isRtl()?a.pack||"end":a.pack,u=a.spacing||0,"row-reversed"!=f&&"column-reverse"!=f||(r=r.set(r.toArray().reverse()),f=f.split("-")[0]),"column"==f?(S="y",N="h",_="minH",k="maxH",R="innerH",T="top",A="deltaH",B="contentH",O="left",M="w",D="x",L="innerW",P="minW",H="right",I="deltaW",F="cont
entW"):(S="x",N="w",_="minW",k="maxW",R="innerW",T="left",A="deltaW",B="contentW",O="top",M="h",D="y",L="innerH",P="minH",H="bottom",I="deltaH",F="contentH"),d=i[R]-o[T]-o[T],E=c=0,t=0,n=r.length;t<n;t++)p=r[t],h=p.layoutRect(),m=p.settings,g=m.flex,d-=t<n-1?u:0,g>0&&(c+=g,h[k]&&v.push(p),h.flex=g),d-=h[_],y=o[O]+h[P]+o[H],y>E&&(E=y);if(x={},d<0?x[_]=i[_]-d+i[A]:x[_]=i[R]-d+i[A],x[P]=E+i[I],x[B]=i[R]-d,x[F]=E,x.minW=U(x.minW,i.maxW),x.minH=U(x.minH,i.maxH),x.minW=z(x.minW,i.startMinWidth),x.minH=z(x.minH,i.startMinHeight),!i.autoResize||x.minW==i.minW&&x.minH==i.minH){for(C=d/c,t=0,n=v.length;t<n;t++)p=v[t],h=p.layoutRect(),b=h[k],y=h[_]+h.flex*C,y>b?(d-=h[k]-h[_],c-=h.flex,h.flex=0,h.maxFlexSize=b):h.maxFlexSize=0;for(C=d/c,w=o[T],x={},0===c&&("end"=
=l?w=d+o[T]:"center"==l?(w=Math.round(i[R]/2-(i[R]-d)/2)+o[T],w<0&&(w=o[T])):"justify"==l&&(w=o[T],u=Math.floor(d/(r.length-1)))),x[D]=o[O],t=0,n=r.length;t<n;t++)p=r[t],h=p.layoutRect(),y=h.maxFlexSize||h[_],"center"===s?x[D]=Math.round(i[L]/2-h[M]/2):"stretch"===s?(x[M]=z(h[P]||0,i[L]-o[O]-o[H]),x[D]=o[O]):"end"===s&&(x[D]=i[L]-h[M]-o.top),h.flex>0&&(y+=h.flex*C),x[N]=y,x[S]=w,p.layoutRect(x),p.recalc&&p.recalc(),w+=y+u}else if(x.w=x.minW,x.h=x.minH,e.layoutRect(x),this.recalc(e),null===e._lastRect){var W=e.parent();W&&(W._lastRect=null,W.recalc())}}})}),r(Ht,[vt],function(e){return e.extend({Defaults:{containerClass:"flow-layout",controlClass:"flow-layout-item",endClass:"break"},recalc:function(e){e.items().filter(":visible").each(function(e){e.recalc&&e.recalc()})},isNative:function(){return!0}})}),r(It,[w],function(e){var n=f
unction(e,t,n){for(;n!==t;){if(n.style[e])return n.style[e];n=n.parentNode}return""},r=function(e){return/[0-9.]+px$/.test(e)?Math.round(72*parseInt(e,10)/96)+"pt":e},i=function(e){return e.replace(/[\'\"]/g,"").replace(/,\s+/g,",")},o=function(t,n){return e.DOM.getStyle(n,t,!0)},a=function(e,t){var r=n("fontSize",e,t);return""!==r?r:o("fontSize",t)},s=function(e,r){var a=n("fontFamily",e,r),s=""!==a?a:o("fontFamily",r);return s!==t?i(s):""};return{getFontSize:a,getFontFamily:s,toPt:r}}),r(Ft,[xe,Pe,Ae,m,h,w,ut,d,It],function(e,t,n,r,i,o,a,s,l){function u(e){e.settings.ui_container&&(s.container=o.DOM.select(e.settings.ui_container)[0])}function c(t){t.on("ScriptsLoaded",function(){t.rtl&&(e.rtl=!0)})}function d(e){function t(t,n){return function(){var r=this;e.on("nodeChange",function(i){var o=e.formatter,a=null;f(i.parents,function(
e){if(f(t,function(t){if(n?o.matchNode(e,n,{value:t.value})&&(a=t.value):o.matchNode(e,t.value)&&(a=t.value),a)return!1}),a)return!1}),r.value(a)})}}function i(t){return function(){var n=this,r=function(e){return e?e.split(",")[0]:""};e.on("nodeChange",function(i){var o,a=null;o=l.getFontFamily(e.getBody(),i.element),f(t,function(e){e.value.toLowerCase()===o.toLowerCase()&&(a=e.value)}),f(t,function(e){a||r(e.value).toLowerCase()!==r(o).toLowerCase()||(a=e.value)}),n.value(a),!a&&o&&n.text(r(o))})}}function o(t){return function(){var n=this;e.on("nodeChange",function(r){var i,o,a=null;i=l.getFontSize(e.getBody(),r.element),o=l.toPt(i),f(t,function(e){e.value===i?a=i:e.value===o&&(a=o)}),n.value(a),a||n.text(o)})}}function a(e){e=e.replace(/;$/,"").split(";");for(var t=e.length;t--;)e[t]=e[t].split("=");return e}function s(){function t(e){var n=[];if(e)return f(e,func
tion(e){var o={text:e.title,icon:e.icon};if(e.items)o.menu=t(e.items);else{var a=e.format||"custom"+r++;e.format||(e.name=a,i.push(e)),o.format=a,o.cmd=e.cmd}n.push(o)}),n}function n(){var n;return n=t(e.settings.style_formats_merge?e.settings.style_formats?o.concat(e.settings.style_formats):o:e.settings.style_formats||o)}var r=0,i=[],o=[{title:"Headings",items:[{title:"Heading 1",format:"h1"},{title:"Heading 2",format:"h2"},{title:"Heading 3",format:"h3"},{title:"Heading 4",format:"h4"},{title:"Heading 5",format:"h5"},{title:"Heading 6",format:"h6"}]},{title:"Inline",items:[{title:"Bold",icon:"bold",format:"bold"},{title:"Italic",icon:"italic",format:"italic"},{title:"Underline",icon:"underline",format:"underline"},{title:"Strikethrough"
;,icon:"strikethrough",format:"strikethrough"},{title:"Superscript",icon:"superscript",format:"superscript"},{title:"Subscript",icon:"subscript",format:"subscript"},{title:"Code",icon:"code",format:"code"}]},{title:"Blocks",items:[{title:"Paragraph",format:"p"},{title:"Blockquote",format:"blockquote"},{title:"Div",format:"div"},{title:"Pre",format:"pre"}]},{title:"Alignment",items:[{title:"Left",icon:"alignleft",format:"alignleft"},{title:"Center",icon:"aligncenter",format:"aligncenter"},{title:"Right",icon:"alignright",format:"alignright"},{title:"Justify",icon:"alignjustify",format:"alignjustify"}]}];return e.on("init",function(){f(i,function(t){e
.formatter.register(t.name,t)})}),{type:"menu",items:n(),onPostRender:function(t){e.fire("renderFormatsMenu",{control:t.control})},itemDefaults:{preview:!0,textStyle:function(){if(this.settings.format)return e.formatter.getCssText(this.settings.format)},onPostRender:function(){var t=this;t.parent().on("show",function(){var n,r;n=t.settings.format,n&&(t.disabled(!e.formatter.canApply(n)),t.active(e.formatter.match(n))),r=t.settings.cmd,r&&t.active(e.queryCommandState(r))})},onclick:function(){this.settings.format&&h(this.settings.format),this.settings.cmd&&e.execCommand(this.settings.cmd)}}}}function u(t){return function(){var n=this;e.formatter?e.formatter.formatChanged(t,function(e){n.active(e)}):e.on("init",function(){e.formatter.formatChanged(t,function(e){n.active(e)})})}}function c(t){return function(){function n(){var n="redo"==t?"hasRedo":"hasUndo";return!!e.undoManager&&
amp;e.undoManager[n]()}var r=this;r.disabled(!n()),e.on("Undo Redo AddUndo TypingUndo ClearUndos SwitchMode",function(){r.disabled(e.readonly||!n())})}}function d(){var t=this;e.on("VisualAid",function(e){t.active(e.hasVisual)}),t.active(e.hasVisual)}function h(t){t.control&&(t=t.control.value()),t&&e.execCommand("mceToggleFormat",!1,t)}function m(t){var n=t.length;return r.each(t,function(t){t.menu&&(t.hidden=0===m(t.menu));var r=t.format;r&&(t.hidden=!e.formatter.canApply(r)),t.hidden&&n--}),n}function g(t){var n=t.items().length;return t.items().each(function(t){t.menu&&t.visible(g(t.menu)>0),!t.menu&&t.settings.menu&&t.visible(m(t.settings.menu)>0);var r=t.settings.format;r&&t.visible(e.formatter.canApply(r)),t.visible()||n--}),n}var v;v=s(),f({bold:"Bold",italic:"Italic",underline:"Underline",strikethrough:"Strikethrough",subscript:
"Subscript",superscript:"Superscript"},function(t,n){e.addButton(n,{tooltip:t,onPostRender:u(n),onclick:function(){h(n)}})}),f({outdent:["Decrease indent","Outdent"],indent:["Increase indent","Indent"],cut:["Cut","Cut"],copy:["Copy","Copy"],paste:["Paste","Paste"],help:["Help","mceHelp"],selectall:["Select all","SelectAll"],removeformat:["Clear formatting","RemoveFormat"],visualaid:["Visual aids","mceToggleVisualAid"],newdocument:["New document","mceNewDocument"]},function(t,n){e.addButton(n,{tooltip:t[0],cmd:t[1]})}),f({blockquote:["Blockquote","mceBlockQuote"],subscript:["Subscript","Subscript"],superscript:["Superscript","Superscript"],alignleft:["Align left","JustifyLeft"],aligncenter
:["Align center","JustifyCenter"],alignright:["Align right","JustifyRight"],alignjustify:["Justify","JustifyFull"],alignnone:["No alignment","JustifyNone"]},function(t,n){e.addButton(n,{tooltip:t[0],cmd:t[1],onPostRender:u(n)})});var y=function(e){var t=e;return t.length>0&&"-"===t[0].text&&(t=t.slice(1)),t.length>0&&"-"===t[t.length-1].text&&(t=t.slice(0,t.length-1)),t},b=function(t){var n,i;if("string"==typeof t)i=t.split(" ");else if(r.isArray(t))return p(r.map(t,b));return n=r.grep(i,function(t){return"|"===t||t in e.menuItems}),r.map(n,function(t){return"|"===t?{text:"-"}:e.menuItems[t]})},C=function(t){var n=[{text:"-"}],i=r.grep(e.menuItems,function(e){return e.context===t});return r.each(i,function(e){"before"==e.separator&&n.push({text:"|"}),e.prependT
oContext?n.unshift(e):n.push(e),"after"==e.separator&&n.push({text:"|"})}),n},x=function(e){return y(e.insert_button_items?b(e.insert_button_items):C("insert"))};e.addButton("undo",{tooltip:"Undo",onPostRender:c("undo"),cmd:"undo"}),e.addButton("redo",{tooltip:"Redo",onPostRender:c("redo"),cmd:"redo"}),e.addMenuItem("newdocument",{text:"New document",icon:"newdocument",cmd:"mceNewDocument"}),e.addMenuItem("undo",{text:"Undo",icon:"undo",shortcut:"Meta+Z",onPostRender:c("undo"),cmd:"undo"}),e.addMenuItem("redo",{text:"Redo",icon:"redo",shortcut:"Meta+Y",onPostRender:c("redo"),cmd:"redo"}),e.addMenuItem("visualaid",{text:"Visual aids",selectable:!0,onPostRender:d,cmd:"mceToggleVisualAid&
quot;}),e.addButton("remove",{tooltip:"Remove",icon:"remove",cmd:"Delete"}),e.addButton("insert",{type:"menubutton",icon:"insert",menu:[],oncreatemenu:function(){this.menu.add(x(e.settings)),this.menu.renderNew()}}),f({cut:["Cut","Cut","Meta+X"],copy:["Copy","Copy","Meta+C"],paste:["Paste","Paste","Meta+V"],selectall:["Select all","SelectAll","Meta+A"],bold:["Bold","Bold","Meta+B"],italic:["Italic","Italic","Meta+I"],underline:["Underline","Underline","Meta+U"],strikethrough:["Strikethrough","Strikethrough"],subscript:["Subscript","Subscript"],superscript:["Superscript","Superscript"],removeformat:["Clear formatting","RemoveFormat&quo
t;]},function(t,n){e.addMenuItem(n,{text:t[0],icon:n,shortcut:t[2],cmd:t[1]})}),e.on("mousedown",function(){n.hideAll()}),e.addButton("styleselect",{type:"menubutton",text:"Formats",menu:v,onShowMenu:function(){e.settings.style_formats_autohide&&g(this.menu)}}),e.addButton("formatselect",function(){var n=[],r=a(e.settings.block_formats||"Paragraph=p;Heading 1=h1;Heading 2=h2;Heading 3=h3;Heading 4=h4;Heading 5=h5;Heading 6=h6;Preformatted=pre");return f(r,function(t){n.push({text:t[0],value:t[1],textStyle:function(){return e.formatter.getCssText(t[1])}})}),{type:"listbox",text:r[0][0],values:n,fixedWidth:!0,onselect:h,onPostRender:t(n)}}),e.addButton("fontselect",function(){var t="Andale Mono=andale mono,monospace;Arial=arial,helvetica,sans-serif;Arial Black=arial black,sans-serif;Book Antiqua=book antiqua,palatino,serif;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier,
monospace;Georgia=georgia,palatino,serif;Helvetica=helvetica,arial,sans-serif;Impact=impact,sans-serif;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco,monospace;Times New Roman=times new roman,times,serif;Trebuchet MS=trebuchet ms,geneva,sans-serif;Verdana=verdana,geneva,sans-serif;Webdings=webdings;Wingdings=wingdings,zapf dingbats",n=[],r=a(e.settings.font_formats||t);return f(r,function(e){n.push({text:{raw:e[0]},value:e[1],textStyle:e[1].indexOf("dings")==-1?"font-family:"+e[1]:""})}),{type:"listbox",text:"Font Family",tooltip:"Font Family",values:n,fixedWidth:!0,onPostRender:i(n),onselect:function(t){t.control.settings.value&&e.execCommand("FontName",!1,t.control.settings.value)}}}),e.addButton("fontsizeselect",function(){var t=[],n="8pt 10pt 12pt 14pt 18pt 24pt 36pt",r=e.settings.fontsize_formats||n;return f(r.split(" "),function(e){v
ar n=e,r=e,i=e.split("=");i.length>1&&(n=i[0],r=i[1]),t.push({text:n,value:r})}),{type:"listbox",text:"Font Sizes",tooltip:"Font Sizes",values:t,fixedWidth:!0,onPostRender:o(t),onclick:function(t){t.control.settings.value&&e.execCommand("FontSize",!1,t.control.settings.value)}}}),e.addMenuItem("formats",{text:"Formats",menu:v})}var f=r.each,p=function(e){return i.reduce(e,function(e,t){return e.concat(t)},[])};a.on("AddEditor",function(e){var t=e.editor;c(t),d(t),u(t)}),e.translate=function(e){return a.translate(e)},t.tooltips=!s.iOS}),r(zt,[yt],function(e){return e.extend({recalc:function(e){var t,n,r,i,o,a,s,l,u,c,d,f,p,h,m,g,v,y,b,C,x,w,E,N=[],_=[],S,k,T,R,A,B;t=e.settings,i=e.items().filter(":visible"),o=e.layoutRect(),r=t.columns||Math.ceil(Math.sqrt(i.length)),n=Math.ceil(i.length/r),y=t.spacingH||t.spacing||0,b=t.spacingV||t.spacing||0,C=t.alignH||t.align,x=t.alignV||t
.align,g=e.paddingBox,A="reverseRows"in t?t.reverseRows:e.isRtl(),C&&"string"==typeof C&&(C=[C]),x&&"string"==typeof x&&(x=[x]);for(d=0;d<r;d++)N.push(0);for(f=0;f<n;f++)_.push(0);for(f=0;f<n;f++)for(d=0;d<r&&(c=i[f*r+d],c);d++)u=c.layoutRect(),S=u.minW,k=u.minH,N[d]=S>N[d]?S:N[d],_[f]=k>_[f]?k:_[f];for(T=o.innerW-g.left-g.right,w=0,d=0;d<r;d++)w+=N[d]+(d>0?y:0),T-=(d>0?y:0)+N[d];for(R=o.innerH-g.top-g.bottom,E=0,f=0;f<n;f++)E+=_[f]+(f>0?b:0),R-=(f>0?b:0)+_[f];if(w+=g.left+g.right,E+=g.top+g.bottom,l={},l.minW=w+(o.w-o.innerW),l.minH=E+(o.h-o.innerH),l.contentW=l.minW-o.deltaW,l.contentH=l.minH-o.deltaH,l.minW=Math.min(l.minW,o.maxW),l.minH=Math.min(l.minH,o.maxH),l.minW=Math.max(l.minW,o.startMinWidth),l.minH=Math.max(l.minH,o.startMinHeight),!o.autoResize||l.minW==o.minW&&l.minH==o.minH){o.autoResize&&(l=e.layoutRect(l),l.contentW=l.minW-o.deltaW,l.contentH=l.m
inH-o.deltaH);var D;D="start"==t.packV?0:R>0?Math.floor(R/n):0;var L=0,M=t.flexWidths;if(M)for(d=0;d<M.length;d++)L+=M[d];else L=r;var P=T/L;for(d=0;d<r;d++)N[d]+=M?M[d]*P:P;for(h=g.top,f=0;f<n;f++){for(p=g.left,s=_[f]+D,d=0;d<r&&(B=A?f*r+r-1-d:f*r+d,c=i[B],c);d++)m=c.settings,u=c.layoutRect(),a=Math.max(N[d],u.startMinWidth),u.x=p,u.y=h,v=m.alignH||(C?C[d]||C[0]:null),"center"==v?u.x=p+a/2-u.w/2:"right"==v?u.x=p+a-u.w:"stretch"==v&&(u.w=a),v=m.alignV||(x?x[d]||x[0]:null),"center"==v?u.y=h+s/2-u.h/2:"bottom"==v?u.y=h+s-u.h:"stretch"==v&&(u.h=s),c.layoutRect(u),p+=a+y,c.recalc&&c.recalc();h+=s+b}}else if(l.w=l.minW,l.h=l.minH,e.layoutRect(l),this.recalc(e),null===e._lastRect){var O=e.parent();O&&(O._lastRect=null,O.recalc())}}})}),r(Ut,[Pe,c],function(e,t){return e.extend({renderHtml:function(){var e=this;return e.classes.add("iframe"),e.canFocus=!1,'
<iframe id="'+e._id+'" class="'+e.classes+'" tabindex="-1" src="'+(e.settings.url||"javascript:''")+'" frameborder="0"></iframe>'},src:function(e){this.getEl().src=e},html:function(e,n){var r=this,i=this.getEl().contentWindow.document.body;return i?(i.innerHTML=e,n&&n()):t.setTimeout(function(){r.html(e)}),this}})}),r(Wt,[Pe],function(e){return e.extend({init:function(e){var t=this;t._super(e),t.classes.add("widget").add("infobox"),t.canFocus=!1},severity:function(e){this.classes.remove("error"),this.classes.remove("warning"),this.classes.remove("success"),this.classes.add(e)},help:function(e){this.state.set("help",e)},renderHtml:function(){var e=this,t=e.classPrefix;return'<div id="'+e._id+'" class="'+e.classes+'"><div id="'+e._id+'-body">'+e.encode(e.state.get("text"))+'<button role="
button" tabindex="-1"><i class="'+t+"ico "+t+'i-help"></i></button></div></div>'},bindStates:function(){var e=this;return e.state.on("change:text",function(t){e.getEl("body").firstChild.data=e.encode(t.value),e.state.get("rendered")&&e.updateLayoutRect()}),e.state.on("change:help",function(t){
-e.classes.toggle("has-help",t.value),e.state.get("rendered")&&e.updateLayoutRect()}),e._super()}})}),r(Vt,[Pe,ve],function(e,t){return e.extend({init:function(e){var t=this;t._super(e),t.classes.add("widget").add("label"),t.canFocus=!1,e.multiline&&t.classes.add("autoscroll"),e.strong&&t.classes.add("strong")},initLayoutRect:function(){var e=this,n=e._super();if(e.settings.multiline){var r=t.getSize(e.getEl());r.width>n.maxW&&(n.minW=n.maxW,e.classes.add("multiline")),e.getEl().style.width=n.minW+"px",n.startMinH=n.h=n.minH=Math.min(n.maxH,t.getSize(e.getEl()).height)}return n},repaint:function(){var e=this;return e.settings.multiline||(e.getEl().style.lineHeight=e.layoutRect().h+"px"),e._super()},severity:function(e){this.classes.remove("error"),this.classes.remove("warning"),this.classes.remove("success"),this.classes.add(e)},re
nderHtml:function(){var e=this,t,n,r=e.settings.forId;return!r&&(n=e.settings.forName)&&(t=e.getRoot().find("#"+n)[0],t&&(r=t._id)),r?'<label id="'+e._id+'" class="'+e.classes+'"'+(r?' for="'+r+'"':"")+">"+e.encode(e.state.get("text"))+"</label>":'<span id="'+e._id+'" class="'+e.classes+'">'+e.encode(e.state.get("text"))+"</span>"},bindStates:function(){var e=this;return e.state.on("change:text",function(t){e.innerHtml(e.encode(t.value)),e.state.get("rendered")&&e.updateLayoutRect()}),e._super()}})}),r($t,[Ne],function(e){return e.extend({Defaults:{role:"toolbar",layout:"flow"},init:function(e){var t=this;t._super(e),t.classes.add("toolbar")},postRender:function(){var e=this;return e.items().each(function(e){e.classes.add("toolbar-item")}),e._super()}
})}),r(qt,[$t],function(e){return e.extend({Defaults:{role:"menubar",containerCls:"menubar",ariaRoot:!0,defaults:{type:"menubutton"}}})}),r(jt,[bt,we,qt],function(e,t,n){function r(e,t){for(;e;){if(t===e)return!0;e=e.parentNode}return!1}var i=e.extend({init:function(e){var t=this;t._renderOpen=!0,t._super(e),e=t.settings,t.classes.add("menubtn"),e.fixedWidth&&t.classes.add("fixed-width"),t.aria("haspopup",!0),t.state.set("menu",e.menu||t.render())},showMenu:function(e){var n=this,r;return n.menu&&n.menu.visible()&&e!==!1?n.hideMenu():(n.menu||(r=n.state.get("menu")||[],r.length?r={type:"menu",items:r}:r.type=r.type||"menu",r.renderTo?n.menu=r.parent(n).show().renderTo():n.menu=t.create(r).parent(n).renderTo(),n.fire("createmenu"),n.menu.reflow(),n.menu.on("cancel",function(e){e.control.parent()===n.menu&&(e.stopPropagation(),n.focus(
),n.hideMenu())}),n.menu.on("select",function(){n.focus()}),n.menu.on("show hide",function(e){e.control==n.menu&&n.activeMenu("show"==e.type),n.aria("expanded","show"==e.type)}).fire("show")),n.menu.show(),n.menu.layoutRect({w:n.layoutRect().w}),n.menu.moveRel(n.getEl(),n.isRtl()?["br-tr","tr-br"]:["bl-tl","tl-bl"]),void n.fire("showmenu"))},hideMenu:function(){var e=this;e.menu&&(e.menu.items().each(function(e){e.hideMenu&&e.hideMenu()}),e.menu.hide())},activeMenu:function(e){this.classes.toggle("active",e)},renderHtml:function(){var e=this,t=e._id,r=e.classPrefix,i=e.settings.icon,o,a=e.state.get("text"),s="";return o=e.settings.image,o?(i="none","string"!=typeof o&&(o=window.getSelection?o[0]:o[1]),o=" style=\"background-image: url('"+o+"')\""):o="",a&
amp;&(e.classes.add("btn-has-text"),s='<span class="'+r+'txt">'+e.encode(a)+"</span>"),i=e.settings.icon?r+"ico "+r+"i-"+i:"",e.aria("role",e.parent()instanceof n?"menuitem":"button"),'<div id="'+t+'" class="'+e.classes+'" tabindex="-1" aria-labelledby="'+t+'"><button id="'+t+'-open" role="presentation" type="button" tabindex="-1">'+(i?'<i class="'+i+'"'+o+"></i>":"")+s+' <i class="'+r+'caret"></i></button></div>'},postRender:function(){var e=this;return e.on("click",function(t){t.control===e&&r(t.target,e.getEl())&&(e.focus(),e.showMenu(!t.aria),t.aria&&e.menu.items().filter(":visible")[0].focus())}),e.on("mouseenter",function(t){var n=t.control,r=e.parent(),o
;n&&r&&n instanceof i&&n.parent()==r&&(r.items().filter("MenuButton").each(function(e){e.hideMenu&&e!=n&&(e.menu&&e.menu.visible()&&(o=!0),e.hideMenu())}),o&&(n.focus(),n.showMenu()))}),e._super()},bindStates:function(){var e=this;return e.state.on("change:menu",function(){e.menu&&e.menu.remove(),e.menu=null}),e._super()},remove:function(){this._super(),this.menu&&this.menu.remove()}});return i}),r(Yt,[Pe,we,d,c],function(e,t,n,r){return e.extend({Defaults:{border:0,role:"menuitem"},init:function(e){var t=this,n;t._super(e),e=t.settings,t.classes.add("menu-item"),e.menu&&t.classes.add("menu-item-expand"),e.preview&&t.classes.add("menu-item-preview"),n=t.state.get("text"),"-"!==n&&"|"!==n||(t.classes.add("menu-item-sep"),t.aria("role","separator"),t.state.
set("text","-")),e.selectable&&(t.aria("role","menuitemcheckbox"),t.classes.add("menu-item-checkbox"),e.icon="selected"),e.preview||e.selectable||t.classes.add("menu-item-normal"),t.on("mousedown",function(e){e.preventDefault()}),e.menu&&!e.ariaHideMenu&&t.aria("haspopup",!0)},hasMenus:function(){return!!this.settings.menu},showMenu:function(){var e=this,n=e.settings,r,i=e.parent();if(i.items().each(function(t){t!==e&&t.hideMenu()}),n.menu){r=e.menu,r?r.show():(r=n.menu,r.length?r={type:"menu",items:r}:r.type=r.type||"menu",i.settings.itemDefaults&&(r.itemDefaults=i.settings.itemDefaults),r=e.menu=t.create(r).parent(e).renderTo(),r.reflow(),r.on("cancel",function(t){t.stopPropagation(),e.focus(),r.hide()}),r.on("show hide",function(e){e.control.items&&e.control.items().each(function(e){e.active(e.settings.se
lected)})}).fire("show"),r.on("hide",function(t){t.control===r&&e.classes.remove("selected")}),r.submenu=!0),r._parentMenu=i,r.classes.add("menu-sub");var o=r.testMoveRel(e.getEl(),e.isRtl()?["tl-tr","bl-br","tr-tl","br-bl"]:["tr-tl","br-bl","tl-tr","bl-br"]);r.moveRel(e.getEl(),o),r.rel=o,o="menu-sub-"+o,r.classes.remove(r._lastRel).add(o),r._lastRel=o,e.classes.add("selected"),e.aria("expanded",!0)}},hideMenu:function(){var e=this;return e.menu&&(e.menu.items().each(function(e){e.hideMenu&&e.hideMenu()}),e.menu.hide(),e.aria("expanded",!1)),e},renderHtml:function(){function e(e){var t,r,i={};for(i=n.mac?{alt:"⌥",ctrl:"⌘",shift:"⇧",meta:"⌘"}:{meta:"Ctrl"},e=e.split("+"),t=0;t<e.length;t++)r=i[e[t
].toLowerCase()],r&&(e[t]=r);return e.join("+")}function t(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function r(e){var n=s.match||"";return n?e.replace(new RegExp(t(n),"gi"),function(e){return"!mce~match["+e+"]mce~match!"}):e}function i(e){return e.replace(new RegExp(t("!mce~match["),"g"),"<b>").replace(new RegExp(t("]mce~match!"),"g"),"</b>")}var o=this,a=o._id,s=o.settings,l=o.classPrefix,u=o.state.get("text"),c=o.settings.icon,d="",f=s.shortcut,p=o.encode(s.url),h="";return c&&o.parent().classes.add("menu-has-icons"),s.image&&(d=" style=\"background-image: url('"+s.image+"')\""),f&&(f=e(f)),c=l+"ico "+l+"i-"+(o.settings.icon||"none"),h="-"!==u?'<i class="'+c+'"'+d+"></i>\x
a0":"",u=i(o.encode(r(u))),p=i(o.encode(r(p))),'<div id="'+a+'" class="'+o.classes+'" tabindex="-1">'+h+("-"!==u?'<span id="'+a+'-text" class="'+l+'text">'+u+"</span>":"")+(f?'<div id="'+a+'-shortcut" class="'+l+'menu-shortcut">'+f+"</div>":"")+(s.menu?'<div class="'+l+'caret"></div>':"")+(p?'<div class="'+l+'menu-item-link">'+p+"</div>":"")+"</div>"},postRender:function(){var e=this,t=e.settings,n=t.textStyle;if("function"==typeof n&&(n=n.call(this)),n){var i=e.getEl("text");i&&i.setAttribute("style",n)}return e.on("mouseenter click",function(n){n.control===e&&(t.menu||"click"!==n.type?(e.showMenu(),n.aria&&e.menu.focus(!0)):(e.fire("select"
),r.requestAnimationFrame(function(){e.parent().hideAll()})))}),e._super(),e},hover:function(){var e=this;return e.parent().items().each(function(e){e.classes.remove("selected")}),e.classes.toggle("selected",!0),e},active:function(e){return"undefined"!=typeof e&&this.aria("checked",e),this._super(e)},remove:function(){this._super(),this.menu&&this.menu.remove()}})}),r(Xt,[g,xe,c],function(e,t,n){return function(r,i){var o=this,a,s=t.classPrefix,l;o.show=function(t,u){function c(){a&&(e(r).append('<div class="'+s+"throbber"+(i?" "+s+"throbber-inline":"")+'"></div>'),u&&u())}return o.hide(),a=!0,t?l=n.setTimeout(c,t):c(),o},o.hide=function(){var e=r.lastChild;return n.clearTimeout(l),e&&e.className.indexOf("throbber")!=-1&&e.parentNode.removeChild(e),a=!1,o}}}),r(Kt,[Ae,Yt,Xt,m],function(e,t,n,r){return e.extend({Defaults:{defa
ultType:"menuitem",border:1,layout:"stack",role:"application",bodyRole:"menu",ariaRoot:!0},init:function(e){var t=this;if(e.autohide=!0,e.constrainToViewport=!0,"function"==typeof e.items&&(e.itemsFactory=e.items,e.items=[]),e.itemDefaults)for(var n=e.items,i=n.length;i--;)n[i]=r.extend({},e.itemDefaults,n[i]);t._super(e),t.classes.add("menu")},repaint:function(){return this.classes.toggle("menu-align",!0),this._super(),this.getEl().style.height="",this.getEl("body").style.height="",this},cancel:function(){var e=this;e.hideAll(),e.fire("select")},load:function(){function e(){t.throbber&&(t.throbber.hide(),t.throbber=null)}var t=this,r,i;i=t.settings.itemsFactory,i&&(t.throbber||(t.throbber=new n(t.getEl("body"),!0),0===t.items().length?(t.throbber.show(),t.fire("loading")):t.throbber.show(100,function(){t.items().remove(),t.fire(&q
uot;loading")}),t.on("hide close",e)),t.requestTime=r=(new Date).getTime(),t.settings.itemsFactory(function(n){return 0===n.length?void t.hide():void(t.requestTime===r&&(t.getEl().style.width="",t.getEl("body").style.width="",e(),t.items().remove(),t.getEl("body").innerHTML="",t.add(n),t.renderNew(),t.fire("loaded")))}))},hideAll:function(){var e=this;return this.find("menuitem").exec("hideMenu"),e._super()},preRender:function(){var e=this;return e.items().each(function(t){var n=t.settings;if(n.icon||n.image||n.selectable)return e._hasIcons=!0,!1}),e.settings.itemsFactory&&e.on("postrender",function(){e.settings.itemsFactory&&e.load()}),e._super()}})}),r(Gt,[jt,Kt],function(e,t){return e.extend({init:function(e){function t(r){for(var a=0;a<r.length;a++){if(i=r[a].selected||e.value===r[a].value)return o=o||r[a].text,n.state.set("value",r[a].val
ue),!0;if(r[a].menu&&t(r[a].menu))return!0}}var n=this,r,i,o,a;n._super(e),e=n.settings,n._values=r=e.values,r&&("undefined"!=typeof e.value&&t(r),!i&&r.length>0&&(o=r[0].text,n.state.set("value",r[0].value)),n.state.set("menu",r)),n.state.set("text",e.text||o),n.classes.add("listbox"),n.on("select",function(t){var r=t.control;a&&(t.lastControl=a),e.multiple?r.active(!r.active()):n.value(t.control.value()),a=r})},bindStates:function(){function e(e,n){e instanceof t&&e.items().each(function(e){e.hasMenus()||e.active(e.value()===n)})}function n(e,t){var r;if(e)for(var i=0;i<e.length;i++){if(e[i].value===t)return e[i];if(e[i].menu&&(r=n(e[i].menu,t)))return r}}var r=this;return r.on("show",function(t){e(t.control,r.value())}),r.state.on("change:value",function(e){var t=n(r.state.get("menu"),e.value);t?r.text(t.text):r.text(r.set
tings.text)}),r._super()}})}),r(Jt,[xt],function(e){return e.extend({Defaults:{classes:"radio",role:"radio"}})}),r(Qt,[Pe,_e],function(e,t){return e.extend({renderHtml:function(){var e=this,t=e.classPrefix;return e.classes.add("resizehandle"),"both"==e.settings.direction&&e.classes.add("resizehandle-both"),e.canFocus=!1,'<div id="'+e._id+'" class="'+e.classes+'"><i class="'+t+"ico "+t+'i-resize"></i></div>'},postRender:function(){var e=this;e._super(),e.resizeDragHelper=new t(this._id,{start:function(){e.fire("ResizeStart")},drag:function(t){"both"!=e.settings.direction&&(t.deltaX=0),e.fire("Resize",t)},stop:function(){e.fire("ResizeEnd")}})},remove:function(){return this.resizeDragHelper&&this.resizeDragHelper.destroy(),this._super()}})}),r(Zt,[Pe],function(e){function t(e){var t="";if(e)for(var n
=0;n<e.length;n++)t+='<option value="'+e[n]+'">'+e[n]+"</option>";return t}return e.extend({Defaults:{classes:"selectbox",role:"selectbox",options:[]},init:function(e){var t=this;t._super(e),t.settings.size&&(t.size=t.settings.size),t.settings.options&&(t._options=t.settings.options),t.on("keydown",function(e){var n;13==e.keyCode&&(e.preventDefault(),t.parents().reverse().each(function(e){if(e.toJSON)return n=e,!1}),t.fire("submit",{data:n.toJSON()}))})},options:function(e){return arguments.length?(this.state.set("options",e),this):this.state.get("options")},renderHtml:function(){var e=this,n,r="";return n=t(e._options),e.size&&(r=' size = "'+e.size+'"'),'<select id="'+e._id+'" class="'+e.classes+'"'+r+">"+n+"</select>"},bindStates:function(){var e=this;return e.state.on("change:opt
ions",function(n){e.getEl().innerHTML=t(n.value)}),e._super()}})}),r(en,[Pe,_e,ve],function(e,t,n){function r(e,t,n){return e<t&&(e=t),e>n&&(e=n),e}function i(e,t,n){e.setAttribute("aria-"+t,n)}function o(e,t){var r,o,a,s,l,u;"v"==e.settings.orientation?(s="top",a="height",o="h"):(s="left",a="width",o="w"),u=e.getEl("handle"),r=(e.layoutRect()[o]||100)-n.getSize(u)[a],l=r*((t-e._minValue)/(e._maxValue-e._minValue))+"px",u.style[s]=l,u.style.height=e.layoutRect().h+"px",i(u,"valuenow",t),i(u,"valuetext",""+e.settings.previewFilter(t)),i(u,"valuemin",e._minValue),i(u,"valuemax",e._maxValue)}return e.extend({init:function(e){var t=this;e.previewFilter||(e.previewFilter=function(e){return Math.round(100*e)/100}),t._super(e),t.classes.add("slider"),"v"==e.orientation&&t.classe
s.add("vertical"),t._minValue=e.minValue||0,t._maxValue=e.maxValue||100,t._initValue=t.state.get("value")},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix;return'<div id="'+t+'" class="'+e.classes+'"><div id="'+t+'-handle" class="'+n+'slider-handle" role="slider" tabindex="-1"></div></div>'},reset:function(){this.value(this._initValue).repaint()},postRender:function(){function e(e,t,n){return(n+e)/(t-e)}function i(e,t,n){return n*(t-e)-e}function o(t,n){function o(o){var a;a=s.value(),a=i(t,n,e(t,n,a)+.05*o),a=r(a,t,n),s.value(a),s.fire("dragstart",{value:a}),s.fire("drag",{value:a}),s.fire("dragend",{value:a})}s.on("keydown",function(e){switch(e.keyCode){case 37:case 38:o(-1);break;case 39:case 40:o(1)}})}function a(e,i,o){var a,l,u,h,m;s._dragHelper=new t(s._id,{handle:s._id+"-handle",start:function(e){a=e[c],l=parseInt(
s.getEl("handle").style[d],10),u=(s.layoutRect()[p]||100)-n.getSize(o)[f],s.fire("dragstart",{value:m})},drag:function(t){var n=t[c]-a;h=r(l+n,0,u),o.style[d]=h+"px",m=e+h/u*(i-e),s.value(m),s.tooltip().text(""+s.settings.previewFilter(m)).show().moveRel(o,"bc tc"),s.fire("drag",{value:m})},stop:function(){s.tooltip().hide(),s.fire("dragend",{value:m})}})}var s=this,l,u,c,d,f,p;l=s._minValue,u=s._maxValue,"v"==s.settings.orientation?(c="screenY",d="top",f="height",p="h"):(c="screenX",d="left",f="width",p="w"),s._super(),o(l,u,s.getEl("handle")),a(l,u,s.getEl("handle"))},repaint:function(){this._super(),o(this,this.value())},bindStates:function(){var e=this;return e.state.on("change:value",function(t){o(e,t.value)}),e._super()}})}),r(tn,[Pe],function(e){return e.extend({renderHtml:function(){var e
=this;return e.classes.add("spacer"),e.canFocus=!1,'<div id="'+e._id+'" class="'+e.classes+'"></div>'}})}),r(nn,[jt,ve,g],function(e,t,n){return e.extend({Defaults:{classes:"widget btn splitbtn",role:"button"},repaint:function(){var e=this,r=e.getEl(),i=e.layoutRect(),o,a;return e._super(),o=r.firstChild,a=r.lastChild,n(o).css({width:i.w-t.getSize(a).width,height:i.h-2}),n(a).css({height:i.h-2}),e},activeMenu:function(e){var t=this;n(t.getEl().lastChild).toggleClass(t.classPrefix+"active",e)},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix,r,i=e.state.get("icon"),o=e.state.get("text"),a="";return r=e.settings.image,r?(i="none","string"!=typeof r&&(r=window.getSelection?r[0]:r[1]),r=" style=\"background-image: url('"+r+"')\""):r="",i=e.settings.icon?n+"ico "+n+"i-"+i:"",o&&a
mp;(e.classes.add("btn-has-text"),a='<span class="'+n+'txt">'+e.encode(o)+"</span>"),'<div id="'+t+'" class="'+e.classes+'" role="button" tabindex="-1"><button type="button" hidefocus="1" tabindex="-1">'+(i?'<i class="'+i+'"'+r+"></i>":"")+a+'</button><button type="button" class="'+n+'open" hidefocus="1" tabindex="-1">'+(e._menuBtnText?(i?"\xa0":"")+e._menuBtnText:"")+' <i class="'+n+'caret"></i></button></div>'},postRender:function(){var e=this,t=e.settings.onclick;return e.on("click",function(e){var n=e.target;if(e.control==this)for(;n;){if(e.aria&&"down"!=e.aria.key||"BUTTON"==n.nodeName&&n.className.indexOf("open")==-1)return e.stopImmediatePropag
ation(),void(t&&t.call(this,e));n=n.parentNode}}),delete e.settings.onclick,e._super()}})}),r(rn,[Ht],function(e){return e.extend({Defaults:{containerClass:"stack-layout",controlClass:"stack-layout-item",endClass:"break"},isNative:function(){return!0}})}),r(on,[ke,g,ve],function(e,t,n){return e.extend({Defaults:{layout:"absolute",defaults:{type:"panel"}},activateTab:function(e){var n;this.activeTabId&&(n=this.getEl(this.activeTabId),t(n).removeClass(this.classPrefix+"active"),n.setAttribute("aria-selected","false")),this.activeTabId="t"+e,n=this.getEl("t"+e),n.setAttribute("aria-selected","true"),t(n).addClass(this.classPrefix+"active"),this.items()[e].show().fire("showtab"),this.reflow(),this.items().each(function(t,n){e!=n&&t.hide()})},renderHtml:function(){var e=this,t=e._layout,n="",r=e.classPrefix;return e.
preRender(),t.preRender(e),e.items().each(function(t,i){var o=e._id+"-t"+i;t.aria("role","tabpanel"),t.aria("labelledby",o),n+='<div id="'+o+'" class="'+r+'tab" unselectable="on" role="tab" aria-controls="'+t._id+'" aria-selected="false" tabIndex="-1">'+e.encode(t.settings.title)+"</div>"}),'<div id="'+e._id+'" class="'+e.classes+'" hidefocus="1" tabindex="-1"><div id="'+e._id+'-head" class="'+r+'tabs" role="tablist">'+n+'</div><div id="'+e._id+'-body" class="'+e.bodyClasses+'">'+t.renderHtml(e)+"</div></div>"},postRender:function(){var e=this;e._super(),e.settings.activeTab=e.settings.activeTab||0,e.activateTab(e.settings.activeTab),this.on("click",function(t){var n=t.target.parentNode;if(n&&n.id==e._
id+"-head")for(var r=n.childNodes.length;r--;)n.childNodes[r]==t.target&&e.activateTab(r)})},initLayoutRect:function(){var e=this,t,r,i;r=n.getSize(e.getEl("head")).width,r=r<0?0:r,i=0,e.items().each(function(e){r=Math.max(r,e.layoutRect().minW),i=Math.max(i,e.layoutRect().minH)}),e.items().each(function(e){e.settings.x=0,e.settings.y=0,e.settings.w=r,e.settings.h=i,e.layoutRect({x:0,y:0,w:r,h:i})});var o=n.getSize(e.getEl("head")).height;return e.settings.minWidth=r,e.settings.minHeight=i+o,t=e._super(),t.deltaH+=o,t.innerH=t.h-t.deltaH,t}})}),r(an,[Pe,m,ve],function(e,t,n){return e.extend({init:function(e){var t=this;t._super(e),t.classes.add("textbox"),e.multiline?t.classes.add("multiline"):(t.on("keydown",function(e){var n;13==e.keyCode&&(e.preventDefault(),t.parents().reverse().each(function(e){if(e.toJSON)return n=e,!1}),t.fire("submit",{data:n.toJSON()}))}),t.on("keyup",function
(e){t.state.set("value",e.target.value)}))},repaint:function(){var e=this,t,n,r,i,o=0,a;t=e.getEl().style,n=e._layoutRect,a=e._lastRepaintRect||{};var s=document;return!e.settings.multiline&&s.all&&(!s.documentMode||s.documentMode<=8)&&(t.lineHeight=n.h-o+"px"),r=e.borderBox,i=r.left+r.right+8,o=r.top+r.bottom+(e.settings.multiline?8:0),n.x!==a.x&&(t.left=n.x+"px",a.x=n.x),n.y!==a.y&&(t.top=n.y+"px",a.y=n.y),n.w!==a.w&&(t.width=n.w-i+"px",a.w=n.w),n.h!==a.h&&(t.height=n.h-o+"px",a.h=n.h),e._lastRepaintRect=a,e.fire("repaint",{},!1),e},renderHtml:function(){var e=this,r=e.settings,i,o;return i={id:e._id,hidefocus:"1"},t.each(["rows","spellcheck","maxLength","size","readonly","min","max","step","list","pattern","placeholder","required&
quot;,"multiple"],function(e){i[e]=r[e]}),e.disabled()&&(i.disabled="disabled"),r.subtype&&(i.type=r.subtype),o=n.create(r.multiline?"textarea":"input",i),o.value=e.state.get("value"),o.className=e.classes,o.outerHTML},value:function(e){return arguments.length?(this.state.set("value",e),this):(this.state.get("rendered")&&this.state.set("value",this.getEl().value),this.state.get("value"))},postRender:function(){var e=this;e.getEl().value=e.state.get("value"),e._super(),e.$el.on("change",function(t){e.state.set("value",t.target.value),e.fire("change",t)})},bindStates:function(){var e=this;return e.state.on("change:value",function(t){e.getEl().value!=t.value&&(e.getEl().value=t.value)}),e.state.on("change:disabled",function(t){e.getEl().disabled=t.value}),e._super()},remove:function(){this.$el.off(),this._s
uper()}})}),r(sn,[],function(){var e=this||window,t=function(){return e.tinymce};return"function"==typeof e.define&&(e.define.amd||e.define("ephox/tinymce",[],t)),"object"==typeof module&&(module.exports=window.tinymce),{}}),a([l,u,c,d,f,p,m,g,v,y,C,w,E,N,T,A,B,D,L,M,P,O,I,F,j,Y,J,te,le,ue,ce,de,pe,me,ge,Ce,xe,we,Ee,Ne,_e,Se,ke,Te,Re,Ae,Be,De,Le,Me,Pe,Oe,He,Ie,Ue,Ve,at,st,lt,ut,dt,ft,pt,ht,mt,gt,vt,yt,bt,Ct,xt,wt,Et,Nt,_t,St,kt,Tt,Rt,At,Bt,Dt,Mt,Pt,Ot,Ht,Ft,zt,Ut,Wt,Vt,$t,qt,jt,Yt,Xt,Kt,Gt,Jt,Qt,Zt,en,tn,nn,rn,on,an])}(window);
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+!function(){var a={},b=function(b){for(var c=a[b],e=c.deps,f=c.defn,g=e.length,h=new Array(g),i=0;i<g;++i)h[i]=d(e[i]);var j=f.apply(null,h);if(void 0===j)throw"module ["+b+"] returned undefined";c.instance=j},c=function(b,c,d){if("string"!=typeof b)throw"module id must be a string";if(void 0===c)throw"no dependencies for "+b;if(void 0===d)throw"no definition function for "+b;a[b]={deps:c,defn:d,instance:void 0}},d=function(c){var d=a[c];if(void 0===d)throw"module ["+c+"] was undefined";return void 0===d.instance&&b(c),d.instance},e=function(a,b){for(var c=a.length,e=new Array(c),f=0;f<c;++f)e.push(d(a[f]));b.apply(null,b)},f={};f.bolt={module:{api:{define:c,require:e,demand:d}}};var g=c,h=function(a,b){g(a,[],function(){return b})};g("3",[],function(){"use strict";function a
(a,b,c){var d,e,g,h,i,k;return d=b.x,e=b.y,g=a.w,h=a.h,i=b.w,k=b.h,c=(c||"").split(""),"b"===c[0]&&(e+=k),"r"===c[1]&&(d+=i),"c"===c[0]&&(e+=j(k/2)),"c"===c[1]&&(d+=j(i/2)),"b"===c[3]&&(e-=h),"r"===c[4]&&(d-=g),"c"===c[3]&&(e-=j(h/2)),"c"===c[4]&&(d-=j(g/2)),f(d,e,g,h)}function b(b,c,d,e){var f,g;for(g=0;g<e.length;g++)if(f=a(b,c,e[g]),f.x>=d.x&&f.x+f.w<=d.w+d.x&&f.y>=d.y&&f.y+f.h<=d.h+d.y)return e[g];return null}function c(a,b,c){return f(a.x-b,a.y-c,a.w+2*b,a.h+2*c)}function d(a,b){var c,d,e,g;return c=i(a.x,b.x),d=i(a.y,b.y),e=h(a.x+a.w,b.x+b.w),g=h(a.y+a.h,b.y+b.h),e-c<0||g-d<0?null:f(c,d,e-c,g-d)}function e(a,b,c){var d,e,g,h,j,k,l,m,n,o;return j=a.x,k=a.y,l=a.x+a.w,m=a.y+a.h,n=b.x+b.w,o=b.y+b.h,d=i(0,b.x-j),e=i(0,b.y-k),g=i(0,l-n),h=i(0,m-o),j+=d,k+=e,c&&(l+=d,m+=
e,j-=g,k-=h),l-=g,m-=h,f(j,k,l-j,m-k)}function f(a,b,c,d){return{x:a,y:b,w:c,h:d}}function g(a){return f(a.left,a.top,a.width,a.height)}var h=Math.min,i=Math.max,j=Math.round;return{inflate:c,relativePosition:a,findBestRelativePosition:b,intersect:d,clamp:e,create:f,fromClientRect:g}}),g("4",[],function(){function a(a,b){return function(){a.apply(b,arguments)}}function b(b){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof b)throw new TypeError("not a function");this._state=null,this._value=null,this._deferreds=[],h(b,a(d,this),a(e,this))}function c(a){var b=this;return null===this._state?void this._deferreds.push(a):void i(function(){var c=b._state?a.onFulfilled:a.onRejected;if(null===c)return void(b._state?a.resolve:a.reject)(b._value);var d;try{d=c(b._value)}catch(b){return void a.reject(b)}a.resolve(d)})}function d(b){try{if(b===this)throw new TypeError("A promise cann
ot be resolved with itself.");if(b&&("object"==typeof b||"function"==typeof b)){var c=b.then;if("function"==typeof c)return void h(a(c,b),a(d,this),a(e,this))}this._state=!0,this._value=b,f.call(this)}catch(a){e.call(this,a)}}function e(a){this._state=!1,this._value=a,f.call(this)}function f(){for(var a=0,b=this._deferreds.length;a<b;a++)c.call(this,this._deferreds[a]);this._deferreds=null}function g(a,b,c,d){this.onFulfilled="function"==typeof a?a:null,this.onRejected="function"==typeof b?b:null,this.resolve=c,this.reject=d}function h(a,b,c){var d=!1;try{a(function(a){d||(d=!0,b(a))},function(a){d||(d=!0,c(a))})}catch(a){if(d)return;d=!0,c(a)}}if(window.Promise)return window.Promise;var i=b.immediateFn||"function"==typeof setImmediate&&setImmediate||function(a){setTimeout(a,1)},j=Array.isArray||function(a){return"[object Array]"===Object.prototype.toString.call(a)};return b.prototype["
;catch"]=function(a){return this.then(null,a)},b.prototype.then=function(a,d){var e=this;return new b(function(b,f){c.call(e,new g(a,d,b,f))})},b.all=function(){var a=Array.prototype.slice.call(1===arguments.length&&j(arguments[0])?arguments[0]:arguments);return new b(function(b,c){function d(f,g){try{if(g&&("object"==typeof g||"function"==typeof g)){var h=g.then;if("function"==typeof h)return void h.call(g,function(a){d(f,a)},c)}a[f]=g,0===--e&&b(a)}catch(a){c(a)}}if(0===a.length)return b([]);for(var e=a.length,f=0;f<a.length;f++)d(f,a[f])})},b.resolve=function(a){return a&&"object"==typeof a&&a.constructor===b?a:new b(function(b){b(a)})},b.reject=function(a){return new b(function(b,c){c(a)})},b.race=function(a){return new b(function(b,c){for(var d=0,e=a.length;d<e;d++)a[d].then(b,c)})},b}),g("5",["4"],function(a){function b(a,b){function c(a){window.setTimeout(a,0)}var d,
e=window.requestAnimationFrame,f=["ms","moz","webkit"];for(d=0;d<f.length&&!e;d++)e=window[f[d]+"RequestAnimationFrame"];e||(e=c),e(a,b)}function c(a,b){return"number"!=typeof b&&(b=0),setTimeout(a,b)}function d(a,b){return"number"!=typeof b&&(b=1),setInterval(a,b)}function e(a){return clearTimeout(a)}function f(a){return clearInterval(a)}function g(a,b){var d,e;return e=function(){var e=arguments;clearTimeout(d),d=c(function(){a.apply(this,e)},b)},e.stop=function(){clearTimeout(d)},e}var h;return{requestAnimationFrame:function(c,d){return h?void h.then(c):void(h=new a(function(a){d||(d=document.body),b(a,d)}).then(c))},setTimeout:c,setInterval:d,setEditorTimeout:function(a,b,d){return c(function(){a.removed||b()},d)},setEditorInterval:function(a,b,c){var e;return e=d(function(){a.removed?clearInterval(e):b()},c)},debounce:g,throttle:g,clearInterval:f,clearTimeout:e}}),g("6",[],function(
){function a(a){return"matchMedia"in window&&matchMedia(a).matches}var b,c,d,e,f,g,h,i,j,k,l,m,n,o=navigator,p=o.userAgent;b=window.opera&&window.opera.buildNumber,j=/Android/.test(p),c=/WebKit/.test(p),d=!c&&!b&&/MSIE/gi.test(p)&&/Explorer/gi.test(o.appName),d=d&&/MSIE (\w+)\./.exec(p)[1],e=p.indexOf("Trident/")!=-1&&(p.indexOf("rv:")!=-1||o.appName.indexOf("Netscape")!=-1)&&11,f=p.indexOf("Edge/")!=-1&&!d&&!e&&12,d=d||e||f,g=!c&&!e&&/Gecko/.test(p),h=p.indexOf("Mac")!=-1,i=/(iPad|iPhone)/.test(p),k="FormData"in window&&"FileReader"in window&&"URL"in window&&!!URL.createObjectURL,l=a("only screen and (max-device-width: 480px)")&&(j||i),m=a("only screen and (min-width: 800px)")&&(j||i),n=p.indexOf("Windows Phone")!=-1,f&
;&(c=!1);var q=!i||k||p.match(/AppleWebKit\/(\d*)/)[1]>=534;return{opera:b,webkit:c,ie:d,gecko:g,mac:h,iOS:i,android:j,contentEditable:q,transparentSrc:"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",caretAfter:8!=d,range:window.getSelection&&"Range"in window,documentMode:d&&!f?document.documentMode||7:10,fileApi:k,ceFalse:d===!1||d>8,canHaveCSP:d===!1||d>11,desktop:!l&&!m,windowsPhone:n}}),g("7",["5","6"],function(a,b){"use strict";function c(a,b,c,d){a.addEventListener?a.addEventListener(b,c,d||!1):a.attachEvent&&a.attachEvent("on"+b,c)}function d(a,b,c,d){a.removeEventListener?a.removeEventListener(b,c,d||!1):a.detachEvent&&a.detachEvent("on"+b,c)}function e(a,b){var c,d=b;return c=a.path,c&&c.length>0&&(d=c[0]),a.deepPath&&(c=a.deepPath(),c&&c.length>0&&(d=c[0])),d}funct
ion f(a,c){var d,f,g=c||{};for(d in a)k[d]||(g[d]=a[d]);if(g.target||(g.target=g.srcElement||document),b.experimentalShadowDom&&(g.target=e(a,g.target)),a&&j.test(a.type)&&a.pageX===f&&a.clientX!==f){var h=g.target.ownerDocument||document,i=h.documentElement,o=h.body;g.pageX=a.clientX+(i&&i.scrollLeft||o&&o.scrollLeft||0)-(i&&i.clientLeft||o&&o.clientLeft||0),g.pageY=a.clientY+(i&&i.scrollTop||o&&o.scrollTop||0)-(i&&i.clientTop||o&&o.clientTop||0)}return g.preventDefault=function(){g.isDefaultPrevented=n,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},g.stopPropagation=function(){g.isPropagationStopped=n,a&&(a.stopPropagation?a.stopPropagation():a.cancelBubble=!0)},g.stopImmediatePropagation=function(){g.isImmediatePropagationStopped=n,g.stopPropagation()},l(g)===!1&&(g.isDefaultPrevented=m,g.isPropagationStopped=m,g.isImmediatePropagationStopped=m),&quo
t;undefined"==typeof g.metaKey&&(g.metaKey=!1),g}function g(e,f,g){function h(){return"complete"===l.readyState||"interactive"===l.readyState&&l.body}function i(){g.domLoaded||(g.domLoaded=!0,f(m))}function j(){h()&&(d(l,"readystatechange",j),i())}function k(){try{l.documentElement.doScroll("left")}catch(b){return void a.setTimeout(k)}i()}var l=e.document,m={type:"ready"};return g.domLoaded?void f(m):(!l.addEventListener||b.ie&&b.ie<11?(c(l,"readystatechange",j),l.documentElement.doScroll&&e.self===e.top&&k()):h()?i():c(e,"DOMContentLoaded",i),void c(e,"load",i))}function h(){function a(a,b){var c,d,e,f,g=m[b];if(c=g&&g[a.type])for(d=0,e=c.length;d<e;d++)if(f=c[d],f&&f.func.call(f.scope,a)===!1&&a.preventDefault(),a.isImmediatePropagationStopped())return}var b,e,h,j,k,l=this,m={};e=i+(+new Date).toString(32),j="onmous
eenter"in document.documentElement,h="onfocusin"in document.documentElement,k={mouseenter:"mouseover",mouseleave:"mouseout"},b=1,l.domLoaded=!1,l.events=m,l.bind=function(d,i,n,o){function p(b){a(f(b||x.event),q)}var q,r,s,t,u,v,w,x=window;if(d&&3!==d.nodeType&&8!==d.nodeType){for(d[e]?q=d[e]:(q=b++,d[e]=q,m[q]={}),o=o||d,i=i.split(" "),s=i.length;s--;)t=i[s],v=p,u=w=!1,"DOMContentLoaded"===t&&(t="ready"),l.domLoaded&&"ready"===t&&"complete"==d.readyState?n.call(o,f({type:t})):(j||(u=k[t],u&&(v=function(b){var c,d;if(c=b.currentTarget,d=b.relatedTarget,d&&c.contains)d=c.contains(d);else for(;d&&d!==c;)d=d.parentNode;d||(b=f(b||x.event),b.type="mouseout"===b.type?"mouseleave":"mouseenter",b.target=c,a(b,q))})),h||"focusin"!==t&&"focusout"!==t||(w=!0,u="focusin"===t?"
;focus":"blur",v=function(b){b=f(b||x.event),b.type="focus"===b.type?"focusin":"focusout",a(b,q)}),r=m[q][t],r?"ready"===t&&l.domLoaded?n({type:t}):r.push({func:n,scope:o}):(m[q][t]=r=[{func:n,scope:o}],r.fakeName=u,r.capture=w,r.nativeHandler=v,"ready"===t?g(d,v,l):c(d,u||t,v,w)));return d=r=0,n}},l.unbind=function(a,b,c){var f,g,h,i,j,k;if(!a||3===a.nodeType||8===a.nodeType)return l;if(f=a[e]){if(k=m[f],b){for(b=b.split(" "),h=b.length;h--;)if(j=b[h],g=k[j]){if(c)for(i=g.length;i--;)if(g[i].func===c){var n=g.nativeHandler,o=g.fakeName,p=g.capture;g=g.slice(0,i).concat(g.slice(i+1)),g.nativeHandler=n,g.fakeName=o,g.capture=p,k[j]=g}c&&0!==g.length||(delete k[j],d(a,g.fakeName||j,g.nativeHandler,g.capture))}}else{for(j in k)g=k[j],d(a,g.fakeName||j,g.nativeHandler,g.capture);k={}}for(j in k)return l;delete m[f];try{delete a[e]}catch(b){a[e]=null}}return l},l.fire=function(b,c,d){var g;if(!b||3
===b.nodeType||8===b.nodeType)return l;d=f(null,d),d.type=c,d.target=b;do g=b[e],g&&a(d,g),b=b.parentNode||b.ownerDocument||b.defaultView||b.parentWindow;while(b&&!d.isPropagationStopped());return l},l.clean=function(a){var b,c,d=l.unbind;if(!a||3===a.nodeType||8===a.nodeType)return l;if(a[e]&&d(a),a.getElementsByTagName||(a=a.document),a&&a.getElementsByTagName)for(d(a),c=a.getElementsByTagName("*"),b=c.length;b--;)a=c[b],a[e]&&d(a);return l},l.destroy=function(){m={}},l.cancel=function(a){return a&&(a.preventDefault(),a.stopImmediatePropagation()),!1}}var i="mce-data-",j=/^(?:mouse|contextmenu)|click/,k={keyLocation:1,layerX:1,layerY:1,returnValue:1,webkitMovementX:1,webkitMovementY:1,keyIdentifier:1},l=function(a){return a.isDefaultPrevented===n||a.isDefaultPrevented===m},m=function(){return!1},n=function(){return!0};return h.Event=new h,h.Event.bind(window,"ready",function(){}),h}),g("8",[],f
unction(){function a(a,b,c,d){var e,f,g,h,i,k,m,n,o,p;if((b?b.ownerDocument||b:N)!==F&&E(b),b=b||F,c=c||[],!a||"string"!=typeof a)return c;if(1!==(h=b.nodeType)&&9!==h)return[];if(H&&!d){if(e=qa.exec(a))if(g=e[1]){if(9===h){if(f=b.getElementById(g),!f||!f.parentNode)return c;if(f.id===g)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(g))&&L(b,f)&&f.id===g)return c.push(f),c}else{if(e[2])return $.apply(c,b.getElementsByTagName(a)),c;if((g=e[3])&&u.getElementsByClassName)return $.apply(c,b.getElementsByClassName(g)),c}if(u.qsa&&(!I||!I.test(a))){if(n=m=M,o=b,p=9===h&&a,1===h&&"object"!==b.nodeName.toLowerCase()){for(k=y(a),(m=b.getAttribute("id"))?n=m.replace(sa,"\\$&"):b.setAttribute("id",n),n="[id='"+n+"'] ",i=k.length;i--;)k[i]=n+l(k[i]);o=ra.test(a)&&j(b.parentNode)||b,p=k.join(",")
}if(p)try{return $.apply(c,o.querySelectorAll(p)),c}catch(a){}finally{m||b.removeAttribute("id")}}}return A(a.replace(ga,"$1"),b,c,d)}function b(){function a(c,d){return b.push(c+" ")>v.cacheLength&&delete a[b.shift()],a[c+" "]=d}var b=[];return a}function c(a){return a[M]=!0,a}function d(a){var b=F.createElement("div");try{return!!a(b)}catch(a){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function e(a,b){for(var c=a.split("|"),d=a.length;d--;)v.attrHandle[c[d]]=b}function f(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||V)-(~a.sourceIndex||V);if(d)return d;if(c)for(;c=c.nextSibling;)if(c===b)return-1;return a?1:-1}function g(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function h(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"butto
n"===c)&&b.type===a}}function i(a){return c(function(b){return b=+b,c(function(c,d){for(var e,f=a([],c.length,b),g=f.length;g--;)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function j(a){return a&&typeof a.getElementsByTagName!==U&&a}function k(){}function l(a){for(var b=0,c=a.length,d="";b<c;b++)d+=a[b].value;return d}function m(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=P++;return b.first?function(b,c,f){for(;b=b[d];)if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[O,f];if(g){for(;b=b[d];)if((1===b.nodeType||e)&&a(b,c,g))return!0}else for(;b=b[d];)if(1===b.nodeType||e){if(i=b[M]||(b[M]={}),(h=i[d])&&h[0]===O&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function n(a){return a.length>1?function(b,c,d){for(var e=a.length;e--;)if(!a[e](b,c,d))return!1;return!0}:a[0]}function o(b,c,d){for(var e=0,f=c.length;e<f;e++)a(b,c[e],d);return d}function p(a,b,c,d,e){for(var
f,g=[],h=0,i=a.length,j=null!=b;h<i;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function q(a,b,d,e,f,g){return e&&!e[M]&&(e=q(e)),f&&!f[M]&&(f=q(f,g)),c(function(c,g,h,i){var j,k,l,m=[],n=[],q=g.length,r=c||o(b||"*",h.nodeType?[h]:h,[]),s=!a||!c&&b?r:p(r,m,a,h,i),t=d?f||(c?a:q||e)?[]:g:s;if(d&&d(s,t,h,i),e)for(j=p(t,n),e(j,[],h,i),k=j.length;k--;)(l=j[k])&&(t[n[k]]=!(s[n[k]]=l));if(c){if(f||a){if(f){for(j=[],k=t.length;k--;)(l=t[k])&&j.push(s[k]=l);f(null,t=[],j,i)}for(k=t.length;k--;)(l=t[k])&&(j=f?aa.call(c,l):m[k])>-1&&(c[j]=!(g[j]=l))}}else t=p(t===g?t.splice(q,t.length):t),f?f(null,g,t,i):$.apply(g,t)})}function r(a){for(var b,c,d,e=a.length,f=v.relative[a[0].type],g=f||v.relative[" "],h=f?1:0,i=m(function(a){return a===b},g,!0),j=m(function(a){return aa.call(b,a)>-1},g,!0),k=[function(a,c,d){return!f&&(d||c!==B)||((b=c
).nodeType?i(a,c,d):j(a,c,d))}];h<e;h++)if(c=v.relative[a[h].type])k=[m(n(k),c)];else{if(c=v.filter[a[h].type].apply(null,a[h].matches),c[M]){for(d=++h;d<e&&!v.relative[a[d].type];d++);return q(h>1&&n(k),h>1&&l(a.slice(0,h-1).concat({value:" "===a[h-2].type?"*":""})).replace(ga,"$1"),c,h<d&&r(a.slice(h,d)),d<e&&r(a=a.slice(d)),d<e&&l(a))}k.push(c)}return n(k)}function s(b,d){var e=d.length>0,f=b.length>0,g=function(c,g,h,i,j){var k,l,m,n=0,o="0",q=c&&[],r=[],s=B,t=c||f&&v.find.TAG("*",j),u=O+=null==s?1:Math.random()||.1,w=t.length;for(j&&(B=g!==F&&g);o!==w&&null!=(k=t[o]);o++){if(f&&k){for(l=0;m=b[l++];)if(m(k,g,h)){i.push(k);break}j&&(O=u)}e&&((k=!m&&k)&&n--,c&&q.push(k))}if(n+=o,e&&o!==n){for(l=0;m=d[l++];)m(q,r,g,h);if(c){if(n>0)for(;o--;)q[o]||r[o]|
|(r[o]=Y.call(i));r=p(r)}$.apply(i,r),j&&!c&&r.length>0&&n+d.length>1&&a.uniqueSort(i)}return j&&(O=u,B=s),q};return e?c(g):g}var t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M="sizzle"+-new Date,N=window.document,O=0,P=0,Q=b(),R=b(),S=b(),T=function(a,b){return a===b&&(D=!0),0},U="undefined",V=1<<31,W={}.hasOwnProperty,X=[],Y=X.pop,Z=X.push,$=X.push,_=X.slice,aa=X.indexOf||function(a){for(var b=0,c=this.length;b<c;b++)if(this[b]===a)return b;return-1},ba="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",ca="[\\x20\\t\\r\\n\\f]",da="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",ea="\\["+ca+"*("+da+")(?:"+ca+"*([*^$|!~]?=)"+ca+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+da+"))|)"+ca+"*\\]",fa=":("+da+")(?
:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+ea+")*)|.*)\\)|)",ga=new RegExp("^"+ca+"+|((?:^|[^\\\\])(?:\\\\.)*)"+ca+"+$","g"),ha=new RegExp("^"+ca+"*,"+ca+"*"),ia=new RegExp("^"+ca+"*([>+~]|"+ca+")"+ca+"*"),ja=new RegExp("="+ca+"*([^\\]'\"]*?)"+ca+"*\\]","g"),ka=new RegExp(fa),la=new RegExp("^"+da+"$"),ma={ID:new RegExp("^#("+da+")"),CLASS:new RegExp("^\\.("+da+")"),TAG:new RegExp("^("+da+"|[*])"),ATTR:new RegExp("^"+ea),PSEUDO:new RegExp("^"+fa),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ca+"*(even|odd|(([+-]|)(\\d*)n|)"+ca+"*(?:([+-]|)"+ca+"*(\\d+)|))"+ca+"*\\)|)","i"),
bool:new RegExp("^(?:"+ba+")$","i"),needsContext:new RegExp("^"+ca+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ca+"*((?:-\\d)?\\d*)"+ca+"*\\)|)(?=[^-]|$)","i")},na=/^(?:input|select|textarea|button)$/i,oa=/^h\d$/i,pa=/^[^{]+\{\s*\[native \w/,qa=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ra=/[+~]/,sa=/'|\\/g,ta=new RegExp("\\\\([\\da-f]{1,6}"+ca+"?|("+ca+")|.)","ig"),ua=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{$.apply(X=_.call(N.childNodes),N.childNodes),X[N.childNodes.length].nodeType}catch(a){$={apply:X.length?function(a,b){Z.apply(a,_.call(b))}:function(a,b){for(var c=a.length,d=0;a[c++]=b[d++];);a.length=c-1}}}u=a.support={},x=a.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.node
Name},E=a.setDocument=function(a){function b(a){try{return a.top}catch(a){}return null}var c,e=a?a.ownerDocument||a:N,g=e.defaultView;return e!==F&&9===e.nodeType&&e.documentElement?(F=e,G=e.documentElement,H=!x(e),g&&g!==b(g)&&(g.addEventListener?g.addEventListener("unload",function(){E()},!1):g.attachEvent&&g.attachEvent("onunload",function(){E()})),u.attributes=d(function(a){return a.className="i",!a.getAttribute("className")}),u.getElementsByTagName=d(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),u.getElementsByClassName=pa.test(e.getElementsByClassName),u.getById=d(function(a){return G.appendChild(a).id=M,!e.getElementsByName||!e.getElementsByName(M).length}),u.getById?(v.find.ID=function(a,b){if(typeof b.getElementById!==U&&H){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},v.filter.ID=function(a){var b=a.re
place(ta,ua);return function(a){return a.getAttribute("id")===b}}):(delete v.find.ID,v.filter.ID=function(a){var b=a.replace(ta,ua);return function(a){var c=typeof a.getAttributeNode!==U&&a.getAttributeNode("id");return c&&c.value===b}}),v.find.TAG=u.getElementsByTagName?function(a,b){if(typeof b.getElementsByTagName!==U)return b.getElementsByTagName(a)}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){for(;c=f[e++];)1===c.nodeType&&d.push(c);return d}return f},v.find.CLASS=u.getElementsByClassName&&function(a,b){if(H)return b.getElementsByClassName(a)},J=[],I=[],(u.qsa=pa.test(e.querySelectorAll))&&(d(function(a){a.innerHTML="<select msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&I.push("[*^$]="+ca+"*(?:''|\"\")"),a.querySelectorAll("[selected]&qu
ot;).length||I.push("\\["+ca+"*(?:value|"+ba+")"),a.querySelectorAll(":checked").length||I.push(":checked")}),d(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&I.push("name"+ca+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||I.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),I.push(",.*:")})),(u.matchesSelector=pa.test(K=G.matches||G.webkitMatchesSelector||G.mozMatchesSelector||G.oMatchesSelector||G.msMatchesSelector))&&d(function(a){u.disconnectedMatch=K.call(a,"div"),K.call(a,"[s!='']:x"),J.push("!=",fa)}),I=I.length&&new RegExp(I.join("|")),J=J.length&&new RegExp(J.join("|")),c=pa.test(G.compareDocumentP
osition),L=c||pa.test(G.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)for(;b=b.parentNode;)if(b===a)return!0;return!1},T=c?function(a,b){if(a===b)return D=!0,0;var c=!a.compareDocumentPosition-!b.compareDocumentPosition;return c?c:(c=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&c||!u.sortDetached&&b.compareDocumentPosition(a)===c?a===e||a.ownerDocument===N&&L(N,a)?-1:b===e||b.ownerDocument===N&&L(N,b)?1:C?aa.call(C,a)-aa.call(C,b):0:4&c?-1:1)}:function(a,b){if(a===b)return D=!0,0;var c,d=0,g=a.parentNode,h=b.parentNode,i=[a],j=[b];if(!g||!h)return a===e?-1:b===e?1:g?-1:h?1:C?aa.call(C,a)-aa.call(C,b):0;if(g===h)return f(a,b);for(c=a;c=c.parentNode;)i.unshift(c);for(c=b;c=c.parentNode;)j.unshift(c);for(;i[d]===j[d];)d++;ret
urn d?f(i[d],j[d]):i[d]===N?-1:j[d]===N?1:0},e):F},a.matches=function(b,c){return a(b,null,null,c)},a.matchesSelector=function(b,c){if((b.ownerDocument||b)!==F&&E(b),c=c.replace(ja,"='$1']"),u.matchesSelector&&H&&(!J||!J.test(c))&&(!I||!I.test(c)))try{var d=K.call(b,c);if(d||u.disconnectedMatch||b.document&&11!==b.document.nodeType)return d}catch(a){}return a(c,F,null,[b]).length>0},a.contains=function(a,b){return(a.ownerDocument||a)!==F&&E(a),L(a,b)},a.attr=function(a,b){(a.ownerDocument||a)!==F&&E(a);var c=v.attrHandle[b.toLowerCase()],d=c&&W.call(v.attrHandle,b.toLowerCase())?c(a,b,!H):void 0;return void 0!==d?d:u.attributes||!H?a.getAttribute(b):(d=a.getAttributeNode(b))&&d.specified?d.value:null},a.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},a.uniqueSort=function(a){var b,c=[],d=0,e=0;if(D=!u.detectDuplicates,C=!u.sortStable&&a.slice(0),a.so
rt(T),D){for(;b=a[e++];)b===a[e]&&(d=c.push(e));for(;d--;)a.splice(c[d],1)}return C=null,a},w=a.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(1===e||9===e||11===e){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=w(a)}else if(3===e||4===e)return a.nodeValue}else for(;b=a[d++];)c+=w(b);return c},v=a.selectors={cacheLength:50,createPseudo:c,match:ma,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ta,ua),a[3]=(a[3]||a[4]||a[5]||"").replace(ta,ua),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(b){return b[1]=b[1].toLowerCase(),"nth"===b[1].slice(0,3)?(b[3]||a.error(b[0]),b[4]=+(b[4]?b[5]+(b[6]||
1):2*("even"===b[3]||"odd"===b[3])),b[5]=+(b[7]+b[8]||"odd"===b[3])):b[3]&&a.error(b[0]),b},PSEUDO:function(a){var b,c=!a[6]&&a[2];return ma.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&ka.test(c)&&(b=y(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ta,ua).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=Q[a+" "];return b||(b=new RegExp("(^|"+ca+")"+a+"("+ca+"|$)"))&&Q(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==U&&a.getAttribute("class")||"")})},ATTR:function(b,c,d){return function(e){var f=a.attr(e,b);return null==f?"!=&quo
t;===c:!c||(f+="","="===c?f===d:"!="===c?f!==d:"^="===c?d&&0===f.indexOf(d):"*="===c?d&&f.indexOf(d)>-1:"$="===c?d&&f.slice(-d.length)===d:"~="===c?(" "+f+" ").indexOf(d)>-1:"|="===c&&(f===d||f.slice(0,d.length+1)===d+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){for(;p;){for(l=b;l=l[p];)if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){for(k=q[M]||(q[M]={}),j=k[a]||[],n=j[0]===O&&j[
1],m=j[0]===O&&j[2],l=n&&q.childNodes[n];l=++n&&l&&l[p]||(m=n=0)||o.pop();)if(1===l.nodeType&&++m&&l===b){k[a]=[O,n,m];break}}else if(s&&(j=(b[M]||(b[M]={}))[a])&&j[0]===O)m=j[1];else for(;(l=++n&&l&&l[p]||(m=n=0)||o.pop())&&((h?l.nodeName.toLowerCase()!==r:1!==l.nodeType)||!++m||(s&&((l[M]||(l[M]={}))[a]=[O,m]),l!==b)););return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(b,d){var e,f=v.pseudos[b]||v.setFilters[b.toLowerCase()]||a.error("unsupported pseudo: "+b);return f[M]?f(d):f.length>1?(e=[b,b,"",d],v.setFilters.hasOwnProperty(b.toLowerCase())?c(function(a,b){for(var c,e=f(a,d),g=e.length;g--;)c=aa.call(a,e[g]),a[c]=!(b[c]=e[g])}):function(a){return f(a,0,e)}):f}},pseudos:{not:c(function(a){var b=[],d=[],e=z(a.replace(ga,"$1"));return e[M]?c(function(a,b,c,d){for(var f,g=e(a,null,d,[]),h=a.length;h--;)(f=g[h])&&(a[h]=!(b[h]=f))}):
function(a,c,f){return b[0]=a,e(b,null,f,d),!d.pop()}}),has:c(function(b){return function(c){return a(b,c).length>0}}),contains:c(function(a){return a=a.replace(ta,ua),function(b){return(b.textContent||b.innerText||w(b)).indexOf(a)>-1}}),lang:c(function(b){return la.test(b||"")||a.error("unsupported lang: "+b),b=b.replace(ta,ua).toLowerCase(),function(a){var c;do if(c=H?a.lang:a.getAttribute("xml:lang")||a.getAttribute("lang"))return c=c.toLowerCase(),c===b||0===c.indexOf(b+"-");while((a=a.parentNode)&&1===a.nodeType);return!1}}),target:function(a){var b=window.location&&window.location.hash;return b&&b.slice(1)===a.id},root:function(a){return a===G},focus:function(a){return a===F.activeElement&&(!F.hasFocus||F.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerC
ase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!v.pseudos.empty(a)},header:function(a){return oa.test(a.nodeName)},input:function(a){return na.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:i(function(){return[0]}),last:i(function(a,b){return[b-1]}),eq:i(function(a,b,c){return[c<0?c+b:c]}),even:i(function(a,b){for(var c=0;c<b;c+=2)a.push(c);return a}),odd:i(function(a,b){for(var c=1;c<b;c+=2)a.push(c)
;return a}),lt:i(function(a,b,c){for(var d=c<0?c+b:c;--d>=0;)a.push(d);return a}),gt:i(function(a,b,c){for(var d=c<0?c+b:c;++d<b;)a.push(d);return a})}},v.pseudos.nth=v.pseudos.eq;for(t in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})v.pseudos[t]=g(t);for(t in{submit:!0,reset:!0})v.pseudos[t]=h(t);return k.prototype=v.filters=v.pseudos,v.setFilters=new k,y=a.tokenize=function(b,c){var d,e,f,g,h,i,j,k=R[b+" "];if(k)return c?0:k.slice(0);for(h=b,i=[],j=v.preFilter;h;){d&&!(e=ha.exec(h))||(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),d=!1,(e=ia.exec(h))&&(d=e.shift(),f.push({value:d,type:e[0].replace(ga," ")}),h=h.slice(d.length));for(g in v.filter)!(e=ma[g].exec(h))||j[g]&&!(e=j[g](e))||(d=e.shift(),f.push({value:d,type:g,matches:e}),h=h.slice(d.length));if(!d)break}return c?h.length:h?a.error(b):R(b,i).slice(0)},z=a.compile=function(a,b){var c,d=[],e=[],f=S[a+" "];if(!f){for(b||(b=y(a)),c=b.length;c--;)f=
r(b[c]),f[M]?d.push(f):e.push(f);f=S(a,s(e,d)),f.selector=a}return f},A=a.select=function(a,b,c,d){var e,f,g,h,i,k="function"==typeof a&&a,m=!d&&y(a=k.selector||a);if(c=c||[],1===m.length){if(f=m[0]=m[0].slice(0),f.length>2&&"ID"===(g=f[0]).type&&u.getById&&9===b.nodeType&&H&&v.relative[f[1].type]){if(b=(v.find.ID(g.matches[0].replace(ta,ua),b)||[])[0],!b)return c;k&&(b=b.parentNode),a=a.slice(f.shift().value.length)}for(e=ma.needsContext.test(a)?0:f.length;e--&&(g=f[e],!v.relative[h=g.type]);)if((i=v.find[h])&&(d=i(g.matches[0].replace(ta,ua),ra.test(f[0].type)&&j(b.parentNode)||b))){if(f.splice(e,1),a=d.length&&l(f),!a)return $.apply(c,d),c;break}}return(k||z(a,m))(d,b,!H,c,ra.test(a)&&j(b.parentNode)||b),c},u.sortStable=M.split("").sort(T).join("")===M,u.detectDuplicates=!!D,E(),u.sortDetached=d(function(a){return 1&a.compareDocume
ntPosition(F.createElement("div"))}),d(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||e("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),u.attributes&&d(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||e("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),d(function(a){return null==a.getAttribute("disabled")})||e(ba,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),a}),g("1g",[],function(){function a(a){var b,c,d=a;if(!j(a))for(d=[],b=0,c=a.length;b<c;b++)d[b]=a[b];return d}function b(a,b,c){var d,e;if(!a)return 0;if(c=
c||a,void 0!==a.length){for(d=0,e=a.length;d<e;d++)if(b.call(c,a[d],d,a)===!1)return 0}else for(d in a)if(a.hasOwnProperty(d)&&b.call(c,a[d],d,a)===!1)return 0;return 1}function c(a,c){var d=[];return b(a,function(b,e){d.push(c(b,e,a))}),d}function d(a,c){var d=[];return b(a,function(b,e){c&&!c(b,e,a)||d.push(b)}),d}function e(a,b){var c,d;if(a)for(c=0,d=a.length;c<d;c++)if(a[c]===b)return c;return-1}function f(a,b,c,d){var e=0;for(arguments.length<3&&(c=a[0]);e<a.length;e++)c=b.call(d,c,a[e],e);return c}function g(a,b,c){var d,e;for(d=0,e=a.length;d<e;d++)if(b.call(c,a[d],d,a))return d;return-1}function h(a,b,c){var d=g(a,b,c);if(d!==-1)return a[d]}function i(a){return a[a.length-1]}var j=Array.isArray||function(a){return"[object Array]"===Object.prototype.toString.call(a)};return{isArray:j,toArray:a,each:b,map:c,filter:d,indexOf:e,reduce:f,findIndex:g,find:h,last:i}}),g("9",["6","1g"],function(a,b){func
tion c(a){return null===a||void 0===a?"":(""+a).replace(n,"")}function d(a,c){return c?!("array"!=c||!b.isArray(a))||typeof a==c:void 0!==a}function e(a,b,c){var d;for(a=a||[],b=b||",","string"==typeof a&&(a=a.split(b)),c=c||{},d=a.length;d--;)c[a[d]]={};return c}function f(a,b){return Object.prototype.hasOwnProperty.call(a,b)}function g(a,b,c){var d,e,f,g,h,i=this,j=0;if(a=/^((static) )?([\w.]+)(:([\w.]+))?/.exec(a),f=a[3].match(/(^|\.)(\w+)$/i)[2],e=i.createNS(a[3].replace(/\.\w+$/,""),c),!e[f]){if("static"==a[2])return e[f]=b,void(this.onCreate&&this.onCreate(a[2],a[3],e[f]));b[f]||(b[f]=function(){},j=1),e[f]=b[f],i.extend(e[f].prototype,b),a[5]&&(d=i.resolve(a[5]).prototype,g=a[5].match(/\.(\w+)$/i)[1],h=e[f],j?e[f]=function(){return d[g].apply(this,arguments)}:e[f]=function(){return this.parent=d[g],h.apply(this,arguments)},e[f].prototype[f]=e[f],i.each(d,function(a,b){e[f].
prototype[b]=d[b]}),i.each(b,function(a,b){d[b]?e[f].prototype[b]=function(){return this.parent=d[b],a.apply(this,arguments)}:b!=f&&(e[f].prototype[b]=a)})),i.each(b["static"],function(a,b){e[f][b]=a})}}function h(a,b){var c,d,e,f,g=arguments;for(c=1,d=g.length;c<d;c++){b=g[c];for(e in b)b.hasOwnProperty(e)&&(f=b[e],void 0!==f&&(a[e]=f))}return a}function i(a,c,d,e){e=e||this,a&&(d&&(a=a[d]),b.each(a,function(a,b){return c.call(e,a,b,d)!==!1&&void i(a,c,d,e)}))}function j(a,b){var c,d;for(b=b||window,a=a.split("."),c=0;c<a.length;c++)d=a[c],b[d]||(b[d]={}),b=b[d];return b}function k(a,b){var c,d;for(b=b||window,a=a.split("."),c=0,d=a.length;c<d&&(b=b[a[c]],b);c++);return b}function l(a,e){return!a||d(a,"array")?a:b.map(a.split(e||","),c)}function m(b){var c=a.cacheSuffix;return c&&(b+=(b.indexOf("?")===-1?"?":"&")+c),b}var n=/^\
s*|\s*$/g;return{trim:c,isArray:b.isArray,is:d,toArray:b.toArray,makeMap:e,each:b.each,map:b.map,
+grep:b.filter,inArray:b.indexOf,hasOwn:f,extend:h,create:g,walk:i,createNS:j,resolve:k,explode:l,_addCacheSuffix:m}}),g("a",["7","8","9","6"],function(a,b,c,d){function e(a){return"undefined"!=typeof a}function f(a){return"string"==typeof a}function g(a){return a&&a==a.window}function h(a,b){var c,d,e;for(b=b||w,e=b.createElement("div"),c=b.createDocumentFragment(),e.innerHTML=a;d=e.firstChild;)c.appendChild(d);return c}function i(a,b,c,d){var e;if(f(b))b=h(b,q(a[0]));else if(b.length&&!b.nodeType){if(b=l.makeArray(b),d)for(e=b.length-1;e>=0;e--)i(a,b[e],c,d);else for(e=0;e<b.length;e++)i(a,b[e],c,d);return a}if(b.nodeType)for(e=a.length;e--;)c.call(a[e],b);return a}function j(a,b){return a&&b&&(" "+a.className+" ").indexOf(" "+b+" ")!==-1}function k(a,b,c){var d,e;return b=l(b)[0],a.each(function(){var a=this;c&&d==a.p
arentNode?e.appendChild(a):(d=a.parentNode,e=b.cloneNode(!1),a.parentNode.insertBefore(e,a),e.appendChild(a))}),a}function l(a,b){return new l.fn.init(a,b)}function m(a,b){var c;if(b.indexOf)return b.indexOf(a);for(c=b.length;c--;)if(b[c]===a)return c;return-1}function n(a){return null===a||a===v?"":(""+a).replace(I,"")}function o(a,b){var c,d,e,f,g;if(a)if(c=a.length,c===f){for(d in a)if(a.hasOwnProperty(d)&&(g=a[d],b.call(g,d,g)===!1))break}else for(e=0;e<c&&(g=a[e],b.call(g,e,g)!==!1);e++);return a}function p(a,b){var c=[];return o(a,function(a,d){b(d,a)&&c.push(d)}),c}function q(a){return a?9==a.nodeType?a:a.ownerDocument:w}function r(a,b,c){var d=[],e=a[b];for("string"!=typeof c&&c instanceof l&&(c=c[0]);e&&9!==e.nodeType;){if(void 0!==c){if(e===c)break;if("string"==typeof c&&l(e).is(c))break}1===e.nodeType&&d.push(e),e=e[b]}return d}function s(a,b,c,d){var e=[];
for(d instanceof l&&(d=d[0]);a;a=a[b])if(!c||a.nodeType===c){if(void 0!==d){if(a===d)break;if("string"==typeof d&&l(a).is(d))break}e.push(a)}return e}function t(a,b,c){for(a=a[b];a;a=a[b])if(a.nodeType==c)return a;return null}function u(a,b,c){o(c,function(c,d){a[c]=a[c]||{},a[c][b]=d})}var v,w=document,x=Array.prototype.push,y=Array.prototype.slice,z=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,A=a.Event,B=c.makeMap("children,contents,next,prev"),C=c.makeMap("fillOpacity fontWeight lineHeight opacity orphans widows zIndex zoom"," "),D=c.makeMap("checked compact declare defer disabled ismap multiple nohref noshade nowrap readonly selected"," "),E={"for":"htmlFor","class":"className",readonly:"readOnly"},F={"float":"cssFloat"},G={},H={},I=/^\s*|\s*$/g;return l.fn=l.prototype={constructor:l,selector:"",context:null,length
:0,init:function(a,b){var c,d,e=this;if(!a)return e;if(a.nodeType)return e.context=e[0]=a,e.length=1,e;if(b&&b.nodeType)e.context=b;else{if(b)return l(a).attr(b);e.context=b=document}if(f(a)){if(e.selector=a,c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c)return l(b).find(a);if(c[1])for(d=h(a,q(b)).firstChild;d;)x.call(e,d),d=d.nextSibling;else{if(d=q(b).getElementById(c[2]),!d)return e;if(d.id!==c[2])return e.find(a);e.length=1,e[0]=d}}else this.add(a,!1);return e},toArray:function(){return c.toArray(this)},add:function(a,b){var c,d,e=this;if(f(a))return e.add(l(a));if(b!==!1)for(c=l.unique(e.toArray().concat(l.makeArray(a))),e.length=c.length,d=0;d<c.length;d++)e[d]=c[d];else x.apply(e,l.makeArray(a));return e},attr:function(a,b){var c,d=this;if("object"==typeof a)o(a,function(a,b){d.attr(a,b)});else{if(!e(b)){if(d[0]&&1===d[0].nodeType){if(c=G[a],c&&c.get)retu
rn c.get(d[0],a);if(D[a])return d.prop(a)?a:v;b=d[0].getAttribute(a,2),null===b&&(b=v)}return b}this.each(function(){var c;if(1===this.nodeType){if(c=G[a],c&&c.set)return void c.set(this,b);null===b?this.removeAttribute(a,2):this.setAttribute(a,b,2)}})}return d},removeAttr:function(a){return this.attr(a,null)},prop:function(a,b){var c=this;if(a=E[a]||a,"object"==typeof a)o(a,function(a,b){c.prop(a,b)});else{if(!e(b))return c[0]&&c[0].nodeType&&a in c[0]?c[0][a]:b;this.each(function(){1==this.nodeType&&(this[a]=b)})}return c},css:function(a,b){function c(a){return a.replace(/-(\D)/g,function(a,b){return b.toUpperCase()})}function d(a){return a.replace(/[A-Z]/g,function(a){return"-"+a})}var f,g,h=this;if("object"==typeof a)o(a,function(a,b){h.css(a,b)});else if(e(b))a=c(a),"number"!=typeof b||C[a]||(b+="px"),h.each(function(){var c=this.style;if(g=H[a],g&&g.set)return void g.set(this,b);t
ry{this.style[F[a]||a]=b}catch(a){}null!==b&&""!==b||(c.removeProperty?c.removeProperty(d(a)):c.removeAttribute(a))});else{if(f=h[0],g=H[a],g&&g.get)return g.get(f);if(f.ownerDocument.defaultView)try{return f.ownerDocument.defaultView.getComputedStyle(f,null).getPropertyValue(d(a))}catch(a){return v}else if(f.currentStyle)return f.currentStyle[c(a)]}return h},remove:function(){for(var a,b=this,c=this.length;c--;)a=b[c],A.clean(a),a.parentNode&&a.parentNode.removeChild(a);return this},empty:function(){for(var a,b=this,c=this.length;c--;)for(a=b[c];a.firstChild;)a.removeChild(a.firstChild);return this},html:function(a){var b,c=this;if(e(a)){b=c.length;try{for(;b--;)c[b].innerHTML=a}catch(d){l(c[b]).empty().append(a)}return c}return c[0]?c[0].innerHTML:""},text:function(a){var b,c=this;if(e(a)){for(b=c.length;b--;)"innerText"in c[b]?c[b].innerText=a:c[0].textContent=a;return c}return c[0]?c[0].innerText||c[0].textContent:""
;},append:function(){return i(this,arguments,function(a){(1===this.nodeType||this.host&&1===this.host.nodeType)&&this.appendChild(a)})},prepend:function(){return i(this,arguments,function(a){(1===this.nodeType||this.host&&1===this.host.nodeType)&&this.insertBefore(a,this.firstChild)},!0)},before:function(){var a=this;return a[0]&&a[0].parentNode?i(a,arguments,function(a){this.parentNode.insertBefore(a,this)}):a},after:function(){var a=this;return a[0]&&a[0].parentNode?i(a,arguments,function(a){this.parentNode.insertBefore(a,this.nextSibling)},!0):a},appendTo:function(a){return l(a).append(this),this},prependTo:function(a){return l(a).prepend(this),this},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){return k(this,a)},wrapAll:function(a){return k(this,a,!0)},wrapInner:function(a){return this.each(function(){l(this).contents().wrapAll(a)}),this},unwrap:function(){return this.parent().each(function(){l(this).repl
aceWith(this.childNodes)})},clone:function(){var a=[];return this.each(function(){a.push(this.cloneNode(!0))}),l(a)},addClass:function(a){return this.toggleClass(a,!0)},removeClass:function(a){return this.toggleClass(a,!1)},toggleClass:function(a,b){var c=this;return"string"!=typeof a?c:(a.indexOf(" ")!==-1?o(a.split(" "),function(){c.toggleClass(this,b)}):c.each(function(c,d){var e,f;f=j(d,a),f!==b&&(e=d.className,f?d.className=n((" "+e+" ").replace(" "+a+" "," ")):d.className+=e?" "+a:a)}),c)},hasClass:function(a){return j(this[0],a)},each:function(a){return o(this,a)},on:function(a,b){return this.each(function(){A.bind(this,a,b)})},off:function(a,b){return this.each(function(){A.unbind(this,a,b)})},trigger:function(a){return this.each(function(){"object"==typeof a?A.fire(this,a.type,a):A.fire(this,a)})},show:function(){return this.css("display","")},hide
:function(){return this.css("display","none")},slice:function(){return new l(y.apply(this,arguments))},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},find:function(a){var b,c,d=[];for(b=0,c=this.length;b<c;b++)l.find(a,this[b],d);return l(d)},filter:function(a){return l("function"==typeof a?p(this.toArray(),function(b,c){return a(c,b)}):l.filter(a,this.toArray()))},closest:function(a){var b=[];return a instanceof l&&(a=a[0]),this.each(function(c,d){for(;d;){if("string"==typeof a&&l(d).is(a)){b.push(d);break}if(d==a){b.push(d);break}d=d.parentNode}}),l(b)},offset:function(a){var b,c,d,e,f=0,g=0;return a?this.css(a):(b=this[0],b&&(c=b.ownerDocument,d=c.documentElement,b.getBoundingClientRect&&(e=b.getBoundingClientRect(),f=e.left+(d.scrollLeft||c.body.scrollLeft)-d.clientLeft,g=e.top+(d.scrollTop||c.body.scrollTop)-d.clientT
op)),{left:f,top:g})},push:x,sort:[].sort,splice:[].splice},c.extend(l,{extend:c.extend,makeArray:function(a){return g(a)||a.nodeType?[a]:c.toArray(a)},inArray:m,isArray:c.isArray,each:o,trim:n,grep:p,find:b,expr:b.selectors,unique:b.uniqueSort,text:b.getText,contains:b.contains,filter:function(a,b,c){var d=b.length;for(c&&(a=":not("+a+")");d--;)1!=b[d].nodeType&&b.splice(d,1);return b=1===b.length?l.find.matchesSelector(b[0],a)?[b[0]]:[]:l.find.matches(a,b)}}),o({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return r(a,"parentNode")},next:function(a){return t(a,"nextSibling",1)},prev:function(a){return t(a,"previousSibling",1)},children:function(a){return s(a.firstChild,"nextSibling",1)},contents:function(a){return c.toArray(("iframe"===a.nodeName?a.contentDocument||a.contentWindow.document:a).childNodes)}},function(a,b){l.fn[a]=function(c){var
d=this,e=[];return d.each(function(){var a=b.call(e,this,c,e);a&&(l.isArray(a)?e.push.apply(e,a):e.push(a))}),this.length>1&&(B[a]||(e=l.unique(e)),0===a.indexOf("parents")&&(e=e.reverse())),e=l(e),c?e.filter(c):e}}),o({parentsUntil:function(a,b){return r(a,"parentNode",b)},nextUntil:function(a,b){return s(a,"nextSibling",1,b).slice(1)},prevUntil:function(a,b){return s(a,"previousSibling",1,b).slice(1)}},function(a,b){l.fn[a]=function(c,d){var e=this,f=[];return e.each(function(){var a=b.call(f,this,c,f);a&&(l.isArray(a)?f.push.apply(f,a):f.push(a))}),this.length>1&&(f=l.unique(f),0!==a.indexOf("parents")&&"prevUntil"!==a||(f=f.reverse())),f=l(f),d?f.filter(d):f}}),l.fn.is=function(a){return!!a&&this.filter(a).length>0},l.fn.init.prototype=l.fn,l.overrideDefaults=function(a){function b(d,e){return c=c||a(),0===arguments.length&&(d=c.element),e||(e=c.c
ontext),new b.fn.init(d,e)}var c;return l.extend(b,this),b},d.ie&&d.ie<8&&(u(G,"get",{maxlength:function(a){var b=a.maxLength;return 2147483647===b?v:b},size:function(a){var b=a.size;return 20===b?v:b},"class":function(a){return a.className},style:function(a){var b=a.style.cssText;return 0===b.length?v:b}}),u(G,"set",{"class":function(a,b){a.className=b},style:function(a,b){a.style.cssText=b}})),d.ie&&d.ie<9&&(F["float"]="styleFloat",u(H,"set",{opacity:function(a,b){var c=a.style;null===b||""===b?c.removeAttribute("filter"):(c.zoom=1,c.filter="alpha(opacity="+100*b+")")}})),l.attrHooks=G,l.cssHooks=H,l}),g("b",[],function(){return function(a,b){function c(a,b,c,d){function e(a){return a=parseInt(a,10).toString(16),a.length>1?a:"0"+a}return"#"+e(b)+e(c)+e(d)}var d,e,f,g,h=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+
)\s*,\s*([0-9]+)\s*\)/gi,i=/(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,j=/\s*([^:]+):\s*([^;]+);?/g,k=/\s+$/,l={},m="\ufeff";for(a=a||{},b&&(f=b.getValidStyles(),g=b.getInvalidStyles()),e=("\\\" \\' \\; \\: ; : "+m).split(" "),d=0;d<e.length;d++)l[e[d]]=m+d,l[m+d]=e[d];return{toHex:function(a){return a.replace(h,c)},parse:function(b){function e(a,b,c){var e,f,g,h;if(e=w[a+"-top"+b],e&&(f=w[a+"-right"+b],f&&(g=w[a+"-bottom"+b],g&&(h=w[a+"-left"+b])))){var i=[e,f,g,h];for(d=i.length-1;d--&&i[d]===i[d+1];);d>-1&&c||(w[a+b]=d==-1?i[0]:i.join(" "),delete w[a+"-top"+b],delete w[a+"-right"+b],delete w[a+"-bottom"+b],delete w[a+"-left"+b])}}function f(a){var b,c=w[a];if(c){for(c=c.split(" "),b=
c.length;b--;)if(c[b]!==c[0])return!1;return w[a]=c[0],!0}}function g(a,b,c,d){f(b)&&f(c)&&f(d)&&(w[a]=w[b]+" "+w[c]+" "+w[d],delete w[b],delete w[c],delete w[d])}function n(a){return v=!0,l[a]}function o(a,b){return v&&(a=a.replace(/\uFEFF[0-9]/g,function(a){return l[a]})),b||(a=a.replace(/\\([\'\";:])/g,"$1")),a}function p(a){return String.fromCharCode(parseInt(a.slice(1),16))}function q(a){return a.replace(/\\[0-9a-f]+/gi,p)}function r(b,c,d,e,f,g){if(f=f||g)return f=o(f),"'"+f.replace(/\'/g,"\\'")+"'";if(c=o(c||d||e),!a.allow_script_urls){var h=c.replace(/[\s\r\n]+/g,"");if(/(java|vb)script:/i.test(h))return"";if(!a.allow_svg_data_urls&&/^data:image\/svg/i.test(h))return""}return x&&(c=x.call(y,c,"style")),"url('"+c.replace(/\'/g,"\\'")+"')"}var s,t,u,v,w={},x=a.url_converter,y=a.url_converter_scope
||this;if(b){for(b=b.replace(/[\u0000-\u001F]/g,""),b=b.replace(/\\[\"\';:\uFEFF]/g,n).replace(/\"[^\"]+\"|\'[^\']+\'/g,function(a){return a.replace(/[;:]/g,n)});s=j.exec(b);)if(j.lastIndex=s.index+s[0].length,t=s[1].replace(k,"").toLowerCase(),u=s[2].replace(k,""),t&&u){if(t=q(t),u=q(u),t.indexOf(m)!==-1||t.indexOf('"')!==-1)continue;if(!a.allow_script_urls&&("behavior"==t||/expression\s*\(|\/\*|\*\//.test(u)))continue;"font-weight"===t&&"700"===u?u="bold":"color"!==t&&"background-color"!==t||(u=u.toLowerCase()),u=u.replace(h,c),u=u.replace(i,r),w[t]=v?o(u,!0):u}e("border","",!0),e("border","-width"),e("border","-color"),e("border","-style"),e("padding",""),e("margin",""),g("border","border-width",&q
uot;border-style","border-color"),"medium none"===w.border&&delete w.border,"none"===w["border-image"]&&delete w["border-image"]}return w},serialize:function(a,b){function c(b){var c,d,e,g;if(c=f[b])for(d=0,e=c.length;d<e;d++)b=c[d],g=a[b],g&&(i+=(i.length>0?" ":"")+b+": "+g+";")}function d(a,b){var c;return c=g["*"],(!c||!c[a])&&(c=g[b],!c||!c[a])}var e,h,i="";if(b&&f)c("*"),c(b);else for(e in a)h=a[e],!h||g&&!d(e,b)||(i+=(i.length>0?" ":"")+e+": "+h+";");return i}}}}),g("c",[],function(){return function(a,b){function c(a,c,d,e){var f,g;if(a){if(!e&&a[c])return a[c];if(a!=b){if(f=a[d])return f;for(g=a.parentNode;g&&g!=b;g=g.parentNode)if(f=g[d])return f}}}function d(a,c,d,e){var f,g,h;if(a){if(f=a[d],b&&f===b)return;if(f){if(!e)fo
r(h=f[c];h;h=h[c])if(!h[c])return h;return f}if(g=a.parentNode,g&&g!==b)return g}}var e=a;this.current=function(){return e},this.next=function(a){return e=c(e,"firstChild","nextSibling",a)},this.prev=function(a){return e=c(e,"lastChild","previousSibling",a)},this.prev2=function(a){return e=d(e,"lastChild","previousSibling",a)}}}),g("d",["9"],function(a){function b(a){var b;return b=document.createElement("div"),b.innerHTML=a,b.textContent||b.innerText||a}function c(a,b){var c,d,f,g={};if(a){for(a=a.split(","),b=b||10,c=0;c<a.length;c+=2)d=String.fromCharCode(parseInt(a[c],b)),e[d]||(f="&"+a[c+1]+";",g[d]=f,g[f]=d);return g}}var d,e,f,g=a.makeMap,h=/[&<>\"\u0060\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,i=/[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,j=/[<>&\"\']/g,k=/&#
([a-z0-9]+);?|&([a-z0-9]+);/gi,l={128:"\u20ac",130:"\u201a",131:"\u0192",132:"\u201e",133:"\u2026",134:"\u2020",135:"\u2021",136:"\u02c6",137:"\u2030",138:"\u0160",139:"\u2039",140:"\u0152",142:"\u017d",145:"\u2018",146:"\u2019",147:"\u201c",148:"\u201d",149:"\u2022",150:"\u2013",151:"\u2014",152:"\u02dc",153:"\u2122",154:"\u0161",155:"\u203a",156:"\u0153",158:"\u017e",159:"\u0178"};e={'"':""","'":"'","<":"<",">":">","&":"&","`":"`"},f={"<":"<",">":">","&":"&&
quot;,""":'"',"'":"'"},d=c("50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,sj,Gamma,sk,Delta,s
l,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,t9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,rfloor,8p9,lang
,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro",32);var m={encodeRaw:function(a,b){return a.replace(b?h:i,function(a){return e[a]||a})},encodeAllRaw:function(a){return(""+a).replace(j,function(a){return e[a]||a})},encodeNumeric:function(a,b){return a.replace(b?h:i,function(a){return a.length>1?"&#"+(1024*(a.charCodeAt(0)-55296)+(a.charCodeAt(1)-56320)+65536)+";":e[a]||"&#"+a.charCodeAt(0)+";"})},encodeNamed:function(a,b,c){return c=c||d,a.replace(b?h:i,function(a){return e[a]||c[a]||a})},getEncodeFunc:function(a,b){function f(a,c){return a.replace(c?h:i,function(a){return e[a]||b[a]||"&#"+a.charCodeAt(0)+";"||a})}func
tion j(a,c){return m.encodeNamed(a,c,b)}return b=c(b)||d,a=g(a.replace(/\+/g,",")),a.named&&a.numeric?f:a.named?b?j:m.encodeNamed:a.numeric?m.encodeNumeric:m.encodeRaw},decode:function(a){return a.replace(k,function(a,c){return c?(c="x"===c.charAt(0).toLowerCase()?parseInt(c.substr(1),16):parseInt(c,10),c>65535?(c-=65536,String.fromCharCode(55296+(c>>10),56320+(1023&c))):l[c]||String.fromCharCode(c)):f[a]||d[a]||b(a)})}};return m}),g("1h",["9"],function(a){function b(c){function d(){return J.createDocumentFragment()}function e(a,b){x(N,a,b)}function f(a,b){x(O,a,b)}function g(a){e(a.parentNode,U(a))}function h(a){e(a.parentNode,U(a)+1)}function i(a){f(a.parentNode,U(a))}function j(a){f(a.parentNode,U(a)+1)}function k(a){a?(I[R]=I[Q],I[S]=I[P]):(I[Q]=I[R],I[P]=I[S]),I.collapsed=N}function l(a){g(a),j(a)}function m(a){e(a,0),f(a,1===a.nodeType?a.childNodes.length:a.nodeValue.length)}function n(a,b){var c=I[Q],d=I[P],e=I[R],f
=I[S],g=b.startContainer,h=b.startOffset,i=b.endContainer,j=b.endOffset;return 0===a?w(c,d,g,h):1===a?w(e,f,g,h):2===a?w(e,f,i,j):3===a?w(c,d,i,j):void 0}function o(){y(M)}function p(){return y(K)}function q(){return y(L)}function r(a){var b,d,e=this[Q],f=this[P];3!==e.nodeType&&4!==e.nodeType||!e.nodeValue?(e.childNodes.length>0&&(d=e.childNodes[f]),d?e.insertBefore(a,d):3==e.nodeType?c.insertAfter(a,e):e.appendChild(a)):f?f>=e.nodeValue.length?c.insertAfter(a,e):(b=e.splitText(f),e.parentNode.insertBefore(a,b)):e.parentNode.insertBefore(a,e)}function s(a){var b=I.extractContents();I.insertNode(a),a.appendChild(b),I.selectNode(a)}function t(){return T(new b(c),{startContainer:I[Q],startOffset:I[P],endContainer:I[R],endOffset:I[S],collapsed:I.collapsed,commonAncestorContainer:I.commonAncestorContainer})}function u(a,b){var c;if(3==a.nodeType)return a;if(b<0)return a;for(c=a.firstChild;c&&b>0;)--b,c=c.nextSibling;return c?c:a}function v(){return I[
Q]==I[R]&&I[P]==I[S]}function w(a,b,d,e){var f,g,h,i,j,k;if(a==d)return b==e?0:b<e?-1:1;for(f=d;f&&f.parentNode!=a;)f=f.parentNode;if(f){for(g=0,h=a.firstChild;h!=f&&g<b;)g++,h=h.nextSibling;return b<=g?-1:1}for(f=a;f&&f.parentNode!=d;)f=f.parentNode;if(f){for(g=0,h=d.firstChild;h!=f&&g<e;)g++,h=h.nextSibling;return g<e?-1:1}for(i=c.findCommonAncestor(a,d),j=a;j&&j.parentNode!=i;)j=j.parentNode;for(j||(j=i),k=d;k&&k.parentNode!=i;)k=k.parentNode;if(k||(k=i),j==k)return 0;for(h=i.firstChild;h;){if(h==j)return-1;if(h==k)return 1;h=h.nextSibling}}function x(a,b,d){var e,f;for(a?(I[Q]=b,I[P]=d):(I[R]=b,I[S]=d),e=I[R];e.parentNode;)e=e.parentNode;for(f=I[Q];f.parentNode;)f=f.parentNode;f==e?w(I[Q],I[P],I[R],I[S])>0&&I.collapse(a):I.collapse(a),I.collapsed=v(),I.commonAncestorContainer=c.findCommonAncestor(I[Q],I[R])}function y(a){var b,c,d,e,f,g,h,i=0,j=0;if(I[Q]==I[R])return z(a);for(b=I[R],c=b.parentNode;
c;b=c,c=c.parentNode){if(c==I[Q])return A(b,a);++i}for(b=I[Q],c=b.parentNode;c;b=c,c=c.parentNode){if(c==I[R])return B(b,a);++j}for(d=j-i,e=I[Q];d>0;)e=e.parentNode,d--;for(f=I[R];d<0;)f=f.parentNode,d++;for(g=e.parentNode,h=f.parentNode;g!=h;g=g.parentNode,h=h.parentNode)e=g,f=h;return C(e,f,a)}function z(a){var b,c,e,f,g,h,i,j,k;if(a!=M&&(b=d()),I[P]==I[S])return b;if(3==I[Q].nodeType){if(c=I[Q].nodeValue,e=c.substring(I[P],I[S]),a!=L&&(f=I[Q],j=I[P],k=I[S]-I[P],0===j&&k>=f.nodeValue.length-1?f.parentNode.removeChild(f):f.deleteData(j,k),I.collapse(N)),a==M)return;return e.length>0&&b.appendChild(J.createTextNode(e)),b}for(f=u(I[Q],I[P]),g=I[S]-I[P];f&&g>0;)h=f.nextSibling,i=G(f,a),b&&b.appendChild(i),--g,f=h;return a!=L&&I.collapse(N),b}function A(a,b){var c,e,f,g,h,i;if(b!=M&&(c=d()),e=D(a,b),c&&c.appendChild(e),f=U(a),g=f-I[P],g<=0)return b!=L&&(I.setEndBefore(a),I.collapse(O)),c;f
or(e=a.previousSibling;g>0;)h=e.previousSibling,i=G(e,b),c&&c.insertBefore(i,c.firstChild),--g,e=h;return b!=L&&(I.setEndBefore(a),I.collapse(O)),c}function B(a,b){var c,e,f,g,h,i;for(b!=M&&(c=d()),f=E(a,b),c&&c.appendChild(f),e=U(a),++e,g=I[S]-e,f=a.nextSibling;f&&g>0;)h=f.nextSibling,i=G(f,b),c&&c.appendChild(i),--g,f=h;return b!=L&&(I.setStartAfter(a),I.collapse(N)),c}function C(a,b,c){var e,f,g,h,i,j,k;for(c!=M&&(f=d()),e=E(a,c),f&&f.appendChild(e),g=U(a),h=U(b),++g,i=h-g,j=a.nextSibling;i>0;)k=j.nextSibling,e=G(j,c),f&&f.appendChild(e),j=k,--i;return e=D(b,c),f&&f.appendChild(e),c!=L&&(I.setStartAfter(a),I.collapse(N)),f}function D(a,b){var c,d,e,f,g,h=u(I[R],I[S]-1),i=h!=I[R];if(h==a)return F(h,i,O,b);for(c=h.parentNode,d=F(c,O,O,b);c;){for(;h;)e=h.previousSibling,f=F(h,i,O,b),b!=M&&d.insertBefore(f,d.firstChild),i=N,h=e;if(c==a)return d;h=c.previousSibling,c=c.pare
ntNode,g=F(c,O,O,b),b!=M&&g.appendChild(d),d=g}}function E(a,b){var c,d,e,f,g,h=u(I[Q],I[P]),i=h!=I[Q];if(h==a)return F(h,i,N,b);for(c=h.parentNode,d=F(c,O,N,b);c;){for(;h;)e=h.nextSibling,f=F(h,i,N,b),b!=M&&d.appendChild(f),i=N,h=e;if(c==a)return d;h=c.nextSibling,c=c.parentNode,g=F(c,O,N,b),b!=M&&g.appendChild(d),d=g}}function F(a,b,d,e){var f,g,h,i,j;if(b)return G(a,e);if(3==a.nodeType){if(f=a.nodeValue,d?(i=I[P],g=f.substring(i),h=f.substring(0,i)):(i=I[S],g=f.substring(0,i),h=f.substring(i)),e!=L&&(a.nodeValue=h),e==M)return;return j=c.clone(a,O),j.nodeValue=g,j}if(e!=M)return c.clone(a,O)}function G(a,b){return b!=M?b==L?c.clone(a,N):a:void a.parentNode.removeChild(a)}function H(){return c.create("body",null,q()).outerText}var I=this,J=c.doc,K=0,L=1,M=2,N=!0,O=!1,P="startOffset",Q="startContainer",R="endContainer",S="endOffset",T=a.extend,U=c.nodeIndex;return T(I,{startContainer:J,startOffset:0,e
ndContainer:J,endOffset:0,collapsed:N,commonAncestorContainer:J,START_TO_START:0,START_TO_END:1,END_TO_END:2,END_TO_START:3,setStart:e,setEnd:f,setStartBefore:g,setStartAfter:h,setEndBefore:i,setEndAfter:j,collapse:k,selectNode:l,selectNodeContents:m,compareBoundaryPoints:n,deleteContents:o,extractContents:p,cloneContents:q,insertNode:r,surroundContents:s,cloneRange:t,toStringIE:H}),I}return b.prototype.toString=function(){return this.toStringIE()},b}),h("4i",Array),h("4j",Error),g("3s",["4i","4j"],function(a,b){var c=function(){},d=function(a,b){return function(){return a(b.apply(null,arguments))}},e=function(a){return function(){return a}},f=function(a){return a},g=function(a,b){return a===b},h=function(b){for(var c=new a(arguments.length-1),d=1;d<arguments.length;d++)c[d-1]=arguments[d];return function(){for(var d=new a(arguments.length),e=0;e<d.length;e++)d[e]=arguments[e];var f=c.concat(d);return b.apply(null,f)}},i=functi
on(a){return function(){return!a.apply(null,arguments)}},j=function(a){return function(){throw new b(a)}},k=function(a){return a()},l=function(a){a()},m=e(!1),n=e(!0);return{noop:c,compose:d,constant:e,identity:f,tripleEquals:g,curry:h,not:i,die:j,apply:k,call:l,never:m,always:n}}),h("55",Object),g("4h",["3s","55"],function(a,b){var c=a.never,d=a.always,e=function(){return f},f=function(){var f=function(a){return a.isNone()},g=function(a){return a()},h=function(a){return a},i=function(){},j={fold:function(a,b){return a()},is:c,isSome:c,isNone:d,getOr:h,getOrThunk:g,getOrDie:function(a){throw new Error(a||"error: getOrDie called on none.")},or:h,orThunk:g,map:e,ap:e,each:i,bind:e,flatten:e,exists:c,forall:d,filter:e,equals:f,equals_:f,toArray:function(){return[]},toString:a.constant("none()")};return b.freeze&&b.freeze(j),j}(),g=function(a){var b=function(){return a},h=function(){return k},i=function(b){return g(b(a)
)},j=function(b){return b(a)},k={fold:function(b,c){return c(a)},is:function(b){return a===b},isSome:d,isNone:c,getOr:b,getOrThunk:b,getOrDie:b,or:h,orThunk:h,map:i,ap:function(b){return b.fold(e,function(b){return g(b(a))})},each:function(b){b(a)},bind:j,flatten:b,exists:j,forall:j,filter:function(b){return b(a)?k:f},equals:function(b){return b.is(a)},equals_:function(b,d){return b.fold(c,function(b){return d(a,b)})},toArray:function(){return[a]},toString:function(){return"some("+a+")"}};return k},h=function(a){return null===a||void 0===a?f:g(a)};return{some:g,none:e,from:h}}),h("4k",String),g("3r",["4h","4i","4j","4k"],function(a,b,c,d){var e=function(){var a=b.prototype.indexOf,c=function(b,c){return a.call(b,c)},d=function(a,b){return u(a,b)};return void 0===a?d:c}(),f=function(b,c){var d=e(b,c);return d===-1?a.none():a.some(d)},g=function(a,b){return e(a,b)>-1},h=function(a,b){return t(a,b).isSom
e()},i=function(a,b){for(var c=[],d=0;d<a;d++)c.push(b(d));return c},j=function(a,b){for(var c=[],d=0;d<a.length;d+=b){var e=a.slice(d,d+b);c.push(e)}return c},k=function(a,c){for(var d=a.length,e=new b(d),f=0;f<d;f++){var g=a[f];e[f]=c(g,f,a)}return e},l=function(a,b){for(var c=0,d=a.length;c<d;c++){var e=a[c];b(e,c,a)}},m=function(a,b){for(var c=a.length-1;c>=0;c--){var d=a[c];b(d,c,a)}},n=function(a,b){for(var c=[],d=[],e=0,f=a.length;e<f;e++){var g=a[e],h=b(g,e,a)?c:d;h.push(g)}return{pass:c,fail:d}},o=function(a,b){for(var c=[],d=0,e=a.length;d<e;d++){var f=a[d];b(f,d,a)&&c.push(f)}return c},p=function(a,b){if(0===a.length)return[];for(var c=b(a[0]),d=[],e=[],f=0,g=a.length;f<g;f++){var h=a[f],i=b(h);i!==c&&(d.push(e),e=[]),c=i,e.push(h)}return 0!==e.length&&d.push(e),d},q=function(a,b,c){return m(a,function(a){c=b(c,a)}),c},r=function(a,b,c){return l(a,function(a){c=b(c,a)}),c},s=function(b,c){for(var d=0,e=b.length;d<e;d++){v
ar f=b[d];if(c(f,d,b))return a.some(f)}return a.none()},t=function(b,c){for(var d=0,e=b.length;d<e;d++){var f=b[d];if(c(f,d,b))return a.some(d)}return a.none()},u=function(a,b){for(var c=0,d=a.length;c<d;++c)if(a[c]===b)return c;return-1},v=b.prototype.push,w=function(a){for(var d=[],e=0,f=a.length;e<f;++e){if(!b.prototype.isPrototypeOf(a[e]))throw new c("Arr.flatten item "+e+" was not an array, input: "+a);v.apply(d,a[e])}return d},x=function(a,b){var c=k(a,b);return w(c)},y=function(a,b){for(var c=0,d=a.length;c<d;++c){var e=a[c];if(b(e,c,a)!==!0)return!1}return!0},z=function(a,b){return a.length===b.length&&y(a,function(a,c){return a===b[c]})},A=b.prototype.slice,B=function(a){var b=A.call(a,0);return b.reverse(),b},C=function(a,b){return o(a,function(a){return!g(b,a)})},D=function(a,b){for(var c={},e=0,f=a.length;e<f;e++){var g=a[e];c[d(g)]=b(g,e)}return c},E=function(a){return[a]},F=function(a,b){var c=A.call(a,0);return c.sort(b),c};r
eturn{map:k,each:l,eachr:m,partition:n,filter:o,groupBy:p,indexOf:f,foldr:q,foldl:r,find:s,findIndex:t,flatten:w,bind:x,forall:y,exists:h,contains:g,equal:z,reverse:B,chunk:j,difference:C,mapToObject:D,pure:E,sort:F,range:i}}),h("56",setTimeout),g("4l",["3r","4h","56"],function(a,b,c){var d=function(e){var f=b.none(),g=[],h=function(a){return d(function(b){i(function(c){b(a(c))})})},i=function(a){k()?m(a):g.push(a)},j=function(a){f=b.some(a),l(g),g=[]},k=function(){return f.isSome()},l=function(b){a.each(b,m)},m=function(a){f.each(function(b){c(function(){a(b)},0)})};return e(j),{get:i,map:h,isReady:k}},e=function(a){return d(function(b){b(a)})};return{nu:d,pure:e}}),g("4m",["4i","56"],function(a,b){var c=function(c){return function(){var d=a.prototype.slice.call(arguments),e=this;b(function(){c.apply(e,d)},0)}};return{bounce:c}}),g("3t",["4l","4m"],function(a,b){var c=funct
ion(d){var e=function(a){d(b.bounce(a))},f=function(a){return c(function(b){e(function(c){var d=a(c);b(d)})})},g=function(a){return c(function(b){e(function(c){a(c).get(b)})})},h=function(a){return c(function(b){e(function(c){a.get(b)})})},i=function(){return a.nu(e)};return{map:f,bind:g,anonBind:h,toLazy:i,get:e}},d=function(a){return c(function(b){b(a)})};return{nu:c,pure:d}}),g("4n",["3r"],function(a){var b=function(b,c){return c(function(c){var d=[],e=0,f=function(a){return function(f){d[a]=f,e++,e>=b.length&&c(d)}};0===b.length?c([]):a.each(b,function(a,b){a.get(f(b))})})};return{par:b}}),g("3u",["3r","3t","4n"],function(a,b,c){var d=function(a){return c.par(a,b.nu)},e=function(b,c){var e=a.map(b,c);return d(e)},f=function(a,b){return function(c){return b(c).bind(a)}};return{par:d,mapM:e,compose:f}}),g("3v",["3s","4h"],function(a,b){var c=function(d){var e=function(a){return d==
=a},f=function(a){return c(d)},g=function(a){return c(d)},h=function(a){return c(a(d))},i=function(a){a(d)},j=function(a){return a(d)},k=function(a,b){return b(d)},l=function(a){return a(d)},m=function(a){return a(d)},n=function(){return b.some(d)};return{is:e,isValue:a.constant(!0),isError:a.constant(!1),getOr:a.constant(d),getOrThunk:a.constant(d),getOrDie:a.constant(d),or:f,orThunk:g,fold:k,map:h,each:i,bind:j,exists:l,forall:m,toOption:n}},d=function(c){var e=function(a){return a()},f=function(){return a.die(c)()},g=function(a){return a},h=function(a){return a()},i=function(a){return d(c)},j=function(a){return d(c)},k=function(a,b){return a(c)};return{is:a.constant(!1),isValue:a.constant(!1),isError:a.constant(!0),getOr:a.identity,getOrThunk:e,getOrDie:f,or:g,orThunk:h,fold:k,map:i,each:a.noop,bind:j,exists:a.constant(!1),forall:a.constant(!0),toOption:b.none}};return{value:c,error:d}}),g("1i",["3r","3s","3t","3u","3v",
"5","9"],function(a,b,c,d,e,f,g){"use strict";return function(h,i){function j(a){h.getElementsByTagName("head")[0].appendChild(a)}function k(a,b,c){function d(){for(var a=t.passed,b=a.length;b--;)a[b]();t.status=2,t.passed=[],t.failed=[]}function e(){for(var a=t.failed,b=a.length;b--;)a[b]();t.status=3,t.passed=[],t.failed=[]}function i(){var a=navigator.userAgent.match(/WebKit\/(\d*)/);return!!(a&&a[1]<536)}function k(a,b){a()||((new Date).getTime()-s<l?f.setTimeout(b):e())}function o(){k(function(){for(var a,b,c=h.styleSheets,e=c.length;e--;)if(a=c[e],b=a.ownerNode?a.ownerNode:a.owningElement,b&&b.id===q.id)return d(),!0},o)}function p(){k(function(){try{var a=r.sheet.cssRules;return d(),!!a}catch(a){}},p)}var q,r,s,t;if(a=g._addCacheSuffix(a),n[a]?t=n[a]:(t={passed:[],failed:[]},n[a]=t),b&&t.passed.push(b),c&&t.failed.push(c),1!=t.status){if(2==t.status)return void d();if(3==t.status)return void e();if(
t.status=1,q=h.createElement("link"),q.rel="stylesheet",q.type="text/css",q.id="u"+m++,q.async=!1,q.defer=!1,s=(new Date).getTime(),"onload"in q&&!i())q.onload=o,q.onerror=e;else{if(navigator.userAgent.indexOf("Firefox")>0)return r=h.createElement("style"),r.textContent='@import "'+a+'"',p(),void j(r);o()}j(q),q.href=a}}var l,m=0,n={};i=i||{},l=i.maxLoadTime||5e3;
+var o=function(a){return c.nu(function(c){k(a,b.compose(c,b.constant(e.value(a))),b.compose(c,b.constant(e.error(a))))})},p=function(a){return a.fold(b.identity,b.identity)},q=function(b,c,e){d.par(a.map(b,o)).get(function(b){var d=a.partition(b,function(a){return a.isValue()});d.fail.length>0?e(d.fail.map(p)):c(d.pass.map(p))})};return{load:k,loadAll:q}}}),g("j",["9"],function(a){function b(b,c){return b=a.trim(b),b?b.split(c||" "):[]}function c(a){function c(a,c,d){function e(a,b){var c,d,e={};for(c=0,d=a.length;c<d;c++)e[a[c]]=b||{};return e}var h,i,j;for(d=d||[],c=c||"","string"==typeof d&&(d=b(d)),a=b(a),h=a.length;h--;)i=b([g,c].join(" ")),j={attributes:e(i),attributesOrder:i,children:e(d,f)},n[a[h]]=j}function d(a,c){var d,e,f,g;for(a=b(a),d=a.length,c=b(c);d--;)for(e=n[a[d]],f=0,g=c.length;f<g;f++)e.attributes[c[f]]={},e.attributesOrder.push(c[f])}var g,i,j,k,l,m,n={};return e[a]?e[a]:(g="id ac
cesskey class dir lang style tabindex title role",i="address blockquote div dl fieldset form h1 h2 h3 h4 h5 h6 hr menu ol p pre table ul",j="a abbr b bdo br button cite code del dfn em embed i iframe img input ins kbd label map noscript object q s samp script select small span strong sub sup textarea u var #text #comment","html4"!=a&&(g+=" contenteditable contextmenu draggable dropzone hidden spellcheck translate",i+=" article aside details dialog figure header footer hgroup section nav",j+=" audio canvas command datalist mark meter output picture progress time wbr video ruby bdi keygen"),"html5-strict"!=a&&(g+=" xml:lang",m="acronym applet basefont big font strike tt",j=[j,m].join(" "),h(b(m),function(a){c(a,"",j)}),l="center dir isindex noframes",i=[i,l].join(" "),k=[i,j].join(" "),h(b(l),function(a){c(a,"",k)}))
,k=k||[i,j].join(" "),c("html","manifest","head body"),c("head","","base command link meta noscript script style title"),c("title hr noscript br"),c("base","href target"),c("link","href rel media hreflang type sizes hreflang"),c("meta","name http-equiv content charset"),c("style","media type scoped"),c("script","src async defer type charset"),c("body","onafterprint onbeforeprint onbeforeunload onblur onerror onfocus onhashchange onload onmessage onoffline ononline onpagehide onpageshow onpopstate onresize onscroll onstorage onunload",k),c("address dt dd div caption","",k),c("h1 h2 h3 h4 h5 h6 pre p abbr code var samp kbd sub sup i b u bdo span legend em strong small s cite dfn","",j),c("blockquote","cite",k),c("ol",&q
uot;reversed start type","li"),c("ul","","li"),c("li","value",k),c("dl","","dt dd"),c("a","href target rel media hreflang type",j),c("q","cite",j),c("ins del","cite datetime",k),c("img","src sizes srcset alt usemap ismap width height"),c("iframe","src name width height",k),c("embed","src type width height"),c("object","data type typemustmatch name usemap form width height",[k,"param"].join(" ")),c("param","name value"),c("map","name",[k,"area"].join(" ")),c("area","alt coords shape href target rel media hreflang type"),c("table","border","caption colgroup thead tfoot tbody tr"+("html4"==a?" col":"&qu
ot;)),c("colgroup","span","col"),c("col","span"),c("tbody thead tfoot","","tr"),c("tr","","td th"),c("td","colspan rowspan headers",k),c("th","colspan rowspan headers scope abbr",k),c("form","accept-charset action autocomplete enctype method name novalidate target",k),c("fieldset","disabled form name",[k,"legend"].join(" ")),c("label","form for",j),c("input","accept alt autocomplete checked dirname disabled form formaction formenctype formmethod formnovalidate formtarget height list max maxlength min multiple name pattern readonly required size src step type value width"),c("button","disabled form formaction formenctype formmethod formnovalidate formtarget name type value","html4"==a?k:j),c("select"
;,"disabled form multiple name required size","option optgroup"),c("optgroup","disabled label","option"),c("option","disabled label selected value"),c("textarea","cols dirname disabled form maxlength name readonly required rows wrap"),c("menu","type label",[k,"li"].join(" ")),c("noscript","",k),"html4"!=a&&(c("wbr"),c("ruby","",[j,"rt rp"].join(" ")),c("figcaption","",k),c("mark rt rp summary bdi","",j),c("canvas","width height",k),c("video","src crossorigin poster preload autoplay mediagroup loop muted controls width height buffered",[k,"track source"].join(" ")),c("audio","src crossorigin preload autoplay mediagroup loop muted controls buffered volume&qu
ot;,[k,"track source"].join(" ")),c("picture","","img source"),c("source","src srcset type media sizes"),c("track","kind src srclang label default"),c("datalist","",[j,"option"].join(" ")),c("article section nav aside header footer","",k),c("hgroup","","h1 h2 h3 h4 h5 h6"),c("figure","",[k,"figcaption"].join(" ")),c("time","datetime",j),c("dialog","open",k),c("command","type label icon disabled checked radiogroup command"),c("output","for form name",j),c("progress","value max",j),c("meter","value min max low high optimum",j),c("details","open",[k,"summary"].join(" ")),c("keygen","autofocus chall
enge disabled form keytype name")),"html5-strict"!=a&&(d("script","language xml:space"),d("style","xml:space"),d("object","declare classid code codebase codetype archive standby align border hspace vspace"),d("embed","align name hspace vspace"),d("param","valuetype type"),d("a","charset name rev shape coords"),d("br","clear"),d("applet","codebase archive code object alt name width height align hspace vspace"),d("img","name longdesc align border hspace vspace"),d("iframe","longdesc frameborder marginwidth marginheight scrolling align"),d("font basefont","size color face"),d("input","usemap align"),d("select","onchange"),d("textarea"),d("h1 h2 h3 h4 h5 h6 div p legend caption","alig
n"),d("ul","type compact"),d("li","type"),d("ol dl menu dir","compact"),d("pre","width xml:space"),d("hr","align noshade size width"),d("isindex","prompt"),d("table","summary width frame rules cellspacing cellpadding align bgcolor"),d("col","width align char charoff valign"),d("colgroup","width align char charoff valign"),d("thead","align char charoff valign"),d("tr","align char charoff valign bgcolor"),d("th","axis align char charoff valign nowrap bgcolor width height"),d("form","accept"),d("td","abbr axis scope align char charoff valign nowrap bgcolor width height"),d("tfoot","align char charoff valign"),d("tbody","align char charoff valign"),d("area",
"nohref"),d("body","background bgcolor text link vlink alink")),"html4"!=a&&(d("input button select textarea","autofocus"),d("input textarea","placeholder"),d("a","download"),d("link script img","crossorigin"),d("iframe","sandbox seamless allowfullscreen")),h(b("a form meter progress dfn"),function(a){n[a]&&delete n[a].children[a]}),delete n.caption.children.table,delete n.script,e[a]=n,n)}function d(a,b){var c;return a&&(c={},"string"==typeof a&&(a={"*":a}),h(a,function(a,d){c[d]=c[d.toUpperCase()]="map"==b?g(a,/[, ]/):j(a,/[, ]/)})),c}var e={},f={},g=a.makeMap,h=a.each,i=a.extend,j=a.explode,k=a.inArray;return function(a){function f(b,c,d){var f=a[b];return f?f=g(f,/[, ]/,g(f.toUpperCase(),/[, ]/)):(f=e[b],f||(f=g(c," ",g(c.toUpperCase()," ")),f=i(f,d),
e[b]=f)),f}function l(a){return new RegExp("^"+a.replace(/([?+*])/g,".$1")+"$")}function m(a){var c,d,e,f,h,i,j,m,n,o,p,q,r,s,t,u,v,w,x,y=/^([#+\-])?([^\[!\/]+)(?:\/([^\[!]+))?(?:(!?)\[([^\]]+)\])?$/,z=/^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/,A=/[*?+]/;if(a)for(a=b(a,","),F["@"]&&(u=F["@"].attributes,v=F["@"].attributesOrder),c=0,d=a.length;c<d;c++)if(h=y.exec(a[c])){if(s=h[1],n=h[2],t=h[3],m=h[5],q={},r=[],i={attributes:q,attributesOrder:r},"#"===s&&(i.paddEmpty=!0),"-"===s&&(i.removeEmpty=!0),"!"===h[4]&&(i.removeEmptyAttrs=!0),u){for(w in u)q[w]=u[w];r.push.apply(r,v)}if(m)for(m=b(m,"|"),e=0,f=m.length;e<f;e++)if(h=z.exec(m[e])){if(j={},p=h[1],o=h[2].replace(/::/g,":"),s=h[3],x=h[4],"!"===p&&(i.attributesRequired=i.attributesRequired||[],i.attributesRequired.push(o),j.required=!0),"-"
===p){delete q[o],r.splice(k(r,o),1);continue}s&&("="===s&&(i.attributesDefault=i.attributesDefault||[],i.attributesDefault.push({name:o,value:x}),j.defaultValue=x),":"===s&&(i.attributesForced=i.attributesForced||[],i.attributesForced.push({name:o,value:x}),j.forcedValue=x),"<"===s&&(j.validValues=g(x,"?"))),A.test(o)?(i.attributePatterns=i.attributePatterns||[],j.pattern=l(o),i.attributePatterns.push(j)):(q[o]||r.push(o),q[o]=j)}u||"@"!=n||(u=q,v=r),t&&(i.outputName=n,F[t]=i),A.test(n)?(i.pattern=l(n),H.push(i)):F[n]=i}}function n(a){F={},H=[],m(a),h(t,function(a,b){G[b]=a.children})}function o(a){var c=/^(~)?(.+)$/;a&&(e.text_block_elements=e.block_elements=null,h(b(a,","),function(a){var b=c.exec(a),d="~"===b[1],e=d?"span":"div",f=b[2];if(G[f]=G[e],I[f]=e,d||(z[f.toUpperCase()]={},z[f]={}),!F[f]){var g=F[e];g=i({},g),delete g.removeEmptyAtt
rs,delete g.removeEmpty,F[f]=g}h(G,function(a,b){a[e]&&(G[b]=a=i({},G[b]),a[f]=a[e])})}))}function p(c){var d=/^([+\-]?)(\w+)\[([^\]]+)\]$/;e[a.schema]=null,c&&h(b(c,","),function(a){var c,e,f=d.exec(a);f&&(e=f[1],c=e?G[f[2]]:G[f[2]]={"#comment":{}},c=G[f[2]],h(b(f[3],"|"),function(a){"-"===e?delete c[a]:c[a]={}}))})}function q(a){var b,c=F[a];if(c)return c;for(b=H.length;b--;)if(c=H[b],c.pattern.test(a))return c}var r,s,t,u,v,w,x,y,z,A,B,C,D,E=this,F={},G={},H=[],I={},J={};a=a||{},t=c(a.schema),a.verify_html===!1&&(a.valid_elements="*[*]"),r=d(a.valid_styles),s=d(a.invalid_styles,"map"),y=d(a.valid_classes,"map"),u=f("whitespace_elements","pre script noscript style textarea video audio iframe object code"),v=f("self_closing_elements","colgroup dd dt li option p td tfoot th thead tr"),w=f("short_ended_elements","area base basefo
nt br col frame hr img input isindex link meta param embed source wbr track"),x=f("boolean_attributes","checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls"),A=f("non_empty_elements","td th iframe video audio object script pre code",w),B=f("move_caret_before_on_enter_elements","table",A),C=f("text_block_elements","h1 h2 h3 h4 h5 h6 p div address pre form blockquote center dir fieldset header footer article section hgroup aside nav figure"),z=f("block_elements","hr table tbody thead tfoot th tr td li ol ul caption dl dt dd noscript menu isindex option datalist select optgroup figcaption",C),D=f("text_inline_elements","span strong b em i font strike u var cite dfn code mark q sup sub samp"),h((a.special||"script noscript style textarea").split(" "),function(a){J[a]=new
RegExp("</"+a+"[^>]*>","gi")}),a.valid_elements?n(a.valid_elements):(h(t,function(a,b){F[b]={attributes:a.attributes,attributesOrder:a.attributesOrder},G[b]=a.children}),"html5"!=a.schema&&h(b("strong/b em/i"),function(a){a=b(a,"/"),F[a[1]].outputName=a[0]}),h(b("ol ul sub sup blockquote span font a table tbody tr strong em b i"),function(a){F[a]&&(F[a].removeEmpty=!0)}),h(b("p h1 h2 h3 h4 h5 h6 th td pre div address caption"),function(a){F[a].paddEmpty=!0}),h(b("span"),function(a){F[a].removeEmptyAttrs=!0})),o(a.custom_elements),p(a.valid_children),m(a.extended_valid_elements),p("+ol[ul|ol],+ul[ul|ol]"),h({dd:"dl",dt:"dl",li:"ul ol",td:"tr",th:"tr",tr:"tbody thead tfoot",tbody:"table",thead:"table",tfoot:"table",legend:"fieldset",area:"map",param:&quo
t;video audio object"},function(a,c){F[c]&&(F[c].parentsRequired=b(a))}),a.invalid_elements&&h(j(a.invalid_elements),function(a){F[a]&&delete F[a]}),q("span")||m("span[!data-mce-type|*]"),E.children=G,E.getValidStyles=function(){return r},E.getInvalidStyles=function(){return s},E.getValidClasses=function(){return y},E.getBoolAttrs=function(){return x},E.getBlockElements=function(){return z},E.getTextBlockElements=function(){return C},E.getTextInlineElements=function(){return D},E.getShortEndedElements=function(){return w},E.getSelfClosingElements=function(){return v},E.getNonEmptyElements=function(){return A},E.getMoveCaretBeforeOnEnterElements=function(){return B},E.getWhiteSpaceElements=function(){return u},E.getSpecialElements=function(){return J},E.isValidChild=function(a,b){var c=G[a.toLowerCase()];return!(!c||!c[b.toLowerCase()])},E.isValid=function(a,b){var c,d,e=q(a);if(e){if(!b)return!0;if(e.attributes[b])return!0;if(c=e.attr
ibutePatterns)for(d=c.length;d--;)if(c[d].pattern.test(a))return!0}return!1},E.getElementRule=q,E.getCustomElements=function(){return I},E.addValidElements=m,E.setValidElements=n,E.addCustomElements=o,E.addValidChildren=p,E.elements=F}}),g("e",["a","7","1h","8","1i","c","6","d","j","b","9"],function(a,b,c,d,e,f,g,h,i,j,k){function l(a,b){var c,d={},e=b.keep_values;return c={set:function(c,d,e){b.url_converter&&(d=b.url_converter.call(b.url_converter_scope||a,d,e,c[0])),c.attr("data-mce-"+e,d).attr(e,d)},get:function(a,b){return a.attr("data-mce-"+b)||a.attr(b)}},d={style:{set:function(a,b){return null!==b&&"object"==typeof b?void a.css(b):(e&&a.attr("data-mce-style",b),void a.attr("style",b))},get:function(b){var c=b.attr("data-mce-style")||b.attr("style");return c=a.seria
lizeStyle(a.parseStyle(c),b[0].nodeName)}}},e&&(d.href=d.src=c),d}function m(a,b){var c=b.attr("style");c=a.serializeStyle(a.parseStyle(c),b[0].nodeName),c||(c=null),b.attr("data-mce-style",c)}function n(a,b){var c,d,e=0;if(a)for(c=a.nodeType,a=a.previousSibling;a;a=a.previousSibling)d=a.nodeType,(!b||3!=d||d!=c&&a.nodeValue.length)&&(e++,c=d);return e}function o(c,d){var f,g=this;g.doc=c,g.win=window,g.files={},g.counter=0,g.stdMode=!t||c.documentMode>=8,g.boxModel=!t||"CSS1Compat"==c.compatMode||g.stdMode,g.styleSheetLoader=new e(c),g.boundEvents=[],g.settings=d=d||{},g.schema=d.schema?d.schema:new i({}),g.styles=new j({url_converter:d.url_converter,url_converter_scope:d.url_converter_scope},d.schema),g.fixDoc(c),g.events=d.ownEvents?new b(d.proxy):b.Event,g.attrHooks=l(g,d),f=d.schema?d.schema.getBlockElements():{},g.$=a.overrideDefaults(function(){return{context:c,element:g.getRoot()}}),g.isBlock=function(a){if(!a)return!1
;var b=a.nodeType;return b?!(1!==b||!f[a.nodeName]):!!f[a]}}var p=k.each,q=k.is,r=k.grep,s=k.trim,t=g.ie,u=/^([a-z0-9],?)+$/i,v=/^[ \t\r\n]*$/;return o.prototype={$$:function(a){return"string"==typeof a&&(a=this.get(a)),this.$(a)},root:null,fixDoc:function(a){var b,c=this.settings;if(t&&c.schema){"abbr article aside audio canvas details figcaption figure footer header hgroup mark menu meter nav output progress section summary time video".replace(/\w+/g,function(b){a.createElement(b)});for(b in c.schema.getCustomElements())a.createElement(b)}},clone:function(a,b){var c,d,e=this;return!t||1!==a.nodeType||b?a.cloneNode(b):(d=e.doc,b?c.firstChild:(c=d.createElement(a.nodeName),p(e.getAttribs(a),function(b){e.setAttrib(c,b.nodeName,e.getAttrib(a,b.nodeName))}),c))},getRoot:function(){var a=this;return a.settings.root_element||a.doc.body},getViewPort:function(a){var b,c;return a=a?a:this.win,b=a.document,c=this.boxModel?b.documentElement:b.body,{x:a.pag
eXOffset||c.scrollLeft,y:a.pageYOffset||c.scrollTop,w:a.innerWidth||c.clientWidth,h:a.innerHeight||c.clientHeight}},getRect:function(a){var b,c,d=this;return a=d.get(a),b=d.getPos(a),c=d.getSize(a),{x:b.x,y:b.y,w:c.w,h:c.h}},getSize:function(a){var b,c,d=this;return a=d.get(a),b=d.getStyle(a,"width"),c=d.getStyle(a,"height"),b.indexOf("px")===-1&&(b=0),c.indexOf("px")===-1&&(c=0),{w:parseInt(b,10)||a.offsetWidth||a.clientWidth,h:parseInt(c,10)||a.offsetHeight||a.clientHeight}},getParent:function(a,b,c){return this.getParents(a,b,c,!1)},getParents:function(a,b,c,d){var e,f=this,g=[];for(a=f.get(a),d=void 0===d,c=c||("BODY"!=f.getRoot().nodeName?f.getRoot().parentNode:null),q(b,"string")&&(e=b,b="*"===b?function(a){return 1==a.nodeType}:function(a){return f.is(a,e)});a&&a!=c&&a.nodeType&&9!==a.nodeType;){if(!b||b(a)){if(!d)return a;g.push(a)}a=a.parentNode}return d?g:n
ull},get:function(a){var b;return a&&this.doc&&"string"==typeof a&&(b=a,a=this.doc.getElementById(a),a&&a.id!==b)?this.doc.getElementsByName(b)[1]:a},getNext:function(a,b){return this._findSib(a,b,"nextSibling")},getPrev:function(a,b){return this._findSib(a,b,"previousSibling")},select:function(a,b){var c=this;return d(a,c.get(b)||c.settings.root_element||c.doc,[])},is:function(a,b){var c;if(!a)return!1;if(void 0===a.length){if("*"===b)return 1==a.nodeType;if(u.test(b)){for(b=b.toLowerCase().split(/,/),a=a.nodeName.toLowerCase(),c=b.length-1;c>=0;c--)if(b[c]==a)return!0;return!1}}if(a.nodeType&&1!=a.nodeType)return!1;var e=a.nodeType?[a]:a;return d(b,e[0].ownerDocument||e[0],null,e).length>0},add:function(a,b,c,d,e){var f=this;return this.run(a,function(a){var g;return g=q(b,"string")?f.doc.createElement(b):b,f.setAttribs(g,c),d&&(d.nodeType?g.appendChild(d):f.setHTML(g,d)),e?g:a.
appendChild(g)})},create:function(a,b,c){return this.add(this.doc.createElement(a),a,b,c,1)},createHTML:function(a,b,c){var d,e="";e+="<"+a;for(d in b)b.hasOwnProperty(d)&&null!==b[d]&&"undefined"!=typeof b[d]&&(e+=" "+d+'="'+this.encode(b[d])+'"');return"undefined"!=typeof c?e+">"+c+"</"+a+">":e+" />"},createFragment:function(a){var b,c,d,e=this.doc;for(d=e.createElement("div"),b=e.createDocumentFragment(),a&&(d.innerHTML=a);c=d.firstChild;)b.appendChild(c);return b},remove:function(a,b){return a=this.$$(a),b?a.each(function(){for(var a;a=this.firstChild;)3==a.nodeType&&0===a.data.length?this.removeChild(a):this.parentNode.insertBefore(a,this)}).remove():a.remove(),a.length>1?a.toArray():a[0]},setStyle:function(a,b,c){a=this.$$(a).css(b,c),this.settings.update_styles&&m(this,a)},getStyle:function(a,b,c){retur
n a=this.$$(a),c?a.css(b):(b=b.replace(/-(\D)/g,function(a,b){return b.toUpperCase()}),"float"==b&&(b=g.ie&&g.ie<12?"styleFloat":"cssFloat"),a[0]&&a[0].style?a[0].style[b]:void 0)},setStyles:function(a,b){a=this.$$(a).css(b),this.settings.update_styles&&m(this,a)},removeAllAttribs:function(a){return this.run(a,function(a){var b,c=a.attributes;for(b=c.length-1;b>=0;b--)a.removeAttributeNode(c.item(b))})},setAttrib:function(a,b,c){var d,e,f=this,g=f.settings;""===c&&(c=null),a=f.$$(a),d=a.attr(b),a.length&&(e=f.attrHooks[b],e&&e.set?e.set(a,c,b):a.attr(b,c),d!=c&&g.onSetAttrib&&g.onSetAttrib({attrElm:a,attrName:b,attrValue:c}))},setAttribs:function(a,b){var c=this;c.$$(a).each(function(a,d){p(b,function(a,b){c.setAttrib(d,b,a)})})},getAttrib:function(a,b,c){var d,e,f=this;return a=f.$$(a),a.length&&(d=f.attrHooks[b],e=d&&d.get?d.get(a,b):a.attr(b)),&quo
t;undefined"==typeof e&&(e=c||""),e},getPos:function(b,c){var d,e,f=this,g=0,h=0,i=f.doc,j=i.body;if(b=f.get(b),c=c||j,b){if(c===j&&b.getBoundingClientRect&&"static"===a(j).css("position"))return e=b.getBoundingClientRect(),c=f.boxModel?i.documentElement:j,g=e.left+(i.documentElement.scrollLeft||j.scrollLeft)-c.clientLeft,h=e.top+(i.documentElement.scrollTop||j.scrollTop)-c.clientTop,{x:g,y:h};for(d=b;d&&d!=c&&d.nodeType;)g+=d.offsetLeft||0,h+=d.offsetTop||0,d=d.offsetParent;for(d=b.parentNode;d&&d!=c&&d.nodeType;)g-=d.scrollLeft||0,h-=d.scrollTop||0,d=d.parentNode}return{x:g,y:h}},parseStyle:function(a){return this.styles.parse(a)},serializeStyle:function(a,b){return this.styles.serialize(a,b)},addStyle:function(a){var b,c,d=this,e=d.doc;if(d!==o.DOM&&e===document){var f=o.DOM.addedStyles;if(f=f||[],f[a])return;f[a]=!0,o.DOM.addedStyles=f}c=e.getElementById("mceDefaultStyles"
;),c||(c=e.createElement("style"),c.id="mceDefaultStyles",c.type="text/css",b=e.getElementsByTagName("head")[0],b.firstChild?b.insertBefore(c,b.firstChild):b.appendChild(c)),c.styleSheet?c.styleSheet.cssText+=a:c.appendChild(e.createTextNode(a))},loadCSS:function(a){var b,c=this,d=c.doc;return c!==o.DOM&&d===document?void o.DOM.loadCSS(a):(a||(a=""),b=d.getElementsByTagName("head")[0],void p(a.split(","),function(a){var e;a=k._addCacheSuffix(a),c.files[a]||(c.files[a]=!0,e=c.create("link",{rel:"stylesheet",href:a}),t&&d.documentMode&&d.recalc&&(e.onload=function(){d.recalc&&d.recalc(),e.onload=null}),b.appendChild(e))}))},addClass:function(a,b){this.$$(a).addClass(b)},removeClass:function(a,b){this.toggleClass(a,b,!1)},hasClass:function(a,b){return this.$$(a).hasClass(b)},toggleClass:function(b,c,d){this.$$(b).toggleClass(c,d).each(function(){""
===this.className&&a(this).attr("class",null)})},show:function(a){this.$$(a).show()},hide:function(a){this.$$(a).hide()},isHidden:function(a){return"none"==this.$$(a).css("display")},uniqueId:function(a){return(a?a:"mce_")+this.counter++},setHTML:function(b,c){b=this.$$(b),t?b.each(function(b,d){if(d.canHaveHTML!==!1){for(;d.firstChild;)d.removeChild(d.firstChild);try{d.innerHTML="<br>"+c,d.removeChild(d.firstChild)}catch(b){a("<div></div>").html("<br>"+c).contents().slice(1).appendTo(d)}return c}}):b.html(c)},getOuterHTML:function(b){return b=this.get(b),1==b.nodeType&&"outerHTML"in b?b.outerHTML:a("<div></div>").append(a(b).clone()).html()},setOuterHTML:function(b,c){var d=this;d.$$(b).each(function(){try{if("outerHTML"in this)return void(this.outerHTML=c)}catch(a){}d.remove(a(this).html(c),!0)})},decode:h.decode,encode:h.encodeAll
Raw,insertAfter:function(a,b){return b=this.get(b),this.run(a,function(a){var c,d;return c=b.parentNode,d=b.nextSibling,d?c.insertBefore(a,d):c.appendChild(a),a})},replace:function(a,b,c){var d=this;return d.run(b,function(b){return q(b,"array")&&(a=a.cloneNode(!0)),c&&p(r(b.childNodes),function(b){a.appendChild(b)}),b.parentNode.replaceChild(a,b)})},rename:function(a,b){var c,d=this;return a.nodeName!=b.toUpperCase()&&(c=d.create(b),p(d.getAttribs(a),function(b){d.setAttrib(c,b.nodeName,d.getAttrib(a,b.nodeName))}),d.replace(c,a,1)),c||a},findCommonAncestor:function(a,b){for(var c,d=a;d;){for(c=b;c&&d!=c;)c=c.parentNode;if(d==c)break;d=d.parentNode}return!d&&a.ownerDocument?a.ownerDocument.documentElement:d},toHex:function(a){return this.styles.toHex(k.trim(a))},run:function(a,b,c){var d,e=this;return"string"==typeof a&&(a=e.get(a)),!!a&&(c=c||this,a.nodeType||!a.length&&0!==a.length?b.call(c,a):(d=
[],p(a,function(a,f){a&&("string"==typeof a&&(a=e.get(a)),d.push(b.call(c,a,f)))}),d))},getAttribs:function(a){var b;if(a=this.get(a),!a)return[];if(t){if(b=[],"OBJECT"==a.nodeName)return a.attributes;"OPTION"===a.nodeName&&this.getAttrib(a,"selected")&&b.push({specified:1,nodeName:"selected"});var c=/<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi;return a.cloneNode(!1).outerHTML.replace(c,"").replace(/[\w:\-]+/gi,function(a){b.push({specified:1,nodeName:a})}),b}return a.attributes},isEmpty:function(a,b){var c,d,e,g,h,i,j=this,k=0;if(a=a.firstChild){h=new f(a,a.parentNode),b=b||(j.schema?j.schema.getNonEmptyElements():null),g=j.schema?j.schema.getWhiteSpaceElements():{};do{if(e=a.nodeType,1===e){var l=a.getAttribute("data-mce-bogus");if(l){a=h.next("all"===l);continue}if(i=a.nodeName.toLowerCase(),b&&b[i]){if("br"===i){k++,a=h
.next();continue}return!1}for(d=j.getAttribs(a),c=d.length;c--;)if(i=d[c].nodeName,"name"===i||"data-mce-bookmark"===i)return!1}if(8==e)return!1;if(3===e&&!v.test(a.nodeValue))return!1;if(3===e&&a.parentNode&&g[a.parentNode.nodeName]&&v.test(a.nodeValue))return!1;a=h.next()}while(a)}return k<=1},createRng:function(){var a=this.doc;return a.createRange?a.createRange():new c(this)},nodeIndex:n,split:function(a,b,c){function d(a){function b(a){var b=a.previousSibling&&"SPAN"==a.previousSibling.nodeName,c=a.nextSibling&&"SPAN"==a.nextSibling.nodeName;return b&&c}var c,e=a.childNodes,f=a.nodeType;if(1!=f||"bookmark"!=a.getAttribute("data-mce-type")){for(c=e.length-1;c>=0;c--)d(e[c]);if(9!=f){if(3==f&&a.nodeValue.length>0){var g=s(a.nodeValue).length;if(!h.isBlock(a.parentNode)||g>0||0===g&&b(a))return}else if(1==f&&(e=a.childNodes,1==e.le
ngth&&e[0]&&1==e[0].nodeType&&"bookmark"==e[0].getAttribute("data-mce-type")&&a.parentNode.insertBefore(e[0],a),e.length||/^(br|hr|input|img)$/i.test(a.nodeName)))return;h.remove(a)}return a}}var e,f,g,h=this,i=h.createRng();if(a&&b)return i.setStart(a.parentNode,h.nodeIndex(a)),i.setEnd(b.parentNode,h.nodeIndex(b)),e=i.extractContents(),i=h.createRng(),i.setStart(b.parentNode,h.nodeIndex(b)+1),i.setEnd(a.parentNode,h.nodeIndex(a)+1),f=i.extractContents(),g=a.parentNode,g.insertBefore(d(e),a),c?g.insertBefore(c,a):g.insertBefore(b,a),g.insertBefore(d(f),a),h.remove(a),c||b},bind:function(a,b,c,d){var e=this;if(k.isArray(a)){for(var f=a.length;f--;)a[f]=e.bind(a[f],b,c,d);return a}return!e.settings.collect||a!==e.doc&&a!==e.win||e.boundEvents.push([a,b,c,d]),e.events.bind(a,b,c,d||e)},unbind:function(a,b,c){var d,e=this;if(k.isArray(a)){for(d=a.length;d--;)a[d]=e.unbind(a[d],b,c);return a}if(e.boundEvents&&(a
===e.doc||a===e.win))for(d=e.boundEvents.length;d--;){var f=e.boundEvents[d];a!=f[0]||b&&b!=f[1]||c&&c!=f[2]||this.events.unbind(f[0],f[1],f[2])}return this.events.unbind(a,b,c)},fire:function(a,b,c){return this.events.fire(a,b,c)},getContentEditable:function(a){var b;return a&&1==a.nodeType?(b=a.getAttribute("data-mce-contenteditable"),b&&"inherit"!==b?b:"inherit"!==a.contentEditable?a.contentEditable:null):null},getContentEditableParent:function(a){for(var b=this.getRoot(),c=null;a&&a!==b&&(c=this.getContentEditable(a),null===c);a=a.parentNode);return c},destroy:function(){var a=this;if(a.boundEvents){for(var b=a.boundEvents.length;b--;){var c=a.boundEvents[b];this.events.unbind(c[0],c[1],c[2])}a.boundEvents=null}d.setDocument&&d.setDocument(),a.win=a.doc=a.root=a.events=a.frag=null},isChildOf:function(a,b){for(;a;){if(b===a)return!0;a=a.parentNode}return!1},dumpRng:function(a){return"startC
ontainer: "+a.startContainer.nodeName+", startOffset: "+a.startOffset+", endContainer: "+a.endContainer.nodeName+", endOffset: "+a.endOffset},_findSib:function(a,b,c){var d=this,e=b;if(a)for("string"==typeof e&&(e=function(a){return d.is(a,b)}),a=a[c];a;a=a[c])if(e(a))return a;return null}},o.DOM=new o(document),o.nodeIndex=n,o}),g("f",["e","9"],function(a,b){function c(){function a(a,c,e){function f(){k.remove(j),i&&(i.onreadystatechange=i.onload=i=null),c()}function h(){g(e)?e():"undefined"!=typeof console&&console.log&&console.log("Failed to load script: "+a)}var i,j,k=d;j=k.uniqueId(),i=document.createElement("script"),i.id=j,i.type="text/javascript",i.src=b._addCacheSuffix(a),"onreadystatechange"in i?i.onreadystatechange=function(){/loaded|complete/.test(i.readyState)&&f()}:i.onload=f,i.onerror=h,(document.getElemen
tsByTagName("head")[0]||document.body).appendChild(i)}var c,h=0,i=1,j=2,k=3,l={},m=[],n={},o=[],p=0;this.isDone=function(a){return l[a]==j},this.markDone=function(a){l[a]=j},this.add=this.load=function(a,b,d,e){var f=l[a];f==c&&(m.push(a),l[a]=h),b&&(n[a]||(n[a]=[]),n[a].push({success:b,failure:e,scope:d||this}))},this.remove=function(a){delete l[a],delete n[a]},this.loadQueue=function(a,b,c){this.loadScripts(m,a,b,c)},this.loadScripts=function(b,d,h,m){function q(a,b){e(n[b],function(b){g(b[a])&&b[a].call(b.scope)}),n[b]=c}var r,s=[];o.push({success:d,failure:m,scope:h||this}),(r=function(){var c=f(b);b.length=0,e(c,function(b){return l[b]===j?void q("success",b):l[b]===k?void q("failure",b):void(l[b]!==i&&(l[b]=i,p++,a(b,function(){l[b]=j,p--,q("success",b),r()},function(){l[b]=k,p--,s.push(b),q("failure",b),r()})))}),p||(e(o,function(a){0===s.length?g(a.success)&&a.success.call(a.scope):g(a.
failure)&&a.failure.call(a.scope,s)}),o.length=0)})()}}var d=a.DOM,e=b.each,f=b.grep,g=function(a){return"function"==typeof a};return c.ScriptLoader=new c,c}),g("g",["f","9"],function(a,b){function c(){var a=this;a.items=[],a.urls={},a.lookup={}}var d=b.each;return c.prototype={get:function(a){if(this.lookup[a])return this.lookup[a].instance},dependencies:function(a){var b;return this.lookup[a]&&(b=this.lookup[a].dependencies),b||[]},requireLangPack:function(b,d){var e=c.language;if(e&&c.languageLoad!==!1){if(d)if(d=","+d+",",d.indexOf(","+e.substr(0,2)+",")!=-1)e=e.substr(0,2);else if(d.indexOf(","+e+",")==-1)return;a.ScriptLoader.add(this.urls[b]+"/langs/"+e+".js")}},add:function(a,b,c){return this.items.push(b),this.lookup[a]={instance:b,dependencies:c},b},remove:function(a){delete this.urls[a],delete this.lookup[a]},createUrl:function(a,
b){return"object"==typeof b?b:{prefix:a.prefix,resource:b,suffix:a.suffix}},addComponents:function(b,c){var e=this.urls[b];d(c,function(b){a.ScriptLoader.add(e+"/"+b)})},load:function(b,e,f,g,h){function i(){var c=j.dependencies(b);d(c,function(a){var b=j.createUrl(e,a);j.load(b.resource,b,void 0,void 0)}),f&&(g?f.call(g):f.call(a))}var j=this,k=e;j.urls[b]||("object"==typeof e&&(k=e.prefix+e.resource+e.suffix),0!==k.indexOf("/")&&k.indexOf("://")==-1&&(k=c.baseURL+"/"+k),j.urls[b]=k.substring(0,k.lastIndexOf("/")),j.lookup[b]?i():a.ScriptLoader.add(k,i,g,h))}},c.PluginManager=new c,c.ThemeManager=new c,c}),g("1j",[],function(){function a(a){return function(b){return!!b&&b.nodeType==a}}function b(a){return a=a.toLowerCase().split(" "),function(b){var c,d;if(b&&b.nodeType)for(d=b.nodeName.toLowerCase(),c=0;c<a.length;c++)if(d===a[c])return!0;ret
urn!1}}function c(a,b){return b=b.toLowerCase().split(" "),function(c){var d,e;if(i(c))for(d=0;d<b.length;d++)if(e=c.ownerDocument.defaultView.getComputedStyle(c,null).getPropertyValue(a),e===b[d])return!0;return!1}}function d(a,b){return function(c){return i(c)&&c[a]===b}}function e(a,b){return function(b){return i(b)&&b.hasAttribute(a)}}function f(a,b){return function(c){return i(c)&&c.getAttribute(a)===b}}function g(a){return i(a)&&a.hasAttribute("data-mce-bogus")}function h(a){return function(b){if(i(b)){if(b.contentEditable===a)return!0;if(b.getAttribute("data-mce-contenteditable")===a)return!0}return!1}}var i=a(1);return{isText:a(3),isElement:i,isComment:a(8),isBr:b("br"),isContentEditableTrue:h("true"),isContentEditableFalse:h("false"),matchNodeNames:b,hasPropValue:d,hasAttribute:e,hasAttributeValue:f,matchStyleValues:c,isBogus:g}}),g("1l",[],function(){var a="\ufeff&
quot;,b=function(b){return b===a},c=function(b){return b.replace(new RegExp(a,"g"),"")};return{isZwsp:b,ZWSP:a,trim:c}}),g("1k",["1j","1l"],function(a,b){function c(a){return n(a)&&(a=a.parentNode),m(a)&&a.hasAttribute("data-mce-caret")}function d(a){return n(a)&&b.isZwsp(a.data)}function e(a){return c(a)||d(a)}function f(a,c){var d,f,g,h;if(d=a.ownerDocument,g=d.createTextNode(b.ZWSP),h=a.parentNode,c){if(f=a.previousSibling,n(f)){if(e(f))return f;if(j(f))return f.splitText(f.data.length-1)}h.insertBefore(g,a)}else{if(f=a.nextSibling,n(f)){if(e(f))return f;if(i(f))return f.splitText(1),f}a.nextSibling?h.insertBefore(g,a.nextSibling):h.appendChild(g)}return g}function g(){var a=document.createElement("br");return a.setAttribute("data-mce-bogus","1"),a}function h(a,b,c){var d,e,f;return d=b.ownerDocument,e=d.createElement(a),e.setAttribute("data-mce-caret",c?&qu
ot;before":"after"),e.setAttribute("data-mce-bogus","all"),e.appendChild(g()),f=b.parentNode,c?f.insertBefore(e,b):b.nextSibling?f.insertBefore(e,b.nextSibling):f.appendChild(e),e}function i(a){return n(a)&&a.data[0]==b.ZWSP}function j(a){return n(a)&&a.data[a.data.length-1]==b.ZWSP}function k(b){var c=b.getElementsByTagName("br"),d=c[c.length-1];a.isBogus(d)&&d.parentNode.removeChild(d)}function l(a){return a&&a.hasAttribute("data-mce-caret")?(k(a),a.removeAttribute("data-mce-caret"),a.removeAttribute("data-mce-bogus"),a.removeAttribute("style"),a.removeAttribute("_moz_abspos"),a):null}var m=a.isElement,n=a.isText,o=function(b){return b.firstChild!==b.lastChild||!a.isBr(b.firstChild)},p=function(c){if(a.isText(c)){var d=c.data;return d.length>0&&d.charAt(0)!==b.ZWSP&&c.insertData(0,b.ZWSP),c}return null},q=function(c){if(a.isText(c)){var
d=c.data;return d.length>0&&d.charAt(d.length-1)!==b.ZWSP&&c.insertData(d.length,b.ZWSP),c}return null},r=function(c){return c&&a.isText(c.container())&&c.container().data.charAt(c.offset())===b.ZWSP},s=function(c){return c&&a.isText(c.container())&&c.container().data.charAt(c.offset()-1)===b.ZWSP};return{isCaretContainer:e,isCaretContainerBlock:c,isCaretContainerInline:d,showCaretContainerBlock:l,insertInline:f,prependInline:p,appendInline:q,isBeforeInline:r,isAfterInline:s,insertBlock:h,hasContent:o,startsWithCaretContainer:i,endsWithCaretContainer:j}}),g("h",["9","c","1j","1h","1k"],function(a,b,c,d,e){
+function f(a){return q(a)||r(a)}function g(a,b){var c=a.childNodes;return b--,b>c.length-1?b=c.length-1:b<0&&(b=0),c[b]||a}function h(a,b,c){for(;a&&a!==b;){if(c(a))return a;a=a.parentNode}return null}function i(a,b,c){return null!==h(a,b,c)}function j(a,b,c){return i(a,b,function(a){return a.nodeName===c})}function k(a){return"_mce_caret"===a.id}function l(a,b){return s(a)&&i(a,b,k)===!1}function m(a){this.walk=function(b,c){function d(a){var b;return b=a[0],3===b.nodeType&&b===q&&r>=b.nodeValue.length&&a.splice(0,1),b=a[a.length-1],0===t&&a.length>0&&b===s&&3===b.nodeType&&a.splice(a.length-1,1),a}function e(a,b,c){for(var d=[];a&&a!=c;a=a[b])d.push(a);return d}function f(a,b){do{if(a.parentNode==b)return a;a=a.parentNode}while(a)}function h(a,b,f){var g=f?"nextSibling":"previousSibling";for(l=a,m=l.parentNode;l&&l!=b;l=m)m=l.parentNode,n=e(l==a
?l:l[g],g),n.length&&(f||n.reverse(),c(d(n)))}var i,j,k,l,m,n,o,q=b.startContainer,r=b.startOffset,s=b.endContainer,t=b.endOffset;if(o=a.select("td[data-mce-selected],th[data-mce-selected]"),o.length>0)return void p(o,function(a){c([a])});if(1==q.nodeType&&q.hasChildNodes()&&(q=q.childNodes[r]),1==s.nodeType&&s.hasChildNodes()&&(s=g(s,t)),q==s)return c(d([q]));for(i=a.findCommonAncestor(q,s),l=q;l;l=l.parentNode){if(l===s)return h(q,i,!0);if(l===i)break}for(l=s;l;l=l.parentNode){if(l===q)return h(s,i);if(l===i)break}j=f(q,i)||q,k=f(s,i)||s,h(q,j,!0),n=e(j==q?j:j.nextSibling,"nextSibling",k==s?k.nextSibling:k),n.length&&c(d(n)),h(s,k)},this.split=function(a){function b(a,b){return a.splitText(b)}var c=a.startContainer,d=a.startOffset,e=a.endContainer,f=a.endOffset;return c==e&&3==c.nodeType?d>0&&d<c.nodeValue.length&&(e=b(c,d),c=e.previousSibling,f>d?(f-=d,c=e=b(e,f).previousSiblin
g,f=e.nodeValue.length,d=0):f=0):(3==c.nodeType&&d>0&&d<c.nodeValue.length&&(c=b(c,d),d=0),3==e.nodeType&&f>0&&f<e.nodeValue.length&&(e=b(e,f).previousSibling,f=e.nodeValue.length)),{startContainer:c,startOffset:d,endContainer:e,endOffset:f}},this.normalize=function(c){function d(d){function g(a){return a&&/^(TD|TH|CAPTION)$/.test(a.nodeName)}function h(c,d){for(var e=new b(c,a.getParent(c.parentNode,a.isBlock)||w);c=e[d?"prev":"next"]();)if("BR"===c.nodeName)return!0}function i(a){for(;a&&a!=w;){if(r(a))return!0;a=a.parentNode}return!1}function k(a,b){return a.previousSibling&&a.previousSibling.nodeName==b}function m(c,d){var g,h,i;if(d=d||n,i=a.getParent(d.parentNode,a.isBlock)||w,c&&"BR"==d.nodeName&&v&&a.isEmpty(i))return n=d.parentNode,o=a.nodeIndex(d),void(f=!0);for(g=new b(d,i);q=g[c?"prev":"next"]();){if("
;false"===a.getContentEditableParent(q)||l(q,a.getRoot()))return;if(3===q.nodeType&&q.nodeValue.length>0)return void(j(q,w,"A")===!1&&(n=q,o=c?q.nodeValue.length:0,f=!0));if(a.isBlock(q)||t[q.nodeName.toLowerCase()])return;h=q}e&&h&&(n=h,f=!0,o=0)}var n,o,p,q,t,u,v,w=a.getRoot();if(n=c[(d?"start":"end")+"Container"],o=c[(d?"start":"end")+"Offset"],v=1==n.nodeType&&o===n.childNodes.length,t=a.schema.getNonEmptyElements(),u=d,!s(n)){if(1==n.nodeType&&o>n.childNodes.length-1&&(u=!1),9===n.nodeType&&(n=a.getRoot(),o=0),n===w){if(u&&(q=n.childNodes[o>0?o-1:0])){if(s(q))return;if(t[q.nodeName]||"TABLE"==q.nodeName)return}if(n.hasChildNodes()){if(o=Math.min(!u&&o>0?o-1:o,n.childNodes.length-1),n=n.childNodes[o],o=0,!e&&n===w.lastChild&&"TABLE"===n.nodeName)return;if(i(n)||s(n))return;if(n.h
asChildNodes()&&!/TABLE/.test(n.nodeName)){q=n,p=new b(n,w);do{if(r(q)||s(q)){f=!1;break}if(3===q.nodeType&&q.nodeValue.length>0){o=u?0:q.nodeValue.length,n=q,f=!0;break}if(t[q.nodeName.toLowerCase()]&&!g(q)){o=a.nodeIndex(q),n=q.parentNode,"IMG"!=q.nodeName||u||o++,f=!0;break}}while(q=u?p.next():p.prev())}}}e&&(3===n.nodeType&&0===o&&m(!0),1===n.nodeType&&(q=n.childNodes[o],q||(q=n.childNodes[o-1]),!q||"BR"!==q.nodeName||k(q,"A")||h(q)||h(q,!0)||m(!0,q))),u&&!e&&3===n.nodeType&&o===n.nodeValue.length&&m(!1),f&&c["set"+(d?"Start":"End")](n,o)}}var e,f=!1;return e=c.collapsed,d(!0),e||d(),f&&e&&c.collapse(!0),f}}function n(b,c,d){var e,f,g;if(e=d.elementFromPoint(b,c),f=d.body.createTextRange(),e&&"HTML"!=e.tagName||(e=d.body),f.moveToElementText(e),g=a.toArray(f.getClientRects()),g=g.sort(func
tion(a,b){return a=Math.abs(Math.max(a.top-c,a.bottom-c)),b=Math.abs(Math.max(b.top-c,b.bottom-c)),a-b}),g.length>0){c=(g[0].bottom+g[0].top)/2;try{return f.moveToPoint(b,c),f.collapse(!0),f}catch(a){}}return null}function o(a,b){var c=a&&a.parentElement?a.parentElement():null;return r(h(c,b,f))?null:a}var p=a.each,q=c.isContentEditableTrue,r=c.isContentEditableFalse,s=e.isCaretContainer;return m.compareRanges=function(a,b){if(a&&b){if(!a.item&&!a.duplicate)return a.startContainer==b.startContainer&&a.startOffset==b.startOffset;if(a.item&&b.item&&a.item(0)===b.item(0))return!0;if(a.isEqual&&b.isEqual&&b.isEqual(a))return!0}return!1},m.getCaretRangeFromPoint=function(a,b,c){var d,e;if(c.caretPositionFromPoint)e=c.caretPositionFromPoint(a,b),d=c.createRange(),d.setStart(e.offsetNode,e.offset),d.collapse(!0);else if(c.caretRangeFromPoint)d=c.caretRangeFromPoint(a,b);else if(c.body.createTextRange){d=c.body.createTextRan
ge();try{d.moveToPoint(a,b),d.collapse(!0)}catch(e){d=n(a,b,c)}return o(d,c.body)}return d},m.getSelectedNode=function(a){var b=a.startContainer,c=a.startOffset;return b.hasChildNodes()&&a.endOffset==c+1?b.childNodes[c]:null},m.getNode=function(a,b){return 1==a.nodeType&&a.hasChildNodes()&&(b>=a.childNodes.length&&(b=a.childNodes.length-1),a=a.childNodes[b]),a},m}),g("i",[],function(){function a(a,b,c){var d,e,f=c?"lastChild":"firstChild",g=c?"prev":"next";if(a[f])return a[f];if(a!==b){if(d=a[g])return d;for(e=a.parent;e&&e!==b;e=e.parent)if(d=e[g])return d}}function b(a,b){this.name=a,this.type=b,1===b&&(this.attributes=[],this.attributes.map={})}var c=/^[ \t\r\n]*$/,d={"#text":3,"#comment":8,"#cdata":4,"#pi":7,"#doctype":10,"#document-fragment":11};return b.prototype={replace:function(a){var b=this;return a.parent&&
;a.remove(),b.insert(a,b),b.remove(),b},attr:function(a,b){var c,d,e,f=this;if("string"!=typeof a){for(d in a)f.attr(d,a[d]);return f}if(c=f.attributes){if(b!==e){if(null===b){if(a in c.map)for(delete c.map[a],d=c.length;d--;)if(c[d].name===a)return c=c.splice(d,1),f;return f}if(a in c.map){for(d=c.length;d--;)if(c[d].name===a){c[d].value=b;break}}else c.push({name:a,value:b});return c.map[a]=b,f}return c.map[a]}},clone:function(){var a,c,d,e,f,g=this,h=new b(g.name,g.type);if(d=g.attributes){for(f=[],f.map={},a=0,c=d.length;a<c;a++)e=d[a],"id"!==e.name&&(f[f.length]={name:e.name,value:e.value},f.map[e.name]=e.value);h.attributes=f}return h.value=g.value,h.shortEnded=g.shortEnded,h},wrap:function(a){var b=this;return b.parent.insert(a,b),a.append(b),b},unwrap:function(){var a,b,c=this;for(a=c.firstChild;a;)b=a.next,c.insert(a,c,!0),a=b;c.remove()},remove:function(){var a=this,b=a.parent,c=a.next,d=a.prev;return b&&(b.firstChild===a?(b.firstChil
d=c,c&&(c.prev=null)):d.next=c,b.lastChild===a?(b.lastChild=d,d&&(d.next=null)):c.prev=d,a.parent=a.next=a.prev=null),a},append:function(a){var b,c=this;return a.parent&&a.remove(),b=c.lastChild,b?(b.next=a,a.prev=b,c.lastChild=a):c.lastChild=c.firstChild=a,a.parent=c,a},insert:function(a,b,c){var d;return a.parent&&a.remove(),d=b.parent||this,c?(b===d.firstChild?d.firstChild=a:b.prev.next=a,a.prev=b.prev,a.next=b,b.prev=a):(b===d.lastChild?d.lastChild=a:b.next.prev=a,a.next=b.next,a.prev=b,b.next=a),a.parent=d,a},getAll:function(b){var c,d=this,e=[];for(c=d.firstChild;c;c=a(c,d))c.name===b&&e.push(c);return e},empty:function(){var b,c,d,e=this;if(e.firstChild){for(b=[],d=e.firstChild;d;d=a(d,e))b.push(d);for(c=b.length;c--;)d=b[c],d.parent=d.firstChild=d.lastChild=d.next=d.prev=null}return e.firstChild=e.lastChild=null,e},isEmpty:function(b,d){var e,f,g=this,h=g.firstChild;if(d=d||{},h)do{if(1===h.type){if(h.attributes.map["data-mce-bogu
s"])continue;if(b[h.name])return!1;for(e=h.attributes.length;e--;)if(f=h.attributes[e].name,"name"===f||0===f.indexOf("data-mce-bookmark"))return!1}if(8===h.type)return!1;if(3===h.type&&!c.test(h.value))return!1;if(3===h.type&&h.parent&&d[h.parent.name]&&c.test(h.value))return!1}while(h=a(h,g));return!0},walk:function(b){return a(this,null,b)}},b.create=function(a,c){var e,f;if(e=new b(a,d[a]||1),c)for(f in c)e.attr(f,c[f]);return e},b}),g("k",["j","d","9"],function(a,b,c){function d(a,b,c){var d,e,f,g,h=1;for(g=a.getShortEndedElements(),f=/<([!?\/])?([A-Za-z0-9\-_\:\.]+)((?:\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\/|\s+)>/g,f.lastIndex=d=c;e=f.exec(b);){if(d=f.lastIndex,"/"===e[1])h--;else if(!e[1]){if(e[2]in g)continue;h++}if(0===h)break}return d}function e(e,h){function i(){}var j=this;e=e||{},j.schema=h=h||new a,e.fix_self_closing!=
=!1&&(e.fix_self_closing=!0),f("comment cdata text start end pi doctype".split(" "),function(a){a&&(j[a]=e[a]||i)}),j.parse=function(a){function f(a){var b,c;for(b=O.length;b--&&O[b].name!==a;);if(b>=0){for(c=O.length-1;c>=b;c--)a=O[c],a.valid&&M.end(a.name);O.length=b}}function i(a,b,c,d,f){var h,i,j=/[\s\u0000-\u001F]+/g;if(b=b.toLowerCase(),c=b in t?b:Q(c||d||f||""),v&&!q&&g(b)===!1){if(h=A[b],!h&&B){for(i=B.length;i--&&(h=B[i],!h.pattern.test(b)););i===-1&&(h=null)}if(!h)return;if(h.validValues&&!(c in h.validValues))return}if(R[b]&&!e.allow_script_urls){var k=c.replace(j,"");try{k=decodeURIComponent(k)}catch(a){k=unescape(k)}if(S.test(k))return;if(!e.allow_html_data_urls&&T.test(k)&&!/^data:image\//i.test(k))return}m.map[b]=c,m.push({name:b,value:c})}var j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M=this,N=0,O=[],P=0
,Q=b.decode,R=c.makeMap("src,href,data,background,formaction,poster"),S=/((java|vb)script|mhtml):/i,T=/^data:/i;for(H=new RegExp("<(?:(?:!--([\\w\\W]*?)-->)|(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|(?:!DOCTYPE([\\w\\W]*?)>)|(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|(?:\\/([A-Za-z][A-Za-z0-9\\-_\\:\\.]*)>)|(?:([A-Za-z][A-Za-z0-9\\-_\\:\\.]*)((?:\\s+[^\"'>]+(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>]*))*|\\/|\\s+)>))","g"),I=/([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:[^\"])*)\")|(?:\'((?:[^\'])*)\')|([^>\s]+)))?/g,s=h.getShortEndedElements(),G=e.self_closing_elements||h.getSelfClosingElements(),t=h.getBoolAttrs(),v=e.validate,r=e.remove_internals,L=e.fix_self_closing,J=h.getSpecialElements();j=H.exec(a+">");){if(N<j.index&&M.text(Q(a.substr(N,j.index-N))),k=j[6])k=k.toLowerCase(),":"===k.charAt(0)&&(k=k.substr(1)),f(k);else if(k=j[7]){if(j.index+j[0].length>a.length
){M.text(Q(a.substr(j.index))),N=j.index+j[0].length;continue}if(k=k.toLowerCase(),":"===k.charAt(0)&&(k=k.substr(1)),u=k in s,L&&G[k]&&O.length>0&&O[O.length-1].name===k&&f(k),!v||(w=h.getElementRule(k))){if(x=!0,v&&(A=w.attributes,B=w.attributePatterns),(z=j[8])?(q=z.indexOf("data-mce-type")!==-1,q&&r&&(x=!1),m=[],m.map={},z.replace(I,i)):(m=[],m.map={}),v&&!q){if(C=w.attributesRequired,D=w.attributesDefault,E=w.attributesForced,F=w.removeEmptyAttrs,F&&!m.length&&(x=!1),E)for(n=E.length;n--;)y=E[n],p=y.name,K=y.value,"{$uid}"===K&&(K="mce_"+P++),m.map[p]=K,m.push({name:p,value:K});if(D)for(n=D.length;n--;)y=D[n],p=y.name,p in m.map||(K=y.value,"{$uid}"===K&&(K="mce_"+P++),m.map[p]=K,m.push({name:p,value:K}));if(C){for(n=C.length;n--&&!(C[n]in m.map););n===-1&&(x=!1)}if(y=m.map["data-mce-bogus&quo
t;]){if("all"===y){N=d(h,a,H.lastIndex),H.lastIndex=N;continue}x=!1}}x&&M.start(k,m,u)}else x=!1;if(l=J[k]){l.lastIndex=N=j.index+j[0].length,(j=l.exec(a))?(x&&(o=a.substr(N,j.index-N)),N=j.index+j[0].length):(o=a.substr(N),N=a.length),x&&(o.length>0&&M.text(o,!0),M.end(k)),H.lastIndex=N;continue}u||(z&&z.indexOf("/")==z.length-1?x&&M.end(k):O.push({name:k,valid:x}))}else(k=j[1])?(">"===k.charAt(0)&&(k=" "+k),e.allow_conditional_comments||"[if"!==k.substr(0,3).toLowerCase()||(k=" "+k),M.comment(k)):(k=j[2])?M.cdata(k):(k=j[3])?M.doctype(k):(k=j[4])&&M.pi(k,j[5]);N=j.index+j[0].length}for(N<a.length&&M.text(Q(a.substr(N))),n=O.length-1;n>=0;n--)k=O[n],k.valid&&M.end(k.name)}}var f=c.each,g=function(a){return 0===a.indexOf("data-")||0===a.indexOf("aria-")};return e.findEndTag=d,e}),g("l",["i",&qu
ot;j","k","9"],function(a,b,c,d){var e=d.makeMap,f=d.each,g=d.explode,h=d.extend,i=function(b,c){b.padd_empty_with_br?c.empty().append(new a("br","1")).shortEnded=!0:c.empty().append(new a("#text","3")).value="\xa0"},j=function(a,b){return a&&a.firstChild===a.lastChild&&a.firstChild.name===b};return function(k,l){function m(b){var c,d,f,g,h,i,k,m,o,p,q,r,s,t,u,v;for(r=e("tr,td,th,tbody,thead,tfoot,table"),p=l.getNonEmptyElements(),q=l.getWhiteSpaceElements(),s=l.getTextBlockElements(),t=l.getSpecialElements(),c=0;c<b.length;c++)if(d=b[c],d.parent&&!d.fixed)if(s[d.name]&&"li"==d.parent.name){for(u=d.next;u&&s[u.name];)u.name="li",u.fixed=!0,d.parent.insert(u,d.parent),u=u.next;d.unwrap(d)}else{for(g=[d],f=d.parent;f&&!l.isValidChild(f.name,d.name)&&!r[f.name];f=f.parent)g.push(f);if(f&&g.length>1){for(g.reverse(
),h=i=n.filterNode(g[0].clone()),o=0;o<g.length-1;o++){for(l.isValidChild(i.name,g[o].name)?(k=n.filterNode(g[o].clone()),i.append(k)):k=i,m=g[o].firstChild;m&&m!=g[o+1];)v=m.next,k.append(m),m=v;i=k}h.isEmpty(p,q)?f.insert(d,g[0],!0):(f.insert(h,g[0],!0),f.insert(d,h)),f=g[0],(f.isEmpty(p,q)||j(f,"br"))&&f.empty().remove()}else if(d.parent){if("li"===d.name){if(u=d.prev,u&&("ul"===u.name||"ul"===u.name)){u.append(d);continue}if(u=d.next,u&&("ul"===u.name||"ul"===u.name)){u.insert(d,u.firstChild,!0);continue}d.wrap(n.filterNode(new a("ul",1)));continue}l.isValidChild(d.parent.name,"div")&&l.isValidChild("div",d.name)?d.wrap(n.filterNode(new a("div",1))):t[d.name]?d.empty().remove():d.unwrap()}}}var n=this,o={},p=[],q={},r={};k=k||{},k.validate=!("validate"in k)||k.validate,k.root_name=k.root_name||"body",n.schema=l=l||new
b,n.filterNode=function(a){var b,c,d;c in o&&(d=q[c],d?d.push(a):q[c]=[a]),b=p.length;for(;b--;)c=p[b].name,c in a.attributes.map&&(d=r[c],d?d.push(a):r[c]=[a]);return a},n.addNodeFilter=function(a,b){f(g(a),function(a){var c=o[a];c||(o[a]=c=[]),c.push(b)})},n.addAttributeFilter=function(a,b){f(g(a),function(a){var c;for(c=0;c<p.length;c++)if(p[c].name===a)return void p[c].callbacks.push(b);p.push({name:a,callbacks:[b]})})},n.parse=function(b,d){function f(){function a(a){a&&(d=a.firstChild,d&&3==d.type&&(d.value=d.value.replace(E,"")),d=a.lastChild,d&&3==d.type&&(d.value=d.value.replace(G,"")))}var b,c,d=t.firstChild;if(l.isValidChild(t.name,M.toLowerCase())){for(;d;)b=d.next,3==d.type||1==d.type&&"p"!==d.name&&!D[d.name]&&!d.attr("data-mce-type")?c?c.append(d):(c=g(M,1),c.attr(k.forced_root_block_attrs),t.insert(c,d),c.append(d)):(a(c),c=null),d=b;a(c)}}functi
on g(b,c){var d,e=new a(b,c);return b in o&&(d=q[b],d?d.push(e):q[b]=[e]),e}function j(a){var b,c,d,e,f=l.getBlockElements();for(b=a.prev;b&&3===b.type;){if(d=b.value.replace(G,""),d.length>0)return void(b.value=d);if(c=b.next){if(3==c.type&&c.value.length){b=b.prev;continue}if(!f[c.name]&&"script"!=c.name&&"style"!=c.name){b=b.prev;continue}}e=b.prev,b.remove(),b=e}}function n(a){var b,c={};for(b in a)"li"!==b&&"p"!=b&&(c[b]=a[b]);return c}var s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N=[];if(d=d||{},q={},r={},D=h(e("script,style,head,html,body,title,meta,param"),l.getBlockElements()),L=l.getNonEmptyElements(),K=l.children,C=k.validate,M="forced_root_block"in d?d.forced_root_block:k.forced_root_block,J=l.getWhiteSpaceElements(),E=/^[ \t\r\n]+/,G=/[ \t\r\n]+$/,H=/[ \t\r\n]+/g,I=/^[ \t\r\n]+$/,s=new c({validate:C,allow_script_urls:k.allow_script_urls,allow_
conditional_comments:k.allow_conditional_comments,self_closing_elements:n(l.getSelfClosingElements()),cdata:function(a){u.append(g("#cdata",4)).value=a},text:function(a,b){var c;F||(a=a.replace(H," "),u.lastChild&&D[u.lastChild.name]&&(a=a.replace(E,""))),0!==a.length&&(c=g("#text",3),c.raw=!!b,u.append(c).value=a)},comment:function(a){u.append(g("#comment",8)).value=a},pi:function(a,b){u.append(g(a,7)).value=b,j(u)},doctype:function(a){var b;b=u.append(g("#doctype",10)),b.value=a,j(u)},start:function(a,b,c){var d,e,f,h,i;if(f=C?l.getElementRule(a):{}){for(d=g(f.outputName||a,1),d.attributes=b,d.shortEnded=c,u.append(d),i=K[u.name],i&&K[d.name]&&!i[d.name]&&N.push(d),e=p.length;e--;)h=p[e].name,h in b.map&&(A=r[h],A?A.push(d):r[h]=[d]);D[a]&&j(d),c||(u=d),!F&&J[a]&&(F=!0)}},end:function(a){var b,c,d,e,f;if(c=C?l.getElementRule(a):{}){if(D[a]&
;&!F){if(b=u.firstChild,b&&3===b.type)if(d=b.value.replace(E,""),d.length>0)b.value=d,b=b.next;else for(e=b.next,b.remove(),b=e;b&&3===b.type;)d=b.value,e=b.next,(0===d.length||I.test(d))&&(b.remove(),b=e),b=e;if(b=u.lastChild,b&&3===b.type)if(d=b.value.replace(G,""),d.length>0)b.value=d,b=b.prev;else for(e=b.prev,b.remove(),b=e;b&&3===b.type;)d=b.value,e=b.prev,(0===d.length||I.test(d))&&(b.remove(),b=e),b=e}if(F&&J[a]&&(F=!1),(c.removeEmpty||c.paddEmpty)&&u.isEmpty(L,J))if(c.paddEmpty)i(k,u);else if(!u.attributes.map.name&&!u.attributes.map.id)return f=u.parent,D[u.name]?u.empty().remove():u.unwrap(),void(u=f);u=u.parent}}},l),t=u=new a(d.context||k.root_name,11),s.parse(b),C&&N.length&&(d.context?d.invalid=!0:m(N)),M&&("body"==t.name||d.isRootContent)&&f(),!d.invalid){for(B in q){for(A=o[B],v=q[B],y=v.length;y--;)v[y].parent||v.sp
lice(y,1);for(w=0,x=A.length;w<x;w++)A[w](v,B,d)}for(w=0,x=p.length;w<x;w++)if(A=p[w],A.name in r){for(v=r[A.name],y=v.length;y--;)v[y].parent||v.splice(y,1);for(y=0,z=A.callbacks.length;y<z;y++)A.callbacks[y](v,A.name,d)}}return t},k.remove_trailing_brs&&n.addNodeFilter("br",function(b){var c,d,e,f,g,j,m,n,o=b.length,p=h({},l.getBlockElements()),q=l.getNonEmptyElements(),r=l.getNonEmptyElements();for(p.body=1,c=0;c<o;c++)if(d=b[c],e=d.parent,p[d.parent.name]&&d===e.lastChild){for(g=d.prev;g;){if(j=g.name,"span"!==j||"bookmark"!==g.attr("data-mce-type")){if("br"!==j)break;if("br"===j){d=null;break}}g=g.prev}d&&(d.remove(),e.isEmpty(q,r)&&(m=l.getElementRule(e.name),m&&(m.removeEmpty?e.remove():m.paddEmpty&&i(k,e))))}else{for(f=d;e&&e.firstChild===f&&e.lastChild===f&&(f=e,!p[e.name]);)e=e.parent;f===e&&k.padd_empty_with_br!==!0&&a
mp;(n=new a("#text",3),n.value="\xa0",d.replace(n))}}),k.allow_unsafe_link_target||n.addAttributeFilter("href",function(a){function b(a){return a=c(a),a?[a,i].join(" "):i}function c(a){var b=new RegExp("("+i.replace(" ","|")+")","g");return a&&(a=d.trim(a.replace(b,""))),a?a:null}function e(a,d){return d?b(a):c(a)}for(var f,g,h=a.length,i="noopener noreferrer";h--;)f=a[h],g=f.attr("rel"),"a"===f.name&&f.attr("rel",e(g,"_blank"==f.attr("target")))}),k.allow_html_in_named_anchor||n.addAttributeFilter("id,name",function(a){for(var b,c,d,e,f=a.length;f--;)if(e=a[f],"a"===e.name&&e.firstChild&&!e.attr("href")){d=e.parent,b=e.lastChild;do c=b.prev,d.insert(b,e),b=c;while(b)}}),k.fix_list_elements&&n.addNodeFilter("ul,ol",function(b){for(var c,d,e=b.leng
th;e--;)if(c=b[e],d=c.parent,"ul"===d.name||"ol"===d.name)if(c.prev&&"li"===c.prev.name)c.prev.append(c);else{var f=new a("li",1);f.attr("style","list-style-type: none"),c.wrap(f)}}),k.validate&&l.getValidClasses()&&n.addAttributeFilter("class",function(a){for(var b,c,d,e,f,g,h,i=a.length,j=l.getValidClasses();i--;){for(b=a[i],c=b.attr("class").split(" "),f="",d=0;d<c.length;d++)e=c[d],h=!1,g=j["*"],g&&g[e]&&(h=!0),g=j[b.name],!h&&g&&g[e]&&(h=!0),h&&(f&&(f+=" "),f+=e);f.length||(f=null),b.attr("class",f)}})}}),g("m",["d","9"],function(a,b){var c=b.makeMap;return function(b){var d,e,f,g,h,i=[];return b=b||{},d=b.indent,e=c(b.indent_before||""),f=c(b.indent_after||""),g=a.getEncodeFunc(b.entity_encoding||"raw",b.enti
ties),h="html"==b.element_format,{start:function(a,b,c){var j,k,l,m;if(d&&e[a]&&i.length>0&&(m=i[i.length-1],m.length>0&&"\n"!==m&&i.push("\n")),i.push("<",a),b)for(j=0,k=b.length;j<k;j++)l=b[j],i.push(" ",l.name,'="',g(l.value,!0),'"');!c||h?i[i.length]=">":i[i.length]=" />",c&&d&&f[a]&&i.length>0&&(m=i[i.length-1],m.length>0&&"\n"!==m&&i.push("\n"))},end:function(a){var b;i.push("</",a,">"),d&&f[a]&&i.length>0&&(b=i[i.length-1],b.length>0&&"\n"!==b&&i.push("\n"))},text:function(a,b){a.length>0&&(i[i.length]=b?a:g(a))},cdata:function(a){i.push("<![CDATA[",a,"]]>")},comment:function(a){i.push("<!--",a,"-->")},pi:function(a
,b){b?i.push("<?",a," ",g(b),"?>"):i.push("<?",a,"?>"),d&&i.push("\n")},doctype:function(a){i.push("<!DOCTYPE",a,">",d?"\n":"")},reset:function(){i.length=0},getContent:function(){return i.join("").replace(/\n$/,"")}}}}),g("n",["m","j"],function(a,b){return function(c,d){var e=this,f=new a(c);c=c||{},c.validate=!("validate"in c)||c.validate,e.schema=d=d||new b,e.writer=f,e.serialize=function(a){function b(a){var c,h,i,j,k,l,m,n,o,p=e[a.type];if(p)p(a);else{if(c=a.name,h=a.shortEnded,i=a.attributes,g&&i&&i.length>1&&(l=[],l.map={},o=d.getElementRule(a.name))){for(m=0,n=o.attributesOrder.length;m<n;m++)j=o.attributesOrder[m],j in i.map&&(k=i.map[j],l.map[j]=k,l.push({name:j,value:k}));for(m=0,n=i.length;m<n;m++)j=i[m].name,j in l.map||(k=i.map[j],l.map[j]=k,l.pu
sh({name:j,value:k}));i=l}if(f.start(a.name,i,h),!h){if(a=a.firstChild)do b(a);while(a=a.next);f.end(c)}}}var e,g;return g=c.validate,e={3:function(a){f.text(a.value,a.raw)},8:function(a){f.comment(a.value)},7:function(a){f.pi(a.name,a.value)},10:function(a){f.doctype(a.value)},4:function(a){f.cdata(a.value)},11:function(a){if(a=a.firstChild)do b(a);while(a=a.next)}},f.reset(),1!=a.type||c.inner?e[11](a):b(a),f.getContent()}}}),g("o",["e","l","k","d","n","i","j","6","9","1l"],function(a,b,c,d,e,f,g,h,i,j){function k(a){function b(a){return a&&"br"===a.name}var c,d;c=a.lastChild,b(c)&&(d=c.prev,b(d)&&(c.remove(),d.remove()))}var l=i.each,m=i.trim,n=a.DOM;return function(a,f){function o(a){var b=new RegExp(["<span[^>]+data-mce-bogus[^>]+>[\u200b\ufeff]+<\\/span>","\\s?("+v.join("|")+')="[^&q
uot;]+"'].join("|"),"gi");return a=j.trim(a.replace(b,""))}function p(a){var b,d,e,g,h,i=a,j=/<(\w+) [^>]*data-mce-bogus="all"[^>]*>/g,k=f.schema;for(i=o(i),h=k.getShortEndedElements();g=j.exec(i);)d=j.lastIndex,e=g[0].length,b=h[g[1]]?d:c.findEndTag(k,i,d),i=i.substring(0,d-e)+i.substring(b),j.lastIndex=d-e;return i}function q(){return p(f.getBody().innerHTML)}function r(a){i.inArray(v,a)===-1&&(u.addAttributeFilter(a,function(a,b){for(var c=a.length;c--;)a[c].attr(b,null)}),v.push(a))}var s,t,u,v=["data-mce-selected"];return f&&(s=f.dom,t=f.schema),s=s||n,t=t||new g(a),a.entity_encoding=a.entity_encoding||"named",a.remove_trailing_brs=!("remove_trailing_brs"in a)||a.remove_trailing_brs,u=new b(a,t),u.addAttributeFilter("data-mce-tabindex",function(a,b){for(var c,d=a.length;d--;)c=a[d],c.attr("tabindex",c.attributes.map["data-mce-tabindex"]),c.attr(b,
null)}),u.addAttributeFilter("src,href,style",function(b,c){for(var d,e,f,g=b.length,h="data-mce-"+c,i=a.url_converter,j=a.url_converter_scope;g--;)d=b[g],e=d.attributes.map[h],e!==f?(d.attr(c,e.length>0?e:null),d.attr(h,null)):(e=d.attributes.map[c],"style"===c?e=s.serializeStyle(s.parseStyle(e),d.name):i&&(e=i.call(j,e,c,d.name)),d.attr(c,e.length>0?e:null))}),u.addAttributeFilter("class",function(a){for(var b,c,d=a.length;d--;)b=a[d],c=b.attr("class"),c&&(c=b.attr("class").replace(/(?:^|\s)mce-item-\w+(?!\S)/g,""),b.attr("class",c.length>0?c:null))}),u.addAttributeFilter("data-mce-type",function(a,b,c){for(var d,e=a.length;e--;)d=a[e],"bookmark"!==d.attributes.map["data-mce-type"]||c.cleanup||d.remove()}),u.addNodeFilter("noscript",function(a){for(var b,c=a.length;c--;)b=a[c].firstChild,b&&(b.value=d.decode(b.value))}),u.addNodeF
ilter("script,style",function(a,b){function c(a){return a.replace(/(<!--\[CDATA\[|\]\]-->)/g,"\n").replace(/^[\r\n]*|[\r\n]*$/g,"").replace(/^\s*((<!--)?(\s*\/\/)?\s*<!\[CDATA\[|(<!--\s*)?\/\*\s*<!\[CDATA\[\s*\*\/|(\/\/)?\s*<!--|\/\*\s*<!--\s*\*\/)\s*[\r\n]*/gi,"").replace(/\s*(\/\*\s*\]\]>\s*\*\/(-->)?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g,"")}for(var d,e,f,g=a.length;g--;)d=a[g],e=d.firstChild?d.firstChild.value:"","script"===b?(f=d.attr("type"),f&&d.attr("type","mce-no/type"==f?null:f.replace(/^mce\-/,"")),e.length>0&&(d.firstChild.value="// <![CDATA[\n"+c(e)+"\n// ]]>")):e.length>0&&(d.firstChild.value="<!--\n"+c(e)+"\n-->")}),u.addNodeFilter("#comment",function(a){for(var b,c=a.length;c--;)b=a[
c],0===b.value.indexOf("[CDATA[")?(b.name="#cdata",b.type=4,b.value=b.value.replace(/^\[CDATA\[|\]\]$/g,"")):0===b.value.indexOf("mce:protected ")&&(b.name="#text",b.type=3,b.raw=!0,b.value=unescape(b.value).substr(14))}),u.addNodeFilter("xml:namespace,input",function(a,b){for(var c,d=a.length;d--;)c=a[d],7===c.type?c.remove():1===c.type&&("input"!==b||"type"in c.attributes.map||c.attr("type","text"))}),u.addAttributeFilter("data-mce-src,data-mce-href,data-mce-style,data-mce-selected,data-mce-expando,data-mce-type,data-mce-resize",function(a,b){for(var c=a.length;c--;)a[c].attr(b,null)}),{schema:t,addNodeFilter:u.addNodeFilter,addAttributeFilter:u.addAttributeFilter,serialize:function(b,c){var d,f,g,i,n,o,p=this;return h.ie&&s.select("script,style,select,map").length>0?(n=b.innerHTML,b=b.cloneNode(!1),s.setHTML(b,n)):b=b.cloneNode(!0),d=d
ocument.implementation,d.createHTMLDocument&&(f=d.createHTMLDocument(""),l("BODY"==b.nodeName?b.childNodes:[b],function(a){f.body.appendChild(f.importNode(a,!0))}),b="BODY"!=b.nodeName?f.body.firstChild:f.body,g=s.doc,s.doc=f),c=c||{},c.format=c.format||"html",c.selection&&(c.forced_root_block=""),c.no_events||(c.node=b,p.onPreProcess(c)),o=u.parse(m(c.getInner?b.innerHTML:s.getOuterHTML(b)),c),k(o),i=new e(a,t),c.content=i.serialize(o),c.cleanup||(c.content=j.trim(c.content),c.content=c.content.replace(/\uFEFF/g,"")),c.no_events||p.onPostProcess(c),g&&(s.doc=g),c.node=null,c.content},addRules:function(a){t.addValidElements(a)},setRules:function(a){t.setValidElements(a)},onPreProcess:function(a){f&&f.fire("PreProcess",a)},onPostProcess:function(a){f&&f.fire("PostProcess",a)},addTempAttr:r,trimHtml:o,getTrimmedContent:q,trimContent:p}}}),g("p",["6&quo
t;],function(a){return{BACKSPACE:8,DELETE:46,DOWN:40,ENTER:13,LEFT:37,RIGHT:39,SPACEBAR:32,TAB:9,UP:38,modifierPressed:function(a){return a.shiftKey||a.ctrlKey||a.altKey||this.metaKeyPressed(a)},metaKeyPressed:function(b){return a.mac?b.metaKey:b.ctrlKey&&!b.altKey}}}),g("q",["p","9","5","6","1j"],function(a,b,c,d,e){function f(a,b){for(;b&&b!=a;){if(h(b)||g(b))return b;b=b.parentNode}return null}var g=e.isContentEditableFalse,h=e.isContentEditableTrue;return function(e,h){function i(a){var b=h.settings.object_resizing;return b!==!1&&!d.iOS&&("string"!=typeof b&&(b="table,img,div"),"false"!==a.getAttribute("data-mce-resize")&&(a!=h.getBody()&&h.dom.is(a,b)))}function j(b){var c,d,e,f,g;c=b.screenX-F,d=b.screenY-G,N=c*D[2]+J,O=d*D[3]+K,N=N<5?5:N,O=O<5?5:O,e="IMG"==z.nodeName&&h.settings.resize_img_proportio
nal!==!1?!a.modifierPressed(b):a.modifierPressed(b)||"IMG"==z.nodeName&&D[2]*D[3]!==0,e&&(W(c)>W(d)?(O=X(N*L),N=X(O/L)):(N=X(O/L),O=X(N*L))),R.setStyles(A,{width:N,height:O}),f=D.startPos.x+c,g=D.startPos.y+d,f=f>0?f:0,g=g>0?g:0,R.setStyles(B,{left:f,top:g,display:"block"}),B.innerHTML=N+" × "+O,D[2]<0&&A.clientWidth<=N&&R.setStyle(A,"left",H+(J-N)),D[3]<0&&A.clientHeight<=O&&R.setStyle(A,"top",I+(K-O)),c=Y.scrollWidth-P,d=Y.scrollHeight-Q,c+d!==0&&R.setStyles(B,{left:f-c,top:g-d}),M||(h.fire("ObjectResizeStart",{target:z,width:J,height:K}),M=!0)}function k(){function a(a,b){b&&(z.style[a]||!h.schema.isValid(z.nodeName.toLowerCase(),a)?R.setStyle(z,a,b):R.setAttrib(z,a,b))}M=!1,a("width",N),a("height",O),R.unbind(T,"mousemove",j),R.unbind(T,"mouseup",k),U!=T&&(R.unbind(U,"mousem
ove",j),R.unbind(U,"mouseup",k)),R.remove(A),R.remove(B),V&&"TABLE"!=z.nodeName||l(z),h.fire("ObjectResized",{target:z,width:N,height:O}),R.setAttrib(z,"style",R.getAttrib(z,"style")),h.nodeChanged()}function l(a,b,c){var e,f,g,l,n;m(),v(),e=R.getPos(a,Y),H=e.x,I=e.y,n=a.getBoundingClientRect(),f=n.width||n.right-n.left,g=n.height||n.bottom-n.top,z!=a&&(u(),z=a,N=O=0),l=h.fire("ObjectSelected",{target:a}),i(a)&&!l.isDefaultPrevented()?S(C,function(a,e){function h(b){F=b.screenX,G=b.screenY,J=z.clientWidth,K=z.clientHeight,L=K/J,D=a,a.startPos={x:f*a[0]+H,y:g*a[1]+I},P=Y.scrollWidth,Q=Y.scrollHeight,A=z.cloneNode(!0),R.addClass(A,"mce-clonedresizable"),R.setAttrib(A,"data-mce-bogus","all"),A.contentEditable=!1,A.unSelectabe=!0,R.setStyles(A,{left:H,top:I,margin:0}),A.removeAttribute("data-mce-selected"),Y.appendChild(A),R.bind(T,"mousemove",j),R.b
ind(T,"mouseup",k),U!=T&&(R.bind(U,"mousemove",j),R.bind(U,"mouseup",k)),B=R.add(Y,"div",{"class":"mce-resize-helper","data-mce-bogus":"all"},J+" × "+K)}var i;return b?void(e==b&&h(c)):(i=R.get("mceResizeHandle"+e),i&&R.remove(i),i=R.add(Y,"div",{id:"mceResizeHandle"+e,"data-mce-bogus":"all","class":"mce-resizehandle",unselectable:!0,style:"cursor:"+e+"-resize; margin:0; padding:0"}),d.ie&&(i.contentEditable=!1),R.bind(i,"mousedown",function(a){a.stopImmediatePropagation(),a.preventDefault(),h(a)}),a.elm=i,void R.setStyles(i,{left:f*a[0]+H-i.offsetWidth/2,top:g*a[1]+I-i.offsetHeight/2}))}):m(),z.setAttribute("data-mce-selected","1")}function m(){var a,b;v(),z&&z.removeAttribute("data-mce-selected");for(a in C)b=R.get(
"mceResizeHandle"+a),b&&(R.unbind(b),R.remove(b))}function n(a){function b(a,b){if(a)do if(a===b)return!0;while(a=a.parentNode)}var c,d;if(!M&&!h.removed)return S(R.select("img[data-mce-selected],hr[data-mce-selected]"),function(a){a.removeAttribute("data-mce-selected")}),d="mousedown"==a.type?a.target:e.getNode(),d=R.$(d).closest(V?"table":"table,img,hr")[0],b(d,Y)&&(w(),c=e.getStart(!0),b(c,d)&&b(e.getEnd(!0),d)&&(!V||d!=c&&"IMG"!==c.nodeName))?void l(d):void m()}function o(a,b,c){a&&a.attachEvent&&a.attachEvent("on"+b,c)}function p(a,b,c){a&&a.detachEvent&&a.detachEvent("on"+b,c)}function q(a){var b,c,d,e,f,g,i,j=a.srcElement;b=j.getBoundingClientRect(),g=E.clientX-b.left,i=E.clientY-b.top;for(c in C)if(d=C[c],e=j.offsetWidth*d[0],f=j.offsetHeight*d[1],W(e-g)<8&&W(f-i)<8){D=d;break}M=!0,h.fire("
;ObjectResizeStart",{target:z,width:z.clientWidth,height:z.clientHeight}),h.getDoc().selection.empty(),l(j,c,E)}function r(a){a.preventDefault?a.preventDefault():a.returnValue=!1}function s(a){return g(f(h.getBody(),a))}function t(a){var b=a.srcElement;if(s(b))return void r(a);if(b!=z){if(h.fire("ObjectSelected",{target:b}),u(),0===b.id.indexOf("mceResizeHandle"))return void(a.returnValue=!1);"IMG"!=b.nodeName&&"TABLE"!=b.nodeName||(m(),z=b,o(b,"resizestart",q))}}function u(){p(z,"resizestart",q)}function v(){for(var a in C){var b=C[a];b.elm&&(R.unbind(b.elm),delete b.elm)}}function w(){try{h.getDoc().execCommand("enableObjectResizing",!1,!1)}catch(a){}}function x(a){var b;if(V){b=T.body.createControlRange();try{return b.addElement(a),b.select(),!0}catch(a){}}}function y(){z=A=null,V&&(u(),p(Y,"controlselect",t))}var z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R=h.dom,S=b.each,T=h.ge
tDoc(),U=document,V=d.ie&&d.ie<11,W=Math.abs,X=Math.round,Y=h.getBody();C={nw:[0,0,-1,-1],ne:[1,0,1,-1],se:[1,1,1,1],sw:[0,1,-1,1]};var Z=".mce-content-body";return h.contentStyles.push(Z+" div.mce-resizehandle {position: absolute;border: 1px solid black;box-sizing: box-sizing;background: #FFF;width: 7px;height: 7px;z-index: 10000}"+Z+" .mce-resizehandle:hover {background: #000}"+Z+" img[data-mce-selected],"+Z+" hr[data-mce-selected] {outline: 1px solid black;resize: none}"+Z+" .mce-clonedresizable {position: absolute;"+(d.gecko?"":"outline: 1px dashed black;")+"opacity: .5;filter: alpha(opacity=50);z-index: 10000}"+Z+" .mce-resize-helper {background: #555;background: rgba(0,0,0,0.75);border-radius: 3px;border: 1px;color: white;display: none;font-family: sans-serif;font-size: 12px;white-space: nowrap;line-height: 14px;margin: 5px 10px;padding: 5px;position: absolute;z-index: 100
01}"),h.on("init",function(){V?(h.on("ObjectResized",function(a){"TABLE"!=a.target.nodeName&&(m(),x(a.target))}),o(Y,"controlselect",t),h.on("mousedown",function(a){E=a})):(w(),d.ie>=11&&(h.on("mousedown click",function(a){var b=a.target,c=b.nodeName;M||!/^(TABLE|IMG|HR)$/.test(c)||s(b)||(h.selection.select(b,"TABLE"==c),"mousedown"==a.type&&h.nodeChanged())}),h.dom.bind(Y,"mscontrolselect",function(a){function b(a){c.setEditorTimeout(h,function(){
+h.selection.select(a)})}return s(a.target)?(a.preventDefault(),void b(a.target)):void(/^(TABLE|IMG|HR)$/.test(a.target.nodeName)&&(a.preventDefault(),"IMG"==a.target.tagName&&b(a.target)))})));var a=c.throttle(function(a){h.composing||n(a)});h.on("nodechange ResizeEditor ResizeWindow drop",a),h.on("keyup compositionend",function(b){z&&"TABLE"==z.nodeName&&a(b)}),h.on("hide blur",m)}),h.on("remove",v),{isResizable:i,showResizeRect:l,hideResizeRect:m,updateResizeRect:n,controlSelect:x,destroy:y}}}),g("1r",[],function(){function a(a){return function(){return a}}function b(a){return function(b){return!a(b)}}function c(a,b){return function(c){return a(b(c))}}function d(){var a=h.call(arguments);return function(b){for(var c=0;c<a.length;c++)if(a[c](b))return!0;return!1}}function e(){var a=h.call(arguments);return function(b){for(var c=0;c<a.length;c++)if(!a[c](b))return!1;return!0}}
function f(a){var b=h.call(arguments);return b.length-1>=a.length?a.apply(this,b.slice(1)):function(){var a=b.concat([].slice.call(arguments));return f.apply(this,a)}}function g(){}var h=[].slice;return{constant:a,negate:b,and:e,or:d,curry:f,compose:c,noop:g}}),g("3w",["1j","1g","1k"],function(a,b,c){function d(a){return!p(a)&&(l(a)?!m(a.parentNode):n(a)||k(a)||o(a)||j(a))}function e(a,b){for(a=a.parentNode;a&&a!=b;a=a.parentNode){if(j(a))return!1;if(i(a))return!0}return!0}function f(a){return!!j(a)&&b.reduce(a.getElementsByTagName("*"),function(a,b){return a||i(b)},!1)!==!0}function g(a){return n(a)||f(a)}function h(a,b){return d(a)&&e(a,b)}var i=a.isContentEditableTrue,j=a.isContentEditableFalse,k=a.isBr,l=a.isText,m=a.matchNodeNames("script style textarea"),n=a.matchNodeNames("img input textarea hr iframe video audio object"),o=a.matchNodeNames("table"),p=c.isCaretCo
ntainer;return{isCaretCandidate:d,isInEditable:e,isAtomic:g,isEditableCaretCandidate:h}}),g("3x",[],function(){function a(a){return a?{left:k(a.left),top:k(a.top),bottom:k(a.bottom),right:k(a.right),width:k(a.width),height:k(a.height)}:{left:0,top:0,bottom:0,right:0,width:0,height:0}}function b(b,c){return b=a(b),c?b.right=b.left:(b.left=b.left+b.width,b.right=b.left),b.width=0,b}function c(a,b){return a.left===b.left&&a.top===b.top&&a.bottom===b.bottom&&a.right===b.right}function d(a,b,c){return a>=0&&a<=Math.min(b.height,c.height)/2}function e(a,b){return a.bottom-a.height/2<b.top||!(a.top>b.bottom)&&d(b.top-a.bottom,a,b)}function f(a,b){return a.top>b.bottom||!(a.bottom<b.top)&&d(b.bottom-a.top,a,b)}function g(a,b){return a.left<b.left}function h(a,b){return a.right>b.right}function i(a,b){return e(a,b)?-1:f(a,b)?1:g(a,b)?-1:h(a,b)?1:0}function j(a,b,c){return b>=a.left&&b<=a.right&
;&c>=a.top&&c<=a.bottom}var k=Math.round;return{clone:a,collapse:b,isEqual:c,isAbove:e,isBelow:f,isLeft:g,isRight:h,compare:i,containsXY:j}}),g("3y",[],function(){function a(a){return"string"==typeof a&&a.charCodeAt(0)>=768&&b.test(a)}var b=new RegExp("[\u0300-\u036f\u0483-\u0487\u0488-\u0489\u0591-\u05bd\u05bf\u05c1-\u05c2\u05c4-\u05c5\u05c7\u0610-\u061a\u064b-\u065f\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7-\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08e3-\u0902\u093a\u093c\u0941-\u0948\u094d\u0951-\u0957\u0962-\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2-\u09e3\u0a01-\u0a02\u0a3c\u0a41-\u0a42\u0a47-\u0a48\u0a4b-\u0a4d\u0a51\u0a70-\u0a71\u0a75\u0a81-\u0a82\u0abc\u0ac1-\u0ac5\u0ac7-\u0ac8\u0acd\u0ae2-\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62-\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c00\u0c3e-\u0c40\u0c46-
\u0c48\u0c4a-\u0c4d\u0c55-\u0c56\u0c62-\u0c63\u0c81\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc-\u0ccd\u0cd5-\u0cd6\u0ce2-\u0ce3\u0d01\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62-\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb-\u0ebc\u0ec8-\u0ecd\u0f18-\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039-\u103a\u103d-\u103e\u1058-\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085-\u1086\u108d\u109d\u135d-\u135f\u1712-\u1714\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17b4-\u17b5\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193b\u1a17-\u1a18\u1a1b\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1ab0-\u1abd\u1abe\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80-\u1b81\u1ba2-\u1ba5\u1ba8-\u1ba9\u1bab-\u1bad\u1be6\u1be8-\u1be9\u1bed\u1bef-\u1bf1\u1c2c-\u1c33\u1c36-\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u
1ced\u1cf4\u1cf8-\u1cf9\u1dc0-\u1df5\u1dfc-\u1dff\u200c-\u200d\u20d0-\u20dc\u20dd-\u20e0\u20e1\u20e2-\u20e4\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302d\u302e-\u302f\u3099-\u309a\ua66f\ua670-\ua672\ua674-\ua67d\ua69e-\ua69f\ua6f0-\ua6f1\ua802\ua806\ua80b\ua825-\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\ua9e5\uaa29-\uaa2e\uaa31-\uaa32\uaa35-\uaa36\uaa43\uaa4c\uaa7c\uaab0\uaab2-\uaab4\uaab7-\uaab8\uaabe-\uaabf\uaac1\uaaec-\uaaed\uaaf6\uabe5\uabe8\uabed\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\uff9e-\uff9f]");return{isExtendingChar:a}}),g("1n",["1r","1j","e","h","3w","3x","3y"],function(a,b,c,d,e,f,g){function h(a){return"createRange"in a?a.createRange():c.DOM.createRng()}function i(a){return a&&/[\r\n\t ]/.test(a)}function j(a){var b,c=a.startContainer,d=a.startOffset;return!!(i(a.toString())&&r(c.parentNode)&&(b=c.da
ta,i(b[d-1])||i(b[d+1])))}function k(a){function b(a){var b,c=a.ownerDocument,d=h(c),e=c.createTextNode("\xa0"),g=a.parentNode;return g.insertBefore(e,a),d.setStart(e,0),d.setEnd(e,1),b=f.clone(d.getBoundingClientRect()),g.removeChild(e),b}function c(a){var c,d;return d=a.getClientRects(),c=d.length>0?f.clone(d[0]):f.clone(a.getBoundingClientRect()),t(a)&&0===c.left?b(a):c}function d(a,b){return a=f.collapse(a,b),a.width=1,a.right=a.left+1,a}function e(a){0!==a.height&&(n.length>0&&f.isEqual(a,n[n.length-1])||n.push(a))}function i(a,b){var f=h(a.ownerDocument);if(b<a.data.length){if(g.isExtendingChar(a.data[b]))return n;if(g.isExtendingChar(a.data[b-1])&&(f.setStart(a,b),f.setEnd(a,b+1),!j(f)))return e(d(c(f),!1)),n}b>0&&(f.setStart(a,b-1),f.setEnd(a,b),j(f)||e(d(c(f),!1))),b<a.data.length&&(f.setStart(a,b),f.setEnd(a,b+1),j(f)||e(d(c(f),!0)))}var k,l,n=[];if(s(a.container()))return i(a.container(),a.offset()),
n;if(m(a.container()))if(a.isAtEnd())l=v(a.container(),a.offset()),s(l)&&i(l,l.data.length),q(l)&&!t(l)&&e(d(c(l),!1));else{if(l=v(a.container(),a.offset()),s(l)&&i(l,0),q(l)&&a.isAtEnd())return e(d(c(l),!1)),n;k=v(a.container(),a.offset()-1),q(k)&&!t(k)&&(o(k)||o(l)||!q(l))&&e(d(c(k),!1)),q(l)&&e(d(c(l),!0))}return n}function l(b,c,d){function e(){return s(b)?0===c:0===c}function f(){return s(b)?c>=b.data.length:c>=b.childNodes.length}function g(){var a;return a=h(b.ownerDocument),a.setStart(b,c),a.setEnd(b,c),a}function i(){return d||(d=k(new l(b,c))),d}function j(){return i().length>0}function m(a){return a&&b===a.container()&&c===a.offset()}function n(a){return v(b,a?c-1:c)}return{container:a.constant(b),offset:a.constant(c),toRange:g,getClientRects:i,isVisible:j,isAtStart:e,isAtEnd:f,isEqual:m,getNode:n}}var m=b.isElement,n=e.isCaretCandidate,o=b.matchStyleValues("display"
,"block table"),p=b.matchStyleValues("float","left right"),q=a.and(m,n,a.negate(p)),r=a.negate(b.matchStyleValues("white-space","pre pre-line pre-wrap")),s=b.isText,t=b.isBr,u=c.nodeIndex,v=d.getNode;return l.fromRangeStart=function(a){return new l(a.startContainer,a.startOffset)},l.fromRangeEnd=function(a){return new l(a.endContainer,a.endOffset)},l.after=function(a){return new l(a.parentNode,u(a)+1)},l.before=function(a){return new l(a.parentNode,u(a))},l.isAtStart=function(a){return!!a&&a.isAtStart()},l.isAtEnd=function(a){return!!a&&a.isAtEnd()},l.isTextPosition=function(a){return!!a&&b.isText(a.container())},l}),g("1m",["1j","e","1r","1g","1n"],function(a,b,c,d,e){function f(a){var b=a.parentNode;return r(b)?f(b):b}function g(a){return a?d.reduce(a.childNodes,function(a,b){return r(b)&&"BR"!=b.nodeName?a=a.concat(g(b)):a.push(b)
,a},[]):[]}function h(a,b){for(;(a=a.previousSibling)&&q(a);)b+=a.data.length;return b}function i(a){return function(b){return a===b}}function j(b){var c,e,h;return c=g(f(b)),e=d.findIndex(c,i(b),b),c=c.slice(0,e+1),h=d.reduce(c,function(a,b,d){return q(b)&&q(c[d-1])&&a++,a},0),c=d.filter(c,a.matchNodeNames(b.nodeName)),e=d.findIndex(c,i(b),b),e-h}function k(a){var b;return b=q(a)?"text()":a.nodeName.toLowerCase(),b+"["+j(a)+"]"}function l(a,b,c){var d=[];for(b=b.parentNode;b!=a&&(!c||!c(b));b=b.parentNode)d.push(b);return d}function m(b,e){var f,g,i,j,m,n=[];return f=e.container(),g=e.offset(),q(f)?i=h(f,g):(j=f.childNodes,g>=j.length?(i="after",g=j.length-1):i="before",f=j[g]),n.push(k(f)),m=l(b,f),m=d.filter(m,c.negate(a.isBogus)),n=n.concat(d.map(m,function(a){return k(a)})),n.reverse().join("/")+","+i}function n(b,c,e){var f=g(b);return f=d.filter(f,function(a,b){return!q(a)
||!q(f[b-1])}),f=d.filter(f,a.matchNodeNames(c)),f[e]}function o(a,b){for(var c,d=a,f=0;q(d);){if(c=d.data.length,b>=f&&b<=f+c){a=d,b-=f;break}if(!q(d.nextSibling)){a=d,b=c;break}f+=c,d=d.nextSibling}return b>a.data.length&&(b=a.data.length),new e(a,b)}function p(a,b){var c,f,g;return b?(c=b.split(","),b=c[0].split("/"),g=c.length>1?c[1]:"before",f=d.reduce(b,function(a,b){return(b=/([\w\-\(\)]+)\[([0-9]+)\]/.exec(b))?("text()"===b[1]&&(b[1]="#text"),n(a,b[1],parseInt(b[2],10))):null},a),f?q(f)?o(f,parseInt(g,10)):(g="after"===g?s(f)+1:s(f),new e(f.parentNode,g)):null):null}var q=a.isText,r=a.isBogus,s=b.nodeIndex;return{create:m,resolve:p}}),g("r",["1m","1k","1n","1j","h","6","1l","9"],function(a,b,c,d,e,f,g,h){function i(g){var i=g.dom;this.getBookmark=function(f,l){function m(a,b){var c=0;return h
.each(i.select(a),function(a){if("all"!==a.getAttribute("data-mce-bogus"))return a!=b&&void c++}),c}function n(a){function b(b){var c,d,e,f=b?"start":"end";c=a[f+"Container"],d=a[f+"Offset"],1==c.nodeType&&"TR"==c.nodeName&&(e=c.childNodes,c=e[Math.min(b?d:d-1,e.length-1)],c&&(d=b?0:c.childNodes.length,a["set"+(b?"Start":"End")](c,d)))}return b(!0),b(),a}function o(a){function b(a,b){var d,e=a[b?"startContainer":"endContainer"],f=a[b?"startOffset":"endOffset"],g=[],h=0;for(3===e.nodeType?g.push(l?k(e,f):f):(d=e.childNodes,f>=d.length&&d.length&&(h=1,f=Math.max(0,d.length-1)),g.push(i.nodeIndex(d[f],l)+h));e&&e!=c;e=e.parentNode)g.push(i.nodeIndex(e,l));return g}var c=i.getRoot(),d={};return d.start=b(a,!0),g.isCollapsed()||(d.end=b(a)),d}function p(a){function c(a,c){var f;if(d.isElement
(a)&&(a=e.getNode(a,c),j(a)))return a;if(b.isCaretContainer(a)){if(d.isText(a)&&b.isCaretContainerBlock(a)&&(a=a.parentNode),f=a.previousSibling,j(f))return f;if(f=a.nextSibling,j(f))return f}}return c(a.startContainer,a.startOffset)||c(a.endContainer,a.endOffset)}var q,r,s,t,u,v,w,x="";if(2==f)return v=g.getNode(),u=v?v.nodeName:null,q=g.getRng(),j(v)||"IMG"==u?{name:u,index:m(u,v)}:g.tridentSel?g.tridentSel.getBookmark(f):(v=p(q),v?(u=v.tagName,{name:u,index:m(u,v)}):o(q));if(3==f)return q=g.getRng(),{start:a.create(i.getRoot(),c.fromRangeStart(q)),end:a.create(i.getRoot(),c.fromRangeEnd(q))};if(f)return{rng:g.getRng()};if(q=g.getRng(),s=i.uniqueId(),t=g.isCollapsed(),w="overflow:hidden;line-height:0px",q.duplicate||q.item){if(q.item)return v=q.item(0),u=v.nodeName,{name:u,index:m(u,v)};r=q.duplicate();try{q.collapse(),q.pasteHTML('<span data-mce-type="bookmark" id="'+s+'_start" style="'+
w+'">'+x+"</span>"),t||(r.collapse(!1),q.moveToElementText(r.parentElement()),0===q.compareEndPoints("StartToEnd",r)&&r.move("character",-1),r.pasteHTML('<span data-mce-type="bookmark" id="'+s+'_end" style="'+w+'">'+x+"</span>"))}catch(a){return null}}else{if(v=g.getNode(),u=v.nodeName,"IMG"==u)return{name:u,index:m(u,v)};r=n(q.cloneRange()),t||(r.collapse(!1),r.insertNode(i.create("span",{"data-mce-type":"bookmark",id:s+"_end",style:w},x))),q=n(q),q.collapse(!0),q.insertNode(i.create("span",{"data-mce-type":"bookmark",id:s+"_start",style:w},x))}return g.moveToBookmark({id:s,keep:1}),{id:s}},this.moveToBookmark=function(b){function c(a){var c,d,e,f,g=b[a?"start":"end"];if(g){for(e=g[0],d=l,c=g.length-1;c>=1;c--){if(f=d.childNodes,g[c]>f.length-1)return;d=f[g[c]]}3===
d.nodeType&&(e=Math.min(g[0],d.nodeValue.length)),1===d.nodeType&&(e=Math.min(g[0],d.childNodes.length)),a?k.setStart(d,e):k.setEnd(d,e)}return!0}function d(a){var c,d,e,g,j=i.get(b.id+"_"+a),k=b.keep;if(j&&(c=j.parentNode,"start"==a?(k?(c=j.firstChild,d=1):d=i.nodeIndex(j),m=n=c,o=p=d):(k?(c=j.firstChild,d=1):d=i.nodeIndex(j),n=c,p=d),!k)){for(g=j.previousSibling,e=j.nextSibling,h.each(h.grep(j.childNodes),function(a){3==a.nodeType&&(a.nodeValue=a.nodeValue.replace(/\uFEFF/g,""))});j=i.get(b.id+"_"+a);)i.remove(j,1);g&&e&&g.nodeType==e.nodeType&&3==g.nodeType&&!f.opera&&(d=g.nodeValue.length,g.appendData(e.nodeValue),i.remove(e),"start"==a?(m=n=g,o=p=d):(n=g,p=d))}}function e(a){return!i.isBlock(a)||a.innerHTML||f.ie||(a.innerHTML='<br data-mce-bogus="1" />'),a}function j(){var c,d;return c=i.createRng(),d=a.resolve(i.getRoot(),b.start),c.setStar
t(d.container(),d.offset()),d=a.resolve(i.getRoot(),b.end),c.setEnd(d.container(),d.offset()),c}var k,l,m,n,o,p;if(b)if(h.isArray(b.start)){if(k=i.createRng(),l=i.getRoot(),g.tridentSel)return g.tridentSel.moveToBookmark(b);c(!0)&&c()&&g.setRng(k)}else"string"==typeof b.start?g.setRng(j(b)):b.id?(d("start"),d("end"),m&&(k=i.createRng(),k.setStart(e(m),o),k.setEnd(e(n),p),g.setRng(k))):b.name?g.select(i.select(b.name)[b.index]):b.rng&&g.setRng(b.rng)}}var j=d.isContentEditableFalse,k=function(a,b){var c,d;for(d=g.trim(a.data.slice(0,b)).length,c=a.previousSibling;c&&3===c.nodeType;c=c.previousSibling)d+=g.trim(c.data).length;return d};return i.isBookmarkNode=function(a){return a&&"SPAN"===a.tagName&&"bookmark"===a.getAttribute("data-mce-type")},i}),g("1o",["1j"],function(a){var b=function(a){for(var b=0,c=0,d=a;d&&d.nodeType;)b+=d.offsetLeft|
|0,c+=d.offsetTop||0,d=d.offsetParent;return{x:b,y:c}},c=function(a,b,c){var d={elm:b,alignToTop:c};return a.fire("scrollIntoView",d),d.isDefaultPrevented()},d=function(d,e,f){var g,h,i,j,k=d.dom,l=k.getRoot(),m=0;if(!c(d,e,f)&&a.isElement(e)){if(f===!1&&(m=e.offsetHeight),"BODY"!==l.nodeName){var n=d.selection.getScrollContainer();if(n)return g=b(e).y-b(n).y+m,j=n.clientHeight,i=n.scrollTop,void((g<i||g+25>i+j)&&(n.scrollTop=g<i?g:g-j+25))}h=k.getViewPort(d.getWin()),g=k.getPos(e).y+m,i=h.y,j=h.h,(g<h.y||g+25>i+j)&&d.getWin().scrollTo(0,g<i?g:g-j+25)}};return{scrollIntoView:d}}),g("1p",[],function(){function a(a){function b(b,c){var d,e,f,g,h,i,j,k,l=0,m=-1;if(d=b.duplicate(),d.collapse(c),k=d.parentElement(),k.ownerDocument===a.dom.doc){for(;"false"===k.contentEditable;)k=k.parentNode;if(!k.hasChildNodes())return{node:k,inside:1};for(g=k.children,e=g.length-1;l<=e;)if(j=Math.floor((l+e)/2)
,h=g[j],d.moveToElementText(h),m=d.compareEndPoints(c?"StartToStart":"EndToEnd",b),m>0)e=j-1;else{if(!(m<0))return{node:h};l=j+1}if(m<0)for(h?d.collapse(!1):(d.moveToElementText(k),d.collapse(!0),h=k,f=!0),i=0;0!==d.compareEndPoints(c?"StartToStart":"StartToEnd",b)&&0!==d.move("character",1)&&k==d.parentElement();)i++;else for(d.collapse(!0),i=0;0!==d.compareEndPoints(c?"StartToStart":"StartToEnd",b)&&0!==d.move("character",-1)&&k==d.parentElement();)i++;return{node:h,position:m,offset:i,inside:f}}}function c(){function c(a){var c,d,e,f,g,h=b(k,a),i=0;if(c=h.node,d=h.offset,h.inside&&!c.hasChildNodes())return void l[a?"setStart":"setEnd"](c,0);if(d===f)return void l[a?"setStartBefore":"setEndAfter"](c);if(h.position<0){if(e=h.inside?c.firstChild:c.nextSibling,!e)return void l[a?"setStartAfter":"setE
ndAfter"](c);if(!d)return void(3==e.nodeType?l[a?"setStart":"setEnd"](e,0):l[a?"setStartBefore":"setEndBefore"](e));for(;e;){if(3==e.nodeType&&(g=e.nodeValue,i+=g.length,i>=d)){c=e,i-=d,i=g.length-i;break}e=e.nextSibling}}else{if(e=c.previousSibling,!e)return l[a?"setStartBefore":"setEndBefore"](c);if(!d)return void(3==c.nodeType?l[a?"setStart":"setEnd"](e,c.nodeValue.length):l[a?"setStartAfter":"setEndAfter"](e));for(;e;){if(3==e.nodeType&&(i+=e.nodeValue.length,i>=d)){c=e,i-=d;break}e=e.previousSibling}}l[a?"setStart":"setEnd"](c,i)}var f,g,h,i,j,k=a.getRng(),l=e.createRng();if(f=k.item?k.item(0):k.parentElement(),f.ownerDocument!=e.doc)return l;if(g=a.isCollapsed(),k.item)return l.setStart(f.parentNode,e.nodeIndex(f)),l.setEnd(l.startContainer,l.startOffset+1),l;try{c(!0),g||c()}catch(b){if(b.number!=-2147024809)throw b;j=d.getBookmark
(2),h=k.duplicate(),h.collapse(!0),f=h.parentElement(),g||(h=k.duplicate(),h.collapse(!1),i=h.parentElement(),i.innerHTML=i.innerHTML),f.innerHTML=f.innerHTML,d.moveToBookmark(j),k=a.getRng(),c(!0),g||c()}return l}var d=this,e=a.dom,f=!1;this.getBookmark=function(c){function d(a){var b,c,d,f,g=[];for(b=a.parentNode,c=e.getRoot().parentNode;b!=c&&9!==b.nodeType;){for(d=b.children,f=d.length;f--;)if(a===d[f]){g.push(f);break}a=b,b=b.parentNode}return g}function f(a){var c;if(c=b(g,a))return{position:c.position,offset:c.offset,indexes:d(c.node),inside:c.inside}}var g=a.getRng(),h={};return 2===c&&(g.item?h.start={ctrl:!0,indexes:d(g.item(0))}:(h.start=f(!0),a.isCollapsed()||(h.end=f()))),h},this.moveToBookmark=function(a){function b(a){var b,c,d,f;for(b=e.getRoot(),c=a.length-1;c>=0;c--)f=b.children,d=a[c],d<=f.length-1&&(b=f[d]);return b}function c(c){var e,g,h,i,j=a[c?"start":"end"];j&&(e=j.position>0,g=f.createTextRange(),
g.moveToElementText(b(j.indexes)),i=j.offset,i!==h?(g.collapse(j.inside||e),g.moveStart("character",e?-i:i)):g.collapse(c),d.setEndPoint(c?"StartToStart":"EndToStart",g),c&&d.collapse(!0))}var d,f=e.doc.body;a.start&&(a.start.ctrl?(d=f.createControlRange(),d.addElement(b(a.start.indexes)),d.select()):(d=f.createTextRange(),c(!0),c(),d.select()))},this.addRange=function(b){function c(a){var b,c,g,l,m;g=e.create("a"),b=a?h:j,c=a?i:k,l=d.duplicate(),b!=o&&b!=o.documentElement||(b=p,c=0),3==b.nodeType?(b.parentNode.insertBefore(g,b),l.moveToElementText(g),l.moveStart("character",c),e.remove(g),d.setEndPoint(a?"StartToStart":"EndToEnd",l)):(m=b.childNodes,m.length?(c>=m.length?e.insertAfter(g,m[m.length-1]):b.insertBefore(g,m[c]),l.moveToElementText(g)):b.canHaveHTML&&(b.innerHTML="<span></span>",g=b.firstChild,l.moveToElementText(g),l.collapse(f)),d.
setEndPoint(a?"StartToStart":"EndToEnd",l),e.remove(g))}var d,g,h,i,j,k,l,m,n,o=a.dom.doc,p=o.body;if(h=b.startContainer,i=b.startOffset,j=b.endContainer,k=b.endOffset,d=p.createTextRange(),h==j&&1==h.nodeType){if(i==k&&!h.hasChildNodes()){if(h.canHaveHTML)return l=h.previousSibling,l&&!l.hasChildNodes()&&e.isBlock(l)?l.innerHTML="":l=null,h.innerHTML="<span></span><span></span>",d.moveToElementText(h.lastChild),d.select(),e.doc.selection.clear(),h.innerHTML="",void(l&&(l.innerHTML=""));i=e.nodeIndex(h),h=h.parentNode}if(i==k-1)try{if(n=h.childNodes[i],g=p.createControlRange(),g.addElement(n),g.select(),m=a.getRng(),m.item&&n===m.item(0))return}catch(a){}}c(!0),c(),d.select()},this.getRangeAt=c}return a}),g("s",["1n","r","q","1j","h","1o","c&qu
ot;,"1p","6","1l","9"],function(a,b,c,d,e,f,g,h,i,j,k){function l(a,d,e,f){var g=this;g.dom=a,g.win=d,g.serializer=e,g.editor=f,g.bookmarkManager=new b(g),g.controlSelection=new c(g,f),g.win.getSelection||(g.tridentSel=new h(g))}var m=k.each,n=k.trim,o=i.ie;return l.prototype={setCursorLocation:function(a,b){var c=this,d=c.dom.createRng();a?(d.setStart(a,b),d.setEnd(a,b),c.setRng(d),c.collapse(!1)):(c._moveEndPoint(d,c.editor.getBody(),!0),c.setRng(d))},getContent:function(a){var b,c,d,e=this,f=e.getRng(),g=e.dom.create("body"),h=e.getSel();return a=a||{},b=c="",a.get=!0,a.format=a.format||"html",a.selection=!0,e.editor.fire("BeforeGetContent",a),"text"===a.format?e.isCollapsed()?"":j.trim(f.text||(h.toString?h.toString():"")):(f.cloneContents?(d=f.cloneContents(),d&&g.appendChild(d)):void 0!==f.item||void 0!==f.htmlText?(g.innerHTML="<br>"+(f.item?f.
item(0).outerHTML:f.htmlText),g.removeChild(g.firstChild)):g.innerHTML=f.toString(),/^\s/.test(g.innerHTML)&&(b=" "),/\s+$/.test(g.innerHTML)&&(c=" "),a.getInner=!0,a.content=e.isCollapsed()?"":b+e.serializer.serialize(g,a)+c,e.editor.fire("GetContent",a),a.content)},setContent:function(a,b){var c,d,e,f=this,g=f.getRng(),h=f.win.document;if(b=b||{format:"html"},b.set=!0,b.selection=!0,b.content=a,b.no_events||f.editor.fire("BeforeSetContent",b),a=b.content,g.insertNode){a+='<span id="__caret">_</span>',g.startContainer==h&&g.endContainer==h?h.body.innerHTML=a:(g.deleteContents(),0===h.body.childNodes.length?h.body.innerHTML=a:g.createContextualFragment?g.insertNode(g.createContextualFragment(a)):(d=h.createDocumentFragment(),e=h.createElement("div"),d.appendChild(e),e.outerHTML=a,g.insertNode(d))),c=f.dom.get("__caret"),g=h.createRange(),g.setStartBefore(c),g
.setEndBefore(c),f.setRng(g),f.dom.remove("__caret");try{f.setRng(g)}catch(a){}}else g.item&&(h.execCommand("Delete",!1,null),g=f.getRng()),/^\s+/.test(a)?(g.pasteHTML('<span id="__mce_tmp">_</span>'+a),f.dom.remove("__mce_tmp")):g.pasteHTML(a);b.no_events||f.editor.fire("SetContent",b)},getStart:function(a){var b,c,d,e,f=this,g=f.getRng();if(g.duplicate||g.item){if(g.item)return g.item(0);for(d=g.duplicate(),d.collapse(1),b=d.parentElement(),b.ownerDocument!==f.dom.doc&&(b=f.dom.getRoot()),c=e=g.parentElement();e=e.parentNode;)if(e==b){b=c;break}return b}return b=g.startContainer,1==b.nodeType&&b.hasChildNodes()&&(a&&g.collapsed||(b=b.childNodes[Math.min(b.childNodes.length-1,g.startOffset)])),b&&3==b.nodeType?b.parentNode:b},getEnd:function(a){var b,c,d=this,e=d.getRng();return e.duplicate||e.item?e.item?e.item(0):(e=e.duplicate(),e.collapse(0),b=e.parentElement(),b.ownerD
ocument!==d.dom.doc&&(b=d.dom.getRoot()),b&&"BODY"==b.nodeName?b.lastChild||b:b):(b=e.endContainer,c=e.endOffset,1==b.nodeType&&b.hasChildNodes()&&(a&&e.collapsed||(b=b.childNodes[c>0?c-1:c])),b&&3==b.nodeType?b.parentNode:b)},getBookmark:function(a,b){return this.bookmarkManager.getBookmark(a,b)},moveToBookmark:function(a){return this.bookmarkManager.moveToBookmark(a)},select:function(a,b){var c,d=this,e=d.dom,f=e.createRng();if(d.lastFocusBookmark=null,a){if(!b&&d.controlSelection.controlSelect(a))return;c=e.nodeIndex(a),f.setStart(a.parentNode,c),f.setEnd(a.parentNode,c+1),b&&(d._moveEndPoint(f,a,!0),d._moveEndPoint(f,a)),d.setRng(f)}return a},isCollapsed:function(){var a=this,b=a.getRng(),c=a.getSel();return!(!b||b.item)&&(b.compareEndPoints?0===b.compareEndPoints("StartToEnd",b):!c||b.collapsed)},collapse:function(a){var b,c=this,d=c.getRng();d.item&&(b=d.item(0),d=c.win.docum
ent.body.createTextRange(),d.moveToElementText(b)),d.collapse(!!a),c.setRng(d)},getSel:function(){var a=this.win;return a.getSelection?a.getSelection():a.document.selection},getRng:function(a){function b(a,b,c){try{return b.compareBoundaryPoints(a,c)}catch(a){return-1}}var c,d,e,f,g,h,i=this;if(!i.win)return null;if(f=i.win.document,"undefined"==typeof f||null===f)return null;if(!a&&i.lastFocusBookmark){var j=i.lastFocusBookmark;return j.startContainer?(d=f.createRange(),d.setStart(j.startContainer,j.startOffset),d.setEnd(j.endContainer,j.endOffset)):d=j,d}if(a&&i.tridentSel)return i.tridentSel.getRangeAt(0);try{(c=i.getSel())&&(d=c.rangeCount>0?c.getRangeAt(0):c.createRange?c.createRange():f.createRange())}catch(a){}if(h=i.editor.fire("GetSelectionRange",{range:d}),h.range!==d)return h.range;if(o&&d&&d.setStart&&f.selection){try{g=f.selection.createRange()}catch(a){}g&&g.item&&(e=g.item(0),d=f.cr
eateRange(),d.setStartBefore(e),d.setEndAfter(e))}return d||(d=f.createRange?f.createRange():f.body.createTextRange()),d.setStart&&9===d.startContainer.nodeType&&d.collapsed&&(e=i.dom.getRoot(),d.setStart(e,0),d.setEnd(e,0)),i.selectedRange&&i.explicitRange&&(0===b(d.START_TO_START,d,i.selectedRange)&&0===b(d.END_TO_END,d,i.selectedRange)?d=i.explicitRange:(i.selectedRange=null,i.explicitRange=null)),d},setRng:function(a,b){var c,d,e,f=this;if(a)if(a.select){f.explicitRange=null;try{a.select()}catch(a){}}else if(f.tridentSel){if(a.cloneRange)try{f.tridentSel.addRange(a)}catch(a){}}else{if(c=f.getSel(),e=f.editor.fire("SetSelectionRange",{range:a}),a=e.range,c){f.explicitRange=a;try{c.removeAllRanges(),c.addRange(a)}catch(a){}b===!1&&c.extend&&(c.collapse(a.endContainer,a.endOffset),c.extend(a.startContainer,a.startOffset)),f.selectedRange=c.rangeCount>0?c.getRangeAt(0):null}a.collapsed||a.startContainer!==a
.endContainer||!c.setBaseAndExtent||i.ie||a.endOffset-a.startOffset<2&&a.startContainer.hasChildNodes()&&(d=a.startContainer.childNodes[a.startOffset],d&&"IMG"===d.tagName&&(c.setBaseAndExtent(a.startContainer,a.startOffset,a.endContainer,a.endOffset),c.anchorNode===a.startContainer&&c.focusNode===a.endContainer||c.setBaseAndExtent(d,0,d,1))),f.editor.fire("AfterSetSelectionRange",{range:a})}},setNode:function(a){var b=this;return b.setContent(b.dom.getOuterHTML(a)),a},getNode:function(){function a(a,b){for(var c=a;a&&3===a.nodeType&&0===a.length;)a=b?a.nextSibling:a.previousSibling;return a||c}var b,c,d,e,f,g=this,h=g.getRng(),i=g.dom.getRoot();return h?(c=h.startContainer,d=h.endContainer,e=h.startOffset,f=h.endOffset,h.setStart?(b=h.commonAncestorContainer,!h.collapsed&&(c==d&&f-e<2&&c.hasChildNodes()&&(b=c.childNodes[e]),3===c.nodeType&&3===d.nodeType&&am
p;(c=c.length===e?a(c.nextSibling,!0):c.parentNode,d=0===f?a(d.previousSibling,!1):d.parentNode,c&&c===d))?c:b&&3==b.nodeType?b.parentNode:b):(b=h.item?h.item(0):h.parentElement(),b.ownerDocument!==g.win.document&&(b=i),b)):i},getSelectedBlocks:function(a,b){var c,d,e=this,f=e.dom,h=[];if(d=f.getRoot(),a=f.getParent(a||e.getStart(),f.isBlock),b=f.getParent(b||e.getEnd(),f.isBlock),a&&a!=d&&h.push(a),a&&b&&a!=b){c=a;for(var i=new g(a,d);(c=i.next())&&c!=b;)f.isBlock(c)&&h.push(c)}return b&&a!=b&&b!=d&&h.push(b),h},isForward:function(){var a,b,c=this.dom,d=this.getSel();return!(d&&d.anchorNode&&d.focusNode)||(a=c.createRng(),a.setStart(d.anchorNode,d.anchorOffset),a.collapse(!0),b=c.createRng(),b.setStart(d.focusNode,d.focusOffset),b.collapse(!0),a.compareBoundaryPoints(a.START_TO_START,b)<=0)},normalize:function(){var a=this,b=a.getRng();return i.range&&new e(a.d
om).normalize(b)&&a.setRng(b,a.isForward()),b},selectorChanged:function(a,b){var c,d=this;return d.selectorChangedData||(d.selectorChangedData={},c={},d.editor.on("NodeChange",function(a){var b=a.element,e=d.dom,f=e.getParents(b,null,e.getRoot()),g={};m(d.selectorChangedData,function(a,b){m(f,function(d){if(e.is(d,b))return c[b]||(m(a,function(a){a(!0,{node:d,selector:b,parents:f})}),c[b]=a),g[b]=a,!1})}),m(c,function(a,d){g[d]||(delete c[d],m(a,function(a){a(!1,{node:b,selector:d,parents:f})}))})})),d.selectorChangedData[a]||(d.selectorChangedData[a]=[]),d.selectorChangedData[a].push(b),d},getScrollContainer:function(){for(var a,b=this.dom.getRoot();b&&"BODY"!=b.nodeName;){if(b.scrollHeight>b.clientHeight){a=b;break}b=b.parentNode}return a},scrollIntoView:function(a,b){f.scrollIntoView(this.editor,a,b)},placeCaretAt:function(a,b){this.setRng(e.getCaretRangeFromPoint(a,b,this.editor.getDoc()))},_moveEndPoint:function(a,b,c){var d=b,e=new g(b,d)
,f=this.dom.schema.getNonEmptyElements();do{if(3==b.nodeType&&0!==n(b.nodeValue).length)return void(c?a.setStart(b,0):a.setEnd(b,b.nodeValue.length));if(f[b.nodeName]&&!/^(TD|TH)$/.test(b.nodeName))return void(c?a.setStartBefore(b):"BR"==b.nodeName?a.setEndBefore(b):a.setEndAfter(b));if(i.ie&&i.ie<11&&this.dom.isBlock(b)&&this.dom.isEmpty(b))return void(c?a.setStart(b,0):a.setEnd(b,0))}while(b=c?e.next():e.prev());"BODY"==d.nodeName&&(c?a.setStart(d,0):a.setEnd(d,d.childNodes.length))},getBoundingClientRect:function(){var b=this.getRng();return b.collapsed?a.fromRangeStart(b).getClientRects()[0]:b.getBoundingClientRect()},destroy:function(){this.win=null,this.controlSelection.destroy()}},l}),g("1q",["r","9"],function(a,b){function c(b){this.compare=function(c,e){function f(a){var c={};return d(b.getAttribs(a),function(d){var e=d.nodeName.toLowerCase();0!==e.indexOf("_")&
;&"style"!==e&&0!==e.indexOf("data-")&&(c[e]=b.getAttrib(a,e))}),c}function g(a,b){var c,d;for(d in a)if(a.hasOwnProperty(d)){if(c=b[d],"undefined"==typeof c)return!1;if(a[d]!=c)return!1;delete b[d]}for(d in b)if(b.hasOwnProperty(d))return!1;return!0}return c.nodeName==e.nodeName&&(!!g(f(c),f(e))&&(!!g(b.parseStyle(b.getAttrib(c,"style")),b.parseStyle(b.getAttrib(e,"style")))&&(!a.isBookmarkNode(c)&&!a.isBookmarkNode(e))))}}var d=b.each;return c}),g("1s",["e","9","j"],function(a,b,c){function d(a,d){function e(a,b){b.classes.length&&j.addClass(a,b.classes.join(" ")),j.setAttribs(a,b.attrs)}function f(a){var b;return k="string"==typeof a?{name:a,classes:[],attrs:{}}:a,b=j.create(k.name),e(b,k),b}function g(a,c){var d="string"!=typeof a?a.nodeName.toLowerCase():a,e=m.getElementRule(d),f=e.parentsRequired;ret
urn!(!f||!f.length)&&(c&&b.inArray(f,c)!==-1?c:f[0])}function h(a,c,d){var e,i,k,l=c.length&&c[0],m=l&&l.name;if(k=g(a,m))m==k?(i=c[0],c=c.slice(1)):i=k;else if(l)i=c[0],c=c.slice(1);else if(!d)return a;return i&&(e=f(i),e.appendChild(a)),d&&(e||(e=j.create("div"),e.appendChild(a)),b.each(d,function(b){var c=f(b);e.insertBefore(c,a)})),h(e,c,i&&i.siblings)}var i,k,l,m=d&&d.schema||new c({});return a&&a.length?(k=a[0],i=f(k),l=j.create("div"),l.appendChild(h(i,a.slice(1),k.siblings)),l):""}function e(a,b){return d(g(a),b)}function f(a){var c,d={classes:[],attrs:{}};return a=d.selector=b.trim(a),"*"!==a&&(c=a.replace(/(?:([#\.]|::?)([\w\-]+)|(\[)([^\]]+)\]?)/g,function(a,c,e,f,g){switch(c){case"#":d.attrs.id=e;break;case".":d.classes.push(e);break;case":":b.inArray("checked disabled enabled read-only required".split(" &quo
t;),e)!==-1&&(d.attrs[e]=e)}if("["==f){var h=g.match(/([\w\-]+)(?:\=\"([^\"]+))?/);h&&(d.attrs[h[1]]=h[2])}return""})),d.name=c||"div",d}function g(a){return a&&"string"==typeof a?(a=a.split(/\s*,\s*/)[0],a=a.replace(/\s*(~\+|~|\+|>)\s*/g,"$1"),b.map(a.split(/(?:>|\s+(?![^\[\]]+\]))/),function(a){var c=b.map(a.split(/(?:~\+|~|\+)/),f),d=c.pop();return c.length&&(d.siblings=c),d}).reverse()):[]}function h(a,b){function c(a){return a.replace(/%(\w+)/g,"")}var e,f,h,k,l,m,n="";if(m=a.settings.preview_styles,m===!1)return"";if("string"!=typeof m&&(m="font-family font-size font-weight font-style text-decoration text-transform color background-color border border-radius outline text-shadow"),"string"==typeof b){if(b=a.formatter.get(b),!b)return;b=b[0]}return"preview"in b&&(m=b.preview,m===!1)?"":(e
=b.block||b.inline||"span",k=g(b.selector),k.length?(k[0].name||(k[0].name=e),e=b.selector,f=d(k,a)):f=d([e],a),h=j.select(e,f)[0]||f.firstChild,i(b.styles,function(a,b){a=c(a),a&&j.setStyle(h,b,a)}),i(b.attributes,function(a,b){a=c(a),a&&j.setAttrib(h,b,a)}),i(b.classes,function(a){a=c(a),j.hasClass(h,a)||j.addClass(h,a)}),a.fire("PreviewFormats"),j.setStyles(f,{position:"absolute",left:-65535}),a.getBody().appendChild(f),l=j.getStyle(a.getBody(),"fontSize",!0),l=/px$/.test(l)?parseInt(l,10):0,i(m.split(" "),function(b){var c=j.getStyle(h,b,!0);if(!("background-color"==b&&/transparent|rgba\s*\([^)]+,\s*0\)/.test(c)&&(c=j.getStyle(a.getBody(),b,!0),"#ffffff"==j.toHex(c).toLowerCase())||"color"==b&&"#000000"==j.toHex(c).toLowerCase())){if("font-size"==b&&/em|%$/.test(c)){if(0===l)return;c=parseFloat(c,10)/(/%$/.test(c)?100:1),c=c*l+"
px"}"border"==b&&c&&(n+="padding:0 2px;"),n+=b+":"+c+";"}}),a.fire("AfterPreviewFormats"),j.remove(f),n)}var i=b.each,j=a.DOM;return{getCssText:h,parseSelector:g,selectorToHtml:e}}),g("1t",["1g","1j","a"],function(a,b,c){function d(a,b){var c=f[a];c||(f[a]=c=[]),f[a].push(b)}function e(a,b){h(f[a],function(a){a(b)})}var f={},g=a.filter,h=a.each;return d("pre",function(d){function e(b){return i(b.previousSibling)&&a.indexOf(j,b.previousSibling)!=-1}function f(a,b){c(b).remove(),c(a).append("<br><br>").append(b.childNodes)}var i,j,k=d.selection.getRng();i=b.matchNodeNames("pre"),k.collapsed||(j=d.selection.getSelectedBlocks(),
+h(g(g(j,i),e),function(a){f(a.previousSibling,a)}))}),{postProcess:e}}),g("t",["c","h","r","1q","1j","1r","9","1s","1t"],function(a,b,c,d,e,f,g,h,i){return function(j){function k(a){return a.nodeType&&(a=a.nodeName),!!j.schema.getTextBlockElements()[a.toLowerCase()]}function l(a){return/^(TH|TD)$/.test(a.nodeName)}function m(a){return a&&/^(IMG)$/.test(a.nodeName)}function n(a,b){return da.getParents(a,b,da.getRoot())}function o(a){return 1===a.nodeType&&"_mce_caret"===a.id}function p(){s({valigntop:[{selector:"td,th",styles:{verticalAlign:"top"}}],valignmiddle:[{selector:"td,th",styles:{verticalAlign:"middle"}}],valignbottom:[{selector:"td,th",styles:{verticalAlign:"bottom"}}],alignleft:[{selector:"figure.image",collapsed:!1,classes:"align-left",ceFalseOverride:!0,preview
:"font-family font-size"},{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"left"},inherit:!1,preview:!1,defaultBlock:"div"},{selector:"img,table",collapsed:!1,styles:{"float":"left"},preview:"font-family font-size"}],aligncenter:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"center"},inherit:!1,preview:!1,defaultBlock:"div"},{selector:"figure.image",collapsed:!1,classes:"align-center",ceFalseOverride:!0,preview:"font-family font-size"},{selector:"img",collapsed:!1,styles:{display:"block",marginLeft:"auto",marginRight:"auto"},preview:!1},{selector:"table",collapsed:!1,styles:{marginLeft:"auto",marginRight:"auto"},preview:"font-family font-size"}],alignright:[{selector:"figure.image",collapsed:!
1,classes:"align-right",ceFalseOverride:!0,preview:"font-family font-size"},{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"right"},inherit:!1,preview:"font-family font-size",defaultBlock:"div"},{selector:"img,table",collapsed:!1,styles:{"float":"right"},preview:"font-family font-size"}],alignjustify:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"justify"},inherit:!1,defaultBlock:"div",preview:"font-family font-size"}],bold:[{inline:"strong",remove:"all"},{inline:"span",styles:{fontWeight:"bold"}},{inline:"b",remove:"all"}],italic:[{inline:"em",remove:"all"},{inline:"span",styles:{fontStyle:"italic"}},{inline:"i",remove:"all"}],underline:[{inline:"span"
,styles:{textDecoration:"underline"},exact:!0},{inline:"u",remove:"all"}],strikethrough:[{inline:"span",styles:{textDecoration:"line-through"},exact:!0},{inline:"strike",remove:"all"}],forecolor:{inline:"span",styles:{color:"%value"},links:!0,remove_similar:!0},hilitecolor:{inline:"span",styles:{backgroundColor:"%value"},links:!0,remove_similar:!0},fontname:{inline:"span",styles:{fontFamily:"%value"}},fontsize:{inline:"span",styles:{fontSize:"%value"}},fontsize_class:{inline:"span",attributes:{"class":"%value"}},blockquote:{block:"blockquote",wrapper:1,remove:"all"},subscript:{inline:"sub"},superscript:{inline:"sup"},code:{inline:"code"},link:{inline:"a",selector:"a",remove:"all",split:!0,deep:!0,onmatch:function(){return!0},on
format:function(a,b,c){qa(c,function(b,c){da.setAttrib(a,c,b)})}},removeformat:[{selector:"b,strong,em,i,font,u,strike,sub,sup,dfn,code,samp,kbd,var,cite,mark,q,del,ins",remove:"all",split:!0,expand:!1,block_expand:!0,deep:!0},{selector:"span",attributes:["style","class"],remove:"empty",split:!0,expand:!1,deep:!0},{selector:"*",attributes:["style","class"],split:!1,expand:!1,deep:!0}]}),qa("p h1 h2 h3 h4 h5 h6 div address pre div dt dd samp".split(/\s/),function(a){s(a,{block:a,remove:"all"})}),s(j.settings.formats)}function q(){j.addShortcut("meta+b","bold_desc","Bold"),j.addShortcut("meta+i","italic_desc","Italic"),j.addShortcut("meta+u","underline_desc","Underline");for(var a=1;a<=6;a++)j.addShortcut("access+"+a,"",["FormatBlock",!1,"h"+a]);
j.addShortcut("access+7","",["FormatBlock",!1,"p"]),j.addShortcut("access+8","",["FormatBlock",!1,"div"]),j.addShortcut("access+9","",["FormatBlock",!1,"address"])}function r(a){return a?ca[a]:ca}function s(a,b){a&&("string"!=typeof a?qa(a,function(a,b){s(b,a)}):(b=b.length?b:[b],qa(b,function(a){a.deep===_&&(a.deep=!a.selector),a.split===_&&(a.split=!a.selector||a.inline),a.remove===_&&a.selector&&!a.inline&&(a.remove="none"),a.selector&&a.inline&&(a.mixed=!0,a.block_expand=!0),"string"==typeof a.classes&&(a.classes=a.classes.split(/\s+/))}),ca[a]=b))}function t(a){return a&&ca[a]&&delete ca[a],ca}function u(a,b){var c=r(b);if(c)for(var d=0;d<c.length;d++)if(c[d].inherit===!1&&da.is(a,c[d].selector))return!0;return!1}function v(a){var b;
return j.dom.getParent(a,function(a){return b=j.dom.getStyle(a,"text-decoration"),b&&"none"!==b}),b}function w(a){var b;1===a.nodeType&&a.parentNode&&1===a.parentNode.nodeType&&(b=v(a.parentNode),j.dom.getStyle(a,"color")&&b?j.dom.setStyle(a,"text-decoration",b):j.dom.getStyle(a,"text-decoration")===b&&j.dom.setStyle(a,"text-decoration",null))}function x(b,c,d){function e(a,b){if(b=b||p,a){if(b.onformat&&b.onformat(a,b,c,d),qa(b.styles,function(b,d){da.setStyle(a,d,O(b,c))}),b.styles){var e=da.getAttrib(a,"style");e&&a.setAttribute("data-mce-style",e)}qa(b.attributes,function(b,d){da.setAttrib(a,d,O(b,c))}),qa(b.classes,function(b){b=O(b,c),da.hasClass(a,b)||da.addClass(a,b)})}}function f(a,b){var c=!1;return!!p.selector&&(qa(a,function(a){if(!("collapsed"in a&&a.collapsed!==q))return da.is(b,a.selector)&&!o
(b)?(e(b,a),c=!0,!1):void 0}),c)}function g(){function b(b,c){var e=new a(c);for(d=e.prev2();d;d=e.prev2()){if(3==d.nodeType&&d.data.length>0)return d;if(d.childNodes.length>1||d==b||"BR"==d.tagName)return d}}var c=j.selection.getRng(),e=c.startContainer,f=c.endContainer;if(e!=f&&0===c.endOffset){var g=b(e,f),h=3==g.nodeType?g.data.length:g.childNodes.length;c.setEnd(g,h)}return c}function h(a,d,g){var h,i,j=[],l=!0;h=p.inline||p.block,i=da.create(h),e(i),fa.walk(a,function(a){function d(a){var q,r,s,t;if(t=l,q=a.nodeName.toLowerCase(),r=a.parentNode.nodeName.toLowerCase(),1===a.nodeType&&oa(a)&&(t=l,l="true"===oa(a),s=!0),H(q,"br"))return m=0,void(p.block&&da.remove(a));if(p.wrapper&&A(a,b,c))return void(m=0);if(l&&!s&&p.block&&!p.wrapper&&k(q)&&ga(r,h))return a=da.rename(a,h),e(a),j.push(a),void(m=0);if(p.selector){var u=f(n,a);if(!p.inline||u)return void(m=0
)}!l||s||!ga(h,q)||!ga(r,h)||!g&&3===a.nodeType&&1===a.nodeValue.length&&65279===a.nodeValue.charCodeAt(0)||o(a)||p.inline&&ha(a)?(m=0,qa(ra(a.childNodes),d),s&&(l=t),m=0):(m||(m=da.clone(i,ma),a.parentNode.insertBefore(m,a),j.push(m)),m.appendChild(a))}var m;qa(a,d)}),p.links===!0&&qa(j,function(a){function b(a){"A"===a.nodeName&&e(a,p),qa(ra(a.childNodes),b)}b(a)}),qa(j,function(a){function d(a){var b=0;return qa(a.childNodes,function(a){P(a)||pa(a)||b++}),b}function f(a){var b=!1;return qa(a.childNodes,function(a){if(J(a))return b=a,!1}),b}function g(a,b){do{if(1!==d(a))break;if(a=f(a),!a)break;if(b(a))return a}while(a);return null}function h(a){var b,c;return b=f(a),b&&!pa(b)&&G(b,p)&&(c=da.clone(b,ma),e(c),da.replace(c,a,na),da.remove(b,1)),c||a}var i;if(i=d(a),(j.length>1||!ha(a))&&0===i)return void da.remove(a,1);if(p.inline||p.wrapper){if(p.exact||1!==i||(a=h(a)),qa(n,functio
n(b){qa(da.select(b.inline,a),function(a){J(a)&&T(b,c,a,b.exact?a:null)})}),A(a.parentNode,b,c)&&T(p,c,a)&&(a=0),p.merge_with_parents&&da.getParent(a.parentNode,function(d){if(A(d,b,c))return T(p,c,a)&&(a=0),na}),a&&!ha(a)&&!M(a,"fontSize")){var k=g(a,K("fontSize"));k&&x("fontsize",{value:M(k,"fontSize")},a)}a&&p.merge_siblings!==!1&&(a=W(V(a),a),a=W(a,V(a,na)))}})}var l,m,n=r(b),p=n[0],q=!d&&ea.isCollapsed();if("false"!==oa(ea.getNode())){if(p){if(d)d.nodeType?f(n,d)||(m=da.createRng(),m.setStartBefore(d),m.setEndAfter(d),h(R(m,n),null,!0)):h(d,null,!0);else if(q&&p.inline&&!da.select("td[data-mce-selected],th[data-mce-selected]").length)Y("apply",b,c);else{var s=j.selection.getNode();ia||!n[0].defaultBlock||da.getParent(s,da.isBlock)||x(n[0].defaultBlock),j.selection.setRng(g()),l=ea.getBookmark(),h(R(ea.getRn
g(na),n),l),p.styles&&((p.styles.color||p.styles.textDecoration)&&(sa(s,w,"childNodes"),w(s)),p.styles.backgroundColor&&I(s,K("fontSize"),L("backgroundColor",O(p.styles.backgroundColor,c)))),ea.moveToBookmark(l),Z(ea.getRng(na)),j.nodeChanged()}i.postProcess(b,j)}}else{d=ea.getNode();for(var t=0,u=n.length;t<u;t++)if(n[t].ceFalseOverride&&da.is(d,n[t].selector))return void e(d,n[t])}}function y(a,b,c,d){function e(a){var c,d,f,g,h;if(1===a.nodeType&&oa(a)&&(g=s,s="true"===oa(a),h=!0),c=ra(a.childNodes),s&&!h)for(d=0,f=p.length;d<f&&!T(p[d],b,a,a);d++);if(q.deep&&c.length){for(d=0,f=c.length;d<f;d++)e(c[d]);h&&(s=g)}}function f(c){var e;return qa(n(c.parentNode).reverse(),function(c){var f;e||"_start"==c.id||"_end"==c.id||(f=A(c,a,b,d),f&&f.split!==!1&&(e=c))}),e}function g(a,c,d,e){var f,g,h,i,j,k;if(a){for(k=a.parentNod
e,f=c.parentNode;f&&f!=k;f=f.parentNode){for(g=da.clone(f,ma),j=0;j<p.length;j++)if(T(p[j],b,g,g)){g=0;break}g&&(h&&g.appendChild(h),i||(i=g),h=g)}!e||q.mixed&&ha(a)||(c=da.split(a,c)),h&&(d.parentNode.insertBefore(h,d),i.appendChild(d))}return c}function h(a){return g(f(a),a,a,!0)}function i(a){var b=da.get(a?"_start":"_end"),c=b[a?"firstChild":"lastChild"];return pa(c)&&(c=c[a?"firstChild":"lastChild"]),3==c.nodeType&&0===c.data.length&&(c=a?b.previousSibling||b.nextSibling:b.nextSibling||b.previousSibling),da.remove(b,!0),c}function k(a){var b,c,d=a.commonAncestorContainer;if(a=R(a,p,na),q.split){if(b=X(a,na),c=X(a),b!=c){if(/^(TR|TH|TD)$/.test(b.nodeName)&&b.firstChild&&(b="TR"==b.nodeName?b.firstChild.firstChild||b:b.firstChild||b),d&&/^T(HEAD|BODY|FOOT|R)$/.test(d.nodeName)&&l(c)&&c.firstChild&&
(c=c.firstChild||c),da.isChildOf(b,c)&&!ha(c)&&!l(b)&&!l(c))return b=Q(b,"span",{id:"_start","data-mce-type":"bookmark"}),h(b),void(b=i(na));b=Q(b,"span",{id:"_start","data-mce-type":"bookmark"}),c=Q(c,"span",{id:"_end","data-mce-type":"bookmark"}),h(b),h(c),b=i(na),c=i()}else b=c=h(b);a.startContainer=b.parentNode?b.parentNode:b,a.startOffset=ja(b),a.endContainer=c.parentNode?c.parentNode:c,a.endOffset=ja(c)+1}fa.walk(a,function(a){qa(a,function(a){e(a),1===a.nodeType&&"underline"===j.dom.getStyle(a,"text-decoration")&&a.parentNode&&"underline"===v(a.parentNode)&&T({deep:!1,exact:!0,inline:"span",styles:{textDecoration:"underline"}},null,a)})})}var m,o,p=r(a),q=p[0],s=!0;if(c)return void(c.nodeType?(o=da.createRng(),o.setStartBefore(c),o.setEndAfter(c),k(o)):k
(c));if("false"!==oa(ea.getNode()))ea.isCollapsed()&&q.inline&&!da.select("td[data-mce-selected],th[data-mce-selected]").length?Y("remove",a,b,d):(m=ea.getBookmark(),k(ea.getRng(na)),ea.moveToBookmark(m),q.inline&&B(a,b,ea.getStart())&&Z(ea.getRng(!0)),j.nodeChanged());else{c=ea.getNode();for(var t=0,u=p.length;t<u&&(!p[t].ceFalseOverride||!T(p[t],b,c,c));t++);}}function z(a,b,c){var d=r(a);!B(a,b,c)||"toggle"in d[0]&&!d[0].toggle?x(a,b,c):y(a,b,c)}function A(a,b,c,d){function e(a,b,e){var f,g,h,i=b[e];if(b.onmatch)return b.onmatch(a,b,e);if(i)if(i.length===_){for(f in i)if(i.hasOwnProperty(f)){if(g="attributes"===e?da.getAttrib(a,f):M(a,f),d&&!g&&!b.exact)return;if((!d||b.exact)&&!H(g,N(O(i[f],c),f)))return}}else for(h=0;h<i.length;h++)if("attributes"===e?da.getAttrib(a,i[h]):M(a,i[h]))return b;return b}var f,g,h,i=r(b);if(i&&a)for(g=0;g&
lt;i.length;g++)if(f=i[g],G(a,f)&&e(a,f,"attributes")&&e(a,f,"styles")){if(h=f.classes)for(g=0;g<h.length;g++)if(!da.hasClass(a,h[g]))return;return f}}function B(a,b,c){function d(c){var d=da.getRoot();return c!==d&&(c=da.getParent(c,function(c){return!!u(c,a)||(c.parentNode===d||!!A(c,a,b,!0))}),A(c,a,b))}var e;return c?d(c):(c=ea.getNode(),d(c)?na:(e=ea.getStart(),e!=c&&d(e)?na:ma))}function C(a,b){var c,d=[],e={};return c=ea.getStart(),da.getParent(c,function(c){var f,g;for(f=0;f<a.length;f++)g=a[f],!e[g]&&A(c,g,b)&&(e[g]=!0,d.push(g))},da.getRoot()),d}function D(a){var b,c,d,e,f,g=r(a);if(g)for(b=ea.getStart(),c=n(b),e=g.length-1;e>=0;e--){if(f=g[e].selector,!f||g[e].defaultBlock)return na;for(d=c.length-1;d>=0;d--)if(da.is(c[d],f))return na}return ma}function E(a,b,c){var d;return $||($={},d={},j.on("NodeChange",function(a){var b=n(a.element),c={};b=g.grep(b,function(a){return 1==a.nodeTyp
e&&!a.getAttribute("data-mce-bogus")}),qa($,function(a,e){qa(b,function(f){return A(f,e,{},a.similar)?(d[e]||(qa(a,function(a){a(!0,{node:f,format:e,parents:b})}),d[e]=a),c[e]=a,!1):!u(f,e)&&void 0})}),qa(d,function(e,f){c[f]||(delete d[f],qa(e,function(c){c(!1,{node:a.element,format:f,parents:b})}))})})),qa(a.split(","),function(a){$[a]||($[a]=[],$[a].similar=c),$[a].push(b)}),this}function F(a){return h.getCssText(j,a)}function G(a,b){return H(a,b.inline)?na:H(a,b.block)?na:b.selector?1==a.nodeType&&da.is(a,b.selector):void 0}function H(a,b){return a=a||"",b=b||"",a=""+(a.nodeName||a),b=""+(b.nodeName||b),a.toLowerCase()==b.toLowerCase()}function I(a,b,c){qa(a.childNodes,function(a){J(a)&&(b(a)&&c(a),a.hasChildNodes()&&I(a,b,c))})}function J(a){return a&&1===a.nodeType&&!pa(a)&&!o(a)&&!e.isBogus(a)}function K(a){return f.curry(function(a,b){re
turn!(!b||!M(b,a))},a)}function L(a,b){return f.curry(function(a,b,c){da.setStyle(c,a,b)},a,b)}function M(a,b){return N(da.getStyle(a,b),b)}function N(a,b){return"color"!=b&&"backgroundColor"!=b||(a=da.toHex(a)),"fontWeight"==b&&700==a&&(a="bold"),"fontFamily"==b&&(a=a.replace(/[\'\"]/g,"").replace(/,\s+/g,",")),""+a}function O(a,b){return"string"!=typeof a?a=a(b):b&&(a=a.replace(/%(\w+)/g,function(a,c){return b[c]||a})),a}function P(a){return a&&3===a.nodeType&&/^([\t \r\n]+|)$/.test(a.nodeValue)}function Q(a,b,c){var d=da.create(b,c);return a.parentNode.insertBefore(d,a),d.appendChild(a),d}function R(b,c,d){function e(a){function b(a){return"BR"==a.nodeName&&a.getAttribute("data-mce-bogus")&&!a.nextSibling}var d,e,f,g,h;if(d=e=a?q:s,g=a?"previousSibling":"nextSibling",h=da.getR
oot(),3==d.nodeType&&!P(d)&&(a?r>0:t<d.nodeValue.length))return d;for(;;){if(!c[0].block_expand&&ha(e))return e;for(f=e[g];f;f=f[g])if(!pa(f)&&!P(f)&&!b(f))return e;if(e==h||e.parentNode==h){d=e;break}e=e.parentNode}return d}function f(a,b){for(b===_&&(b=3===a.nodeType?a.length:a.childNodes.length);a&&a.hasChildNodes();)a=a.childNodes[b],a&&(b=3===a.nodeType?a.length:a.childNodes.length);return{node:a,offset:b}}function g(a){for(var b=a;b;){if(1===b.nodeType&&oa(b))return"false"===oa(b)?b:a;b=b.parentNode}return a}function h(b,c,e){function f(a,b){var c,f,g=a.nodeValue;return"undefined"==typeof b&&(b=e?g.length:0),e?(c=g.lastIndexOf(" ",b),f=g.lastIndexOf("\xa0",b),c=c>f?c:f,c===-1||d||c++):(c=g.indexOf(" ",b),f=g.indexOf("\xa0",b),c=c!==-1&&(f===-1||c<f)?c:f),c}var g,h,i,k;if(3===b.nodeType){if(i=f(b,c),i!==-1)return{contain
er:b,offset:i};k=b}for(g=new a(b,da.getParent(b,ha)||j.getBody());h=g[e?"prev":"next"]();)if(3===h.nodeType){if(k=h,i=f(h),i!==-1)return{container:h,offset:i}}else if(ha(h))break;if(k)return c=e?0:k.length,{container:k,offset:c}}function i(a,d){var e,f,g,h;for(3==a.nodeType&&0===a.nodeValue.length&&a[d]&&(a=a[d]),e=n(a),f=0;f<e.length;f++)for(g=0;g<c.length;g++)if(h=c[g],!("collapsed"in h&&h.collapsed!==b.collapsed)&&da.is(e[f],h.selector))return e[f];return a}function l(a,b){var d,e=da.getRoot();if(c[0].wrapper||(d=da.getParent(a,c[0].block,e)),d||(d=da.getParent(3==a.nodeType?a.parentNode:a,function(a){return a!=e&&k(a)})),d&&c[0].wrapper&&(d=n(d,"ul,ol").reverse()[0]||d),!d)for(d=a;d[b]&&!ha(d[b])&&(d=d[b],!H(d,"br")););return d||a}var m,o,p,q=b.startContainer,r=b.startOffset,s=b.endContainer,t=b.endOffset;if(1==q.nodeType&&q.hasChildNode
s()&&(m=q.childNodes.length-1,q=q.childNodes[r>m?m:r],3==q.nodeType&&(r=0)),1==s.nodeType&&s.hasChildNodes()&&(m=s.childNodes.length-1,s=s.childNodes[t>m?m:t-1],3==s.nodeType&&(t=s.nodeValue.length)),q=g(q),s=g(s),(pa(q.parentNode)||pa(q))&&(q=pa(q)?q:q.parentNode,q=q.nextSibling||q,3==q.nodeType&&(r=0)),(pa(s.parentNode)||pa(s))&&(s=pa(s)?s:s.parentNode,s=s.previousSibling||s,3==s.nodeType&&(t=s.length)),c[0].inline&&(b.collapsed&&(p=h(q,r,!0),p&&(q=p.container,r=p.offset),p=h(s,t),p&&(s=p.container,t=p.offset)),o=f(s,t),o.node)){for(;o.node&&0===o.offset&&o.node.previousSibling;)o=f(o.node.previousSibling);o.node&&o.offset>0&&3===o.node.nodeType&&" "===o.node.nodeValue.charAt(o.offset-1)&&o.offset>1&&(s=o.node,s.splitText(o.offset-1))}return(c[0].inline||c[0].block_expand)&&(c[0].inline&&am
p;3==q.nodeType&&0!==r||(q=e(!0)),c[0].inline&&3==s.nodeType&&t!==s.nodeValue.length||(s=e())),c[0].selector&&c[0].expand!==ma&&!c[0].inline&&(q=i(q,"previousSibling"),s=i(s,"nextSibling")),(c[0].block||c[0].selector)&&(q=l(q,"previousSibling"),s=l(s,"nextSibling"),c[0].block&&(ha(q)||(q=e(!0)),ha(s)||(s=e()))),1==q.nodeType&&(r=ja(q),q=q.parentNode),1==s.nodeType&&(t=ja(s)+1,s=s.parentNode),{startContainer:q,startOffset:r,endContainer:s,endOffset:t}}function S(a,b){return b.links&&"A"==a.tagName}function T(a,b,c,d){var e,f,g;if(!G(c,a)&&!S(c,a))return ma;if("all"!=a.remove)for(qa(a.styles,function(e,f){e=N(O(e,b),f),"number"==typeof f&&(f=e,d=0),(a.remove_similar||!d||H(M(d,f),e))&&da.setStyle(c,f,""),g=1}),g&&""===da.getAttrib(c,"style")&&(c.removeAttribute
("style"),c.removeAttribute("data-mce-style")),qa(a.attributes,function(a,e){var f;if(a=O(a,b),"number"==typeof e&&(e=a,d=0),!d||H(da.getAttrib(d,e),a)){if("class"==e&&(a=da.getAttrib(c,e),a&&(f="",qa(a.split(/\s+/),function(a){/mce\-\w+/.test(a)&&(f+=(f?" ":"")+a)}),f)))return void da.setAttrib(c,e,f);"class"==e&&c.removeAttribute("className"),la.test(e)&&c.removeAttribute("data-mce-"+e),c.removeAttribute(e)}}),qa(a.classes,function(a){a=O(a,b),d&&!da.hasClass(d,a)||da.removeClass(c,a)}),f=da.getAttribs(c),e=0;e<f.length;e++){var h=f[e].nodeName;if(0!==h.indexOf("_")&&0!==h.indexOf("data-"))return ma}return"none"!=a.remove?(U(c,a),na):void 0}function U(a,b){function c(a,b,c){return a=V(a,b,c),!a||"BR"==a.nodeName||ha(a)}var d,e=a.parentNode;b.block&&(ia?e==da.getRoot()&a
mp;&(b.list_block&&H(a,b.list_block)||qa(ra(a.childNodes),function(a){ga(ia,a.nodeName.toLowerCase())?d?d.appendChild(a):(d=Q(a,ia),da.setAttribs(d,j.settings.forced_root_block_attrs)):d=0})):ha(a)&&!ha(e)&&(c(a,ma)||c(a.firstChild,na,1)||a.insertBefore(da.create("br"),a.firstChild),c(a,na)||c(a.lastChild,ma,1)||a.appendChild(da.create("br")))),b.selector&&b.inline&&!H(b.inline,a)||da.remove(a,1)}function V(a,b,c){if(a)for(b=b?"nextSibling":"previousSibling",a=c?a:a[b];a;a=a[b])if(1==a.nodeType||!P(a))return a}function W(a,b){function c(a,b){for(e=a;e;e=e[b]){if(3==e.nodeType&&0!==e.nodeValue.length)return a;if(1==e.nodeType&&!pa(e))return e}return a}var e,f,g=new d(da);if(a&&b&&(a=c(a,"previousSibling"),b=c(b,"nextSibling"),g.compare(a,b))){for(e=a.nextSibling;e&&e!=b;)f=e,e=e.nextSibling,a.appendChild(f);return da.remove(b),qa(ra(b.childNo
des),function(b){a.appendChild(b)}),a}return b}function X(b,c){var d,e,f;return d=b[c?"startContainer":"endContainer"],e=b[c?"startOffset":"endOffset"],1==d.nodeType&&(f=d.childNodes.length-1,!c&&e&&e--,d=d.childNodes[e>f?f:e]),3===d.nodeType&&c&&e>=d.nodeValue.length&&(d=new a(d,j.getBody()).next()||d),3!==d.nodeType||c||0!==e||(d=new a(d,j.getBody()).prev()||d),d}function Y(b,c,d,e){function f(a){var b=da.create("span",{id:p,"data-mce-bogus":!0,style:q?"color:red":""});return a&&b.appendChild(j.getDoc().createTextNode(ka)),b}function g(a,b){for(;a;){if(3===a.nodeType&&a.nodeValue!==ka||a.childNodes.length>1)return!1;b&&1===a.nodeType&&b.push(a),a=a.firstChild}return!0}function h(a){for(;a;){if(a.id===p)return a;a=a.parentNode}}function i(b){var c;if(b)for(c=new a(b,b),b=c.current();b;b=c.next())if(3===b.nodeType)re
turn b}function l(a,b){var c,d;if(a)d=ea.getRng(!0),g(a)?(b!==!1&&(d.setStartBefore(a),d.setEndBefore(a)),da.remove(a)):(c=i(a),c.nodeValue.charAt(0)===ka&&(c.deleteData(0,1),d.startContainer==c&&d.startOffset>0&&d.setStart(c,d.startOffset-1),d.endContainer==c&&d.endOffset>0&&d.setEnd(c,d.endOffset-1)),da.remove(a,1)),ea.setRng(d);else if(a=h(ea.getStart()),!a)for(;a=da.get(p);)l(a,!1)}function m(){var a,b,e,g,j,k,l;a=ea.getRng(!0),g=a.startOffset,k=a.startContainer,l=k.nodeValue,b=h(ea.getStart()),b&&(e=i(b));var m=/[^\s\u00a0\u00ad\u200b\ufeff]/;l&&g>0&&g<l.length&&m.test(l.charAt(g))&&m.test(l.charAt(g-1))?(j=ea.getBookmark(),a.collapse(!0),a=R(a,r(c)),a=fa.split(a),x(c,d,a),ea.moveToBookmark(j)):(b&&e.nodeValue===ka?x(c,d,b):(b=f(!0),e=b.firstChild,a.insertNode(b),g=1,x(c,d,b)),ea.setCursorLocation(e,g))}function n(){var a,b,g,h,i,j,l,m,n=ea.getRng(!0),o=[];for(a=n.startCo
ntainer,b=n.startOffset,i=a,3==a.nodeType&&(b!=a.nodeValue.length&&(h=!0),i=i.parentNode);i;){if(A(i,c,d,e)){j=i;break}i.nextSibling&&(h=!0),o.push(i),i=i.parentNode}if(j)if(h)g=ea.getBookmark(),n.collapse(!0),n=R(n,r(c),!0),n=fa.split(n),y(c,d,n),ea.moveToBookmark(g);else{for(m=f(),i=m,l=o.length-1;l>=0;l--)i.appendChild(da.clone(o[l],!1)),i=i.firstChild;i.appendChild(da.doc.createTextNode(ka)),i=i.firstChild;var p=da.getParent(j,k);p&&da.isEmpty(p)?j.parentNode.replaceChild(m,j):da.insertAfter(m,j),ea.setCursorLocation(i,1),da.isEmpty(j)&&da.remove(j)}}function o(){var a;a=h(ea.getStart()),a&&!da.isEmpty(a)&&sa(a,function(a){1!=a.nodeType||a.id===p||da.isEmpty(a)||da.setAttrib(a,"data-mce-bogus",null)},"childNodes")}var p="_mce_caret",q=j.settings.caret_debug;j._hasCaretEvents||(ba=function(){var a,b=[];if(g(h(ea.getStart()),b))for(a=b.length;a--;)da.setAttrib(b[a],"data-mce-bogus",&
quot;1")},aa=function(a){var b=a.keyCode;l(),8==b&&ea.isCollapsed()&&ea.getStart().innerHTML==ka&&l(h(ea.getStart())),37!=b&&39!=b||l(h(ea.getStart())),o()},j.on("SetContent",function(a){a.selection&&o()}),j._hasCaretEvents=!0),"apply"==b?m():n()}function Z(b){var c,d,e,f,g,h=b.startContainer,i=b.startOffset;if((b.startContainer!=b.endContainer||!m(b.startContainer.childNodes[b.startOffset]))&&(3==h.nodeType&&i>=h.nodeValue.length&&(i=ja(h),h=h.parentNode,c=!0),1==h.nodeType))for(f=h.childNodes,h=f[Math.min(i,f.length-1)],d=new a(h,da.getParent(h,da.isBlock)),(i>f.length-1||c)&&d.next(),e=d.current();e;e=d.next())if(3==e.nodeType&&!P(e))return g=da.create("a",{"data-mce-bogus":"all"},ka),e.parentNode.insertBefore(g,e),b.setStart(e,0),ea.setRng(b),void da.remove(g)}var $,_,aa,ba,ca={},da=j.dom,ea=j.selection,fa=new b(da),ga=j.schema.isValidChild
,ha=da.isBlock,ia=j.settings.forced_root_block,ja=da.nodeIndex,ka="\ufeff",la=/^(src|href|style)$/,ma=!1,na=!0,oa=da.getContentEditable,pa=c.isBookmarkNode,qa=g.each,ra=g.grep,sa=g.walk,ta=g.extend;ta(this,{get:r,register:s,unregister:t,apply:x,remove:y,toggle:z,match:B,matchAll:C,matchNode:A,canApply:D,formatChanged:E,getCssText:F}),p(),q(),j.on("BeforeGetContent",function(a){ba&&"raw"!=a.format&&ba()}),j.on("mouseup keydown",function(a){aa&&aa(a)})}}),g("4o",[],function(){var a=0,b=1,c=2,d=function(d,e){var f=d.length+e.length+2,g=new Array(f),h=new Array(f),i=function(a,b,c){return{start:a,end:b,diag:c}},j=function(f,g,h,i,k){var m=l(f,g,h,i);if(null===m||m.start===g&&m.diag===g-i||m.end===f&&m.diag===f-h)for(var n=f,o=h;n<g||o<i;)n<g&&o<i&&d[n]===e[o]?(k.push([a,d[n]]),++n,++o):g-f>i-h?(k.push([c,d[n]]),++n):(k.push([b,e[o]]),++o);else{j(f,m.start,h,m.start-m.
diag,k);for(var p=m.start;p<m.end;++p)k.push([a,d[p]]);j(m.end,g,m.end-m.diag,i,k)}},k=function(a,b,c,f){for(var g=a;g-b<f&&g<c&&d[g]===e[g-b];)++g;return i(a,g,b)},l=function(a,b,c,f){var i=b-a,j=f-c;if(0===i||0===j)return null;var l=i-j,m=j+i,n=(m%2===0?m:m+1)/2;g[1+n]=a,h[1+n]=b+1;for(var o=0;o<=n;++o){for(var p=-o;p<=o;p+=2){var q=p+n;p===-o||p!=o&&g[q-1]<g[q+1]?g[q]=g[q+1]:g[q]=g[q-1]+1;for(var r=g[q],s=r-a+c-p;r<b&&s<f&&d[r]===e[s];)g[q]=++r,++s;if(l%2!=0&&l-o<=p&&p<=l+o&&h[q-l]<=g[q])return k(h[q-l],p+a-c,b,f)}for(p=l-o;p<=l+o;p+=2){for(q=p+n-l,p===l-o||p!=l+o&&h[q+1]<=h[q-1]?h[q]=h[q+1]-1:h[q]=h[q-1],r=h[q]-1,s=r-a+c-p;r>=a&&s>=c&&d[r]===e[s];)h[q]=r--,s--;if(l%2===0&&-o<=p&&p<=o&&h[q]<=g[q+l])return k(h[q],p+a-c,b,f)}}},m=[];return j(0,d.length,0,e.length,m),m};return{KEEP:a,DELETE:c,INSERT:b,diff:d}}),g("
3z",["1g","d","4o"],function(a,b,c){var d=function(a){return 1===a.nodeType?a.outerHTML:3===a.nodeType?b.encodeRaw(a.data,!1):8===a.nodeType?"<!--"+a.data+"-->":""},e=function(a){var b,c,d;for(d=document.createElement("div"),b=document.createDocumentFragment(),a&&(d.innerHTML=a);c=d.firstChild;)b.appendChild(c);return b},f=function(a,b,c){var d=e(b);if(a.hasChildNodes()&&c<a.childNodes.length){var f=a.childNodes[c];f.parentNode.insertBefore(d,f)}else a.appendChild(d)},g=function(a,b){if(a.hasChildNodes()&&b<a.childNodes.length){var c=a.childNodes[b];c.parentNode.removeChild(c)}},h=function(b,d){var e=0;a.each(b,function(a){a[0]===c.KEEP?e++:a[0]===c.INSERT?(f(d,a[1],e),e++):a[0]===c.DELETE&&g(d,e)})},i=function(b){return a.map(b.childNodes,d)},j=function(b,e){var f=a.map(e.childNodes,d);return h(c.diff(f,b),e),e};return{read:i,write:j}}),g("1u",["1g&q
uot;,"3z"],function(a,b){var c=function(a){return a.indexOf("</iframe>")!==-1},d=function(a){return{type:"fragmented",fragments:a,content:"",bookmark:null,beforeBookmark:null}},e=function(a){return{type:"complete",fragments:null,content:a,bookmark:null,beforeBookmark:null}},f=function(f){var g,h,i;return g=b.read(f.getBody()),i=a.map(g,function(a){return f.serializer.trimContent(a)}),h=i.join(""),c(h)?d(i):e(h)},g=function(a,c,d){"fragmented"===c.type?b.write(c.fragments,a.getBody()):a.setContent(c.content,{format:"raw"}),a.selection.moveToBookmark(d?c.beforeBookmark:c.bookmark)},h=function(a){return"fragmented"===a.type?a.fragments.join(""):a.content},i=function(a,b){return h(a)===h(b)};return{createFragmentedLevel:d,createCompleteLevel:e,createFromEditor:f,applyToEditor:g,isEq:i}}),g("u",["p","9","1u"],function(a,b,c){return function(a){
function d(b){a.setDirty(b)}function e(a){n(!1),i.add({},a)}function f(){i.typing&&(n(!1),i.add())}var g,h,i=this,j=0,k=[],l=0,m=function(){return 0===l},n=function(a){m()&&(i.typing=a)};return a.on("init",function(){i.add()}),a.on("BeforeExecCommand",function(a){var b=a.command;"Undo"!==b&&"Redo"!==b&&"mceRepaint"!==b&&(f(),i.beforeChange())}),a.on("ExecCommand",function(a){var b=a.command;"Undo"!==b&&"Redo"!==b&&"mceRepaint"!==b&&e(a)}),a.on("ObjectResizeStart Cut",function(){i.beforeChange()}),a.on("SaveContent ObjectResized blur",e),a.on("DragEnd",e),a.on("KeyUp",function(b){var f=b.keyCode;b.isDefaultPrevented()||((f>=33&&f<=36||f>=37&&f<=40||45===f||b.ctrlKey)&&(e(),a.nodeChanged()),46!==f&&8!==f||a.nodeChanged(),h&&i.typing&&c
.isEq(c.createFromEditor(a),k[0])===!1&&(a.isDirty()===!1&&(d(!0),a.fire("change",{level:k[0],lastLevel:null})),a.fire("TypingUndo"),h=!1,a.nodeChanged()))}),a.on("KeyDown",function(a){var b=a.keyCode;if(!a.isDefaultPrevented()){if(b>=33&&b<=36||b>=37&&b<=40||45===b)return void(i.typing&&e(a));var c=a.ctrlKey&&!a.altKey||a.metaKey;!(b<16||b>20)||224===b||91===b||i.typing||c||(i.beforeChange(),n(!0),i.add({},a),h=!0)}}),a.on("MouseDown",function(a){i.typing&&e(a)}),a.addShortcut("meta+z","","Undo"),a.addShortcut("meta+y,meta+shift+z","","Redo"),a.on("AddUndo Undo Redo ClearUndos",function(b){b.isDefaultPrevented()||a.nodeChanged()}),i={data:k,typing:!1,beforeChange:function(){m()&&(g=a.selection.getBookmark(2,!0))},add:function(e,f){var h,i,l,n=a.settings;if(l=c.createFromEditor(a),e=e||{},e=b.e
xtend(e,l),m()===!1||a.removed)return null;if(i=k[j],a.fire("BeforeAddUndo",{level:e,lastLevel:i,originalEvent:f}).isDefaultPrevented())return null;if(i&&c.isEq(i,e))return null;if(k[j]&&(k[j].beforeBookmark=g),n.custom_undo_redo_levels&&k.length>n.custom_undo_redo_levels){for(h=0;h<k.length-1;h++)k[h]=k[h+1];k.length--,j=k.length}e.bookmark=a.selection.getBookmark(2,!0),j<k.length-1&&(k.length=j+1),k.push(e),j=k.length-1;var o={level:e,lastLevel:i,originalEvent:f};return a.fire("AddUndo",o),j>0&&(d(!0),a.fire("change",o)),e},undo:function(){var b;return i.typing&&(i.add(),i.typing=!1,n(!1)),j>0&&(b=k[--j],c.applyToEditor(a,b,!0),d(!0),a.fire("undo",{level:b})),b},redo:function(){var b;return j<k.length-1&&(b=k[++j],c.applyToEditor(a,b,!1),d(!0),a.fire("redo",{level:b})),b},clear:function(){k=[],j=0,i.typing=!1,i.data=k,a.fire("ClearUndos")},h
asUndo:function(){return j>0||i.typing&&k[0]&&!c.isEq(c.createFromEditor(a),k[0])},hasRedo:function(){return j<k.length-1&&!i.typing},transact:function(a){return f(),i.beforeChange(),i.ignore(a),i.add()},ignore:function(a){try{l++,a()}finally{l--}},extra:function(b,d){var e,f;i.transact(b)&&(f=k[j].bookmark,e=k[j-1],c.applyToEditor(a,e,!0),i.transact(d)&&(k[j-1].beforeBookmark=f))}}}}),g("4r",["4h"],function(a){var b=function(a){for(var b=[],c=function(a){b.push(a)},d=0;d<a.length;d++)a[d].each(c);return b},c=function(b,c){for(var d=0;d<b.length;d++){var e=c(b[d],d);if(e.isSome())return e}return a.none()},d=function(b,c){for(var d=[],e=0;e<b.length;e++){var f=b[e];if(!f.isSome())return a.none();d.push(f.getOrDie())}return a.some(c.apply(null,d))};return{cat:b,findMap:c,liftN:d}}),g("5v",["3r","3s","4i","4j"],function(a,b,c,d){return function(){var e=arguments;
return function(){for(var f=new c(arguments.length),g=0;g<f.length;g++)f[g]=arguments[g];if(e.length!==f.length)throw new d('Wrong number of arguments to struct. Expected "['+e.length+']", got '+f.length+" arguments");var h={};return a.each(e,function(a,c){h[a]=b.constant(f[c])}),h}}}),g("68",["4h","55"],function(a,b){var c=function(){var a=b.keys,c=function(a){var b=[];for(var c in a)a.hasOwnProperty(c)&&b.push(c);return b};return void 0===a?c:a}(),d=function(a,b){for(var d=c(a),e=0,f=d.length;e<f;e++){var g=d[e],h=a[g];b(h,g,a)}},e=function(a,b){return f(a,function(a,c,d){return{k:c,v:b(a,c,d)}})},f=function(a,b){var c={};return d(a,function(d,e){var f=b(d,e,a);c[f.k]=f.v}),c},g=function(a,b){var c={},e={};return d(a,function(a,d){var f=b(a,d)?c:e;f[d]=a}),{t:c,f:e}},h=function(a,b){var c=[];return d(a,function(a,d){c.push(b(a,d))}),c},i=function(b,d){for(var e=c(b),f=0,g=e.length;f<g;f++){var h=e[f],i=b[h];if(d(i,
h,b))return a.some(i)}return a.none()},j=function(a){return h(a,function(a){return a})},k=function(a){return j(a).length};return{bifilter:g,each:d,map:e,mapToArray:h,tupleMap:f,find:i,keys:c,values:j,size:k}}),g("62",["4i","4k"],function(a,b){var c=function(c){if(null===c)return"null";var d=typeof c;return"object"===d&&a.prototype.isPrototypeOf(c)?"array":"object"===d&&b.prototype.isPrototypeOf(c)?"string":d},d=function(a){return function(b){return c(b)===a}};return{isString:d("string"),isObject:d("object"),isArray:d("array"),isNull:d("null"),isBoolean:d("boolean"),isUndefined:d("undefined"),isFunction:d("function"),isNumber:d("number")}}),g("6m",["3r","62","4j"],function(a,b,c){var d=function(a){return a.slice(0).sort()},e=function(a,b){throw new c("All required ke
ys ("+d(a).join(", ")+") were not specified. Specified keys were: "+d(b).join(", ")+".")},f=function(a){throw new c("Unsupported keys for object: "+d(a).join(", "))},g=function(d,e){if(!b.isArray(e))throw new c("The "+d+" fields must be an array. Was: "+e+".");a.each(e,function(a){if(!b.isString(a))throw new c("The value "+a+" in the "+d+" fields was not a string.")})},h=function(a,b){throw new c("All values need to be of type: "+b+". Keys ("+d(a).join(", ")+") were not.")},i=function(b){var e=d(b),f=a.find(e,function(a,b){return b<e.length-1&&a===e[b+1]});f.each(function(a){throw new c("The field: "+a+" occurs more than once in the combined fields: ["+e.join(", ")+"].")})};return{sort:d,reqMessage:e,unsuppMessage:f,validateStrArr:g,invalidTypeMessage:h,checkDupes:i}}),g
("5w",["3r","3s","68","4h","6m","4j","55"],function(a,b,c,d,e,f,g){return function(h,i){var j=h.concat(i);if(0===j.length)throw new f("You must specify at least one required or optional field.");return e.validateStrArr("required",h),e.validateStrArr("optional",i),e.checkDupes(j),function(f){var k=c.keys(f),l=a.forall(h,function(b){return a.contains(k,b)});l||e.reqMessage(h,k);var m=a.filter(k,function(b){return!a.contains(j,b)});m.length>0&&e.unsuppMessage(m);var n={};return a.each(h,function(a){n[a]=b.constant(f[a])}),a.each(i,function(a){n[a]=b.constant(g.prototype.hasOwnProperty.call(f,a)?d.some(f[a]):d.none())}),n}}}),g("57",["5v","5w"],function(a,b){return{immutable:a,immutableBag:b}}),g("70",[],function(){return Function("return this;")();
+}),g("6n",["70"],function(a){var b=function(b,c){for(var d=void 0!==c?c:a,e=0;e<b.length&&void 0!==d&&null!==d;++e)d=d[b[e]];return d},c=function(a,c){var d=a.split(".");return b(d,c)},d=function(a,b){return void 0!==a[b]&&null!==a[b]||(a[b]={}),a[b]},e=function(b,c){for(var e=void 0!==c?c:a,f=0;f<b.length;++f)e=d(e,b[f]);return e},f=function(a,b){var c=a.split(".");return e(c,b)};return{path:b,resolve:c,forge:e,namespace:f}}),g("5x",["6n"],function(a){var b=function(b,c){return a.resolve(b,c)},c=function(a,c){var d=b(a,c);if(void 0===d)throw a+" not available on this browser";return d};return{getOrDie:c}}),g("58",["5x"],function(a){var b=function(){var b=a.getOrDie("Node");return b},c=function(a,b,c){return 0!==(a.compareDocumentPosition(b)&c)},d=function(a,d){return c(a,d,b().DOCUMENT_POSITION_PRECEDING)},e=function(a,d){return c(a,d,b().DOCUMENT_PO
SITION_CONTAINED_BY)};return{documentPositionPreceding:d,documentPositionContainedBy:e}}),g("5y",[],function(){var a=function(a){var b,c=!1;return function(){return c||(c=!0,b=a.apply(null,arguments)),b}};return{cached:a}}),h("74",Number),g("71",["3r","74","4k"],function(a,b,c){var d=function(a,b){for(var c=0;c<a.length;c++){var d=a[c];if(d.test(b))return d}},e=function(a,c){var e=d(a,c);if(!e)return{major:0,minor:0};var f=function(a){return b(c.replace(e,"$"+a))};return h(f(1),f(2))},f=function(a,b){var d=c(b).toLowerCase();return 0===a.length?g():e(a,d)},g=function(){return h(0,0)},h=function(a,b){return{major:a,minor:b}};return{nu:h,detect:f,unknown:g}}),g("6o",["3s","71"],function(a,b){var c="Edge",d="Chrome",e="IE",f="Opera",g="Firefox",h="Safari",i=function(a,b){return function(){return b===a}},j=function(){return k(
{current:void 0,version:b.unknown()})},k=function(a){var b=a.current,j=a.version;return{current:b,version:j,isEdge:i(c,b),isChrome:i(d,b),isIE:i(e,b),isOpera:i(f,b),isFirefox:i(g,b),isSafari:i(h,b)}};return{unknown:j,nu:k,edge:a.constant(c),chrome:a.constant(d),ie:a.constant(e),opera:a.constant(f),firefox:a.constant(g),safari:a.constant(h)}}),g("6p",["3s","71"],function(a,b){var c="Windows",d="iOS",e="Android",f="Linux",g="OSX",h="Solaris",i="FreeBSD",j=function(a,b){return function(){return b===a}},k=function(){return l({current:void 0,version:b.unknown()})},l=function(a){var b=a.current,k=a.version;return{current:b,version:k,isWindows:j(c,b),isiOS:j(d,b),isAndroid:j(e,b),isOSX:j(g,b),isLinux:j(f,b),isSolaris:j(h,b),isFreeBSD:j(i,b)}};return{unknown:k,nu:l,windows:a.constant(c),ios:a.constant(d),android:a.constant(e),linux:a.constant(f),osx:a.constant(g),solaris:a.constant(h),freebsd
:a.constant(i)}}),g("6q",["3s"],function(a){return function(b,c,d){var e=b.isiOS()&&/ipad/i.test(d)===!0,f=b.isiOS()&&!e,g=b.isAndroid()&&3===b.version.major,h=b.isAndroid()&&4===b.version.major,i=e||g||h&&/mobile/i.test(d)===!0,j=b.isiOS()||b.isAndroid(),k=j&&!i,l=c.isSafari()&&b.isiOS()&&/safari/i.test(d)===!1;return{isiPad:a.constant(e),isiPhone:a.constant(f),isTablet:a.constant(i),isPhone:a.constant(k),isTouch:a.constant(j),isAndroid:b.isAndroid,isiOS:b.isiOS,isWebView:a.constant(l)}}}),g("6r",["3r","71","4k"],function(a,b,c){var d=function(b,d){var e=c(d).toLowerCase();return a.find(b,function(a){return a.search(e)})},e=function(a,c){return d(a,c).map(function(a){var d=b.detect(a.versionRegexes,c);return{current:a.name,version:d}})},f=function(a,c){return d(a,c).map(function(a){var d=b.detect(a.versionRegexes,c);return{current:a.name,version:d}})};return{d
etectBrowser:e,detectOs:f}}),g("75",[],function(){var a=function(a,b){return b+a},b=function(a,b){return a+b},c=function(a,b){return a.substring(b)},d=function(a,b){return a.substring(0,a.length-b)};return{addToStart:a,addToEnd:b,removeFromStart:c,removeFromEnd:d}}),g("76",["4h","4j"],function(a,b){var c=function(a,b){return a.substr(0,b)},d=function(a,b){return a.substr(a.length-b,a.length)},e=function(b){return""===b?a.none():a.some(b.substr(0,1))},f=function(b){return""===b?a.none():a.some(b.substring(1))};return{first:c,last:d,head:e,tail:f}}),g("72",["75","76","4j"],function(a,b,c){var d=function(a,b,c){if(""===b)return!0;if(a.length<b.length)return!1;var d=a.substr(c,c+b.length);return d===b},e=function(a,b){var c=function(a){var b=typeof a;return"string"===b||"number"===b};return a.replace(/\${([^{}]*)}/g,function(a,d){var e=b[d];return c(e)?e:a
})},f=function(b,c){return l(b,c)?a.removeFromStart(b,c.length):b},g=function(b,c){return m(b,c)?a.removeFromEnd(b,c.length):b},h=function(b,c){return l(b,c)?b:a.addToStart(b,c)},i=function(b,c){return m(b,c)?b:a.addToEnd(b,c)},j=function(a,b){return a.indexOf(b)!==-1},k=function(a){return b.head(a).bind(function(c){return b.tail(a).map(function(a){return c.toUpperCase()+a})}).getOr(a)},l=function(a,b){return d(a,b,0)},m=function(a,b){return d(a,b,a.length-b.length)},n=function(a){return a.replace(/^\s+|\s+$/g,"")},o=function(a){return a.replace(/^\s+/g,"")},p=function(a){return a.replace(/\s+$/g,"")};return{supplant:e,startsWith:l,removeLeading:f,removeTrailing:g,ensureLeading:h,ensureTrailing:i,endsWith:m,contains:j,trim:n,lTrim:o,rTrim:p,capitalize:k}}),g("6s",["3s","72"],function(a,b){var c=/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,d=function(a){return function(c){return b.contains(c,a)}},e=[{name:"Edge",versionRe
gexes:[/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],search:function(a){var c=b.contains(a,"edge/")&&b.contains(a,"chrome")&&b.contains(a,"safari")&&b.contains(a,"applewebkit");return c}},{name:"Chrome",versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/,c],search:function(a){return b.contains(a,"chrome")&&!b.contains(a,"chromeframe")}},{name:"IE",versionRegexes:[/.*?msie\ ?([0-9]+)\.([0-9]+).*/,/.*?rv:([0-9]+)\.([0-9]+).*/],search:function(a){return b.contains(a,"msie")||b.contains(a,"trident")}},{name:"Opera",versionRegexes:[c,/.*?opera\/([0-9]+)\.([0-9]+).*/],search:d("opera")},{name:"Firefox",versionRegexes:[/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],search:d("firefox")},{name:"Safari",versionRegexes:[c,/.*?cpu os ([0-9]+)_([0-9]+).*/],search:function(a){return(b.contains(a,"safari")||b.contains(a,"mobi
le/"))&&b.contains(a,"applewebkit")}}],f=[{name:"Windows",search:d("win"),versionRegexes:[/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]},{name:"iOS",search:function(a){return b.contains(a,"iphone")||b.contains(a,"ipad")},versionRegexes:[/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,/.*cpu os ([0-9]+)_([0-9]+).*/,/.*cpu iphone os ([0-9]+)_([0-9]+).*/]},{name:"Android",search:d("android"),versionRegexes:[/.*?android\ ?([0-9]+)\.([0-9]+).*/]},{name:"OSX",search:d("os x"),versionRegexes:[/.*?os\ x\ ?([0-9]+)_([0-9]+).*/]},{name:"Linux",search:d("linux"),versionRegexes:[]},{name:"Solaris",search:d("sunos"),versionRegexes:[]},{name:"FreeBSD",search:d("freebsd"),versionRegexes:[]}];return{browsers:a.constant(e),oses:a.constant(f)}}),g("5z",["6o","6p","6q","6r","6s"],functio
n(a,b,c,d,e){var f=function(f){var g=e.browsers(),h=e.oses(),i=d.detectBrowser(g,f).fold(a.unknown,a.nu),j=d.detectOs(h,f).fold(b.unknown,b.nu),k=c(j,i,f);return{browser:i,os:j,deviceType:k}};return{detect:f}}),h("60",navigator),g("59",["5y","5z","60"],function(a,b,c){var d=a.cached(function(){var a=c.userAgent;return b.detect(a)});return{detect:d}}),g("5b",[],function(){return"undefined"==typeof console&&(console={log:function(){}}),console}),h("1x",document),g("4t",["3s","4j","5b","1x"],function(a,b,c,d){var e=function(a,b){var e=b||d,f=e.createElement("div");if(f.innerHTML=a,!f.hasChildNodes()||f.childNodes.length>1)throw c.error("HTML does not have a single root node",a),"HTML must have a single root node";return h(f.childNodes[0])},f=function(a,b){var c=b||d,e=c.createElement(a);return h(e)},g=function(a,b){va
r c=b||d,e=c.createTextNode(a);return h(e)},h=function(c){if(null===c||void 0===c)throw new b("Node cannot be null or undefined");return{dom:a.constant(c)}};return{fromHtml:e,fromTag:f,fromText:g,fromDom:h}}),g("61",[],function(){return{ATTRIBUTE:2,CDATA_SECTION:4,COMMENT:8,DOCUMENT:9,DOCUMENT_TYPE:10,DOCUMENT_FRAGMENT:11,ELEMENT:1,TEXT:3,PROCESSING_INSTRUCTION:7,ENTITY_REFERENCE:5,ENTITY:6,NOTATION:12}}),g("5a",["3r","4h","4t","61","4j","1x"],function(a,b,c,d,e,f){var g=0,h=1,i=2,j=3,k=function(){var a=f.createElement("span");return void 0!==a.matches?g:void 0!==a.msMatchesSelector?h:void 0!==a.webkitMatchesSelector?i:void 0!==a.mozMatchesSelector?j:-1}(),l=d.ELEMENT,m=d.DOCUMENT,n=function(a,b){var c=a.dom();if(c.nodeType!==l)return!1;if(k===g)return c.matches(b);if(k===h)return c.msMatchesSelector(b);if(k===i)return c.webkitMatchesSelector(b);if(k===j)return c.mozMatchesSelector(b)
;throw new e("Browser lacks native selectors")},o=function(a){return a.nodeType!==l&&a.nodeType!==m||0===a.childElementCount},p=function(b,d){var e=void 0===d?f:d.dom();return o(e)?[]:a.map(e.querySelectorAll(b),c.fromDom)},q=function(a,d){var e=void 0===d?f:d.dom();return o(e)?b.none():b.from(e.querySelector(a)).map(c.fromDom)};return{all:p,is:n,one:q}}),g("4s",["3r","3s","58","59","5a"],function(a,b,c,d,e){var f=function(a,b){return a.dom()===b.dom()},g=function(a,b){return a.dom().isEqualNode(b.dom())},h=function(c,d){return a.exists(d,b.curry(f,c))},i=function(a,b){var c=a.dom(),d=b.dom();return c!==d&&c.contains(d)},j=function(a,b){return c.documentPositionContainedBy(a.dom(),b.dom())},k=d.detect().browser,l=k.isIE()?j:i;return{eq:f,isEqualNode:g,member:h,contains:l,is:e.is}}),g("5c",["61"],function(a){var b=function(a){var b=a.dom().nodeName;return b.toLowerCase()},c=funct
ion(a){return a.dom().nodeType},d=function(a){return a.dom().nodeValue},e=function(a){return function(b){return c(b)===a}},f=function(d){return c(d)===a.COMMENT||"#comment"===b(d)},g=e(a.ELEMENT),h=e(a.TEXT),i=e(a.DOCUMENT);return{name:b,type:c,value:d,isElement:g,isText:h,isDocument:i,isComment:f}}),g("63",["5y","4t","5c","1x"],function(a,b,c,d){var e=function(a){var b=c.isText(a)?a.dom().parentNode:a.dom();return void 0!==b&&null!==b&&b.ownerDocument.body.contains(b)},f=a.cached(function(){return g(b.fromDom(d))}),g=function(a){var c=a.dom().body;if(null===c||void 0===c)throw"Body is not available yet";return b.fromDom(c)};return{body:f,getBody:g,inBody:e}}),g("64",["62","4h"],function(a,b){return function(c,d,e,f,g){return c(e,f)?b.some(e):a.isFunction(g)&&g(e)?b.none():d(e,f,g)}}),g("5d",["62","3r","3s","4h"
,"63","4s","4t","64"],function(a,b,c,d,e,f,g,h){var i=function(a){return n(e.body(),a)},j=function(b,e,f){for(var h=b.dom(),i=a.isFunction(f)?f:c.constant(!1);h.parentNode;){h=h.parentNode;var j=g.fromDom(h);if(e(j))return d.some(j);if(i(j))break}return d.none()},k=function(a,b,c){var d=function(a){return b(a)};return h(d,j,a,b,c)},l=function(a,b){var c=a.dom();return c.parentNode?m(g.fromDom(c.parentNode),function(c){return!f.eq(a,c)&&b(c)}):d.none()},m=function(a,d){var e=b.find(a.dom().childNodes,c.compose(d,g.fromDom));return e.map(g.fromDom)},n=function(a,b){var c=function(a){for(var e=0;e<a.childNodes.length;e++){if(b(g.fromDom(a.childNodes[e])))return d.some(g.fromDom(a.childNodes[e]));var f=c(a.childNodes[e]);if(f.isSome())return f}return d.none()};return c(a.dom())};return{first:i,ancestor:j,closest:k,sibling:l,child:m,descendant:n}}),g("65",[],function(){var a=function(a,b){var c=[],d=function(a){return c.push(a)
,b(a)},e=b(a);do e=e.bind(d);while(e.isSome());return c};return{toArray:a}}),g("5e",["62","3r","3s","4h","57","65","4s","4t"],function(a,b,c,d,e,f,g,h){var i=function(a){return h.fromDom(a.dom().ownerDocument)},j=function(a){var b=i(a);return h.fromDom(b.dom().documentElement)},k=function(a){var b=a.dom(),c=b.ownerDocument.defaultView;return h.fromDom(c)},l=function(a){var b=a.dom();return d.from(b.parentNode).map(h.fromDom)},m=function(a){return l(a).bind(function(c){var d=u(c);return b.findIndex(d,function(b){return g.eq(a,b)})})},n=function(b,d){for(var e=a.isFunction(d)?d:c.constant(!1),f=b.dom(),g=[];null!==f.parentNode&&void 0!==f.parentNode;){var i=f.parentNode,j=h.fromDom(i);if(g.push(j),e(j)===!0)break;f=i}return g},o=function(a){var c=function(c){return b.filter(c,function(b){return!g.eq(a,b)})};return l(a).map(u).map(c).getOr([])},p=function(a){var b=a.dom();return d.from(b.o
ffsetParent).map(h.fromDom)},q=function(a){var b=a.dom();return d.from(b.previousSibling).map(h.fromDom)},r=function(a){var b=a.dom();return d.from(b.nextSibling).map(h.fromDom)},s=function(a){return b.reverse(f.toArray(a,q))},t=function(a){return f.toArray(a,r)},u=function(a){var c=a.dom();return b.map(c.childNodes,h.fromDom)},v=function(a,b){var c=a.dom().childNodes;return d.from(c[b]).map(h.fromDom)},w=function(a){return v(a,0)},x=function(a){return v(a,a.dom().childNodes.length-1)},y=e.immutable("element","offset"),z=function(a,b){var c=u(a);return c.length>0&&b<c.length?y(c[b],0):y(a,b)};return{owner:i,defaultView:k,documentElement:j,parent:l,findIndex:m,parents:n,siblings:o,prevSibling:q,offsetParent:p,prevSiblings:s,nextSibling:r,nextSiblings:t,children:u,child:v,firstChild:w,lastChild:x,leaf:z}}),g("4v",["1r","c","1j","1n","1k","3w"],function(a,b,c,d,e,f){function g(a){ret
urn a>0}function h(a){return a<0}function i(a,b){for(var c;c=a(b);)if(!y(c))return c;return null}function j(a,c,d,e,f){var j=new b(a,e);if(h(c)){if((v(a)||y(a))&&(a=i(j.prev,!0),d(a)))return a;for(;a=i(j.prev,f);)if(d(a))return a}if(g(c)){if((v(a)||y(a))&&(a=i(j.next,!0),d(a)))return a;for(;a=i(j.next,f);)if(d(a))return a}return null}function k(a,b){for(a=a.parentNode;a&&a!=b;a=a.parentNode)if(u(a))return a;return b}function l(a,b){for(;a&&a!=b;){if(w(a))return a;a=a.parentNode}return null}function m(a,b,c){return l(a.container(),c)==l(b.container(),c)}function n(a,b,c){return k(a.container(),c)==k(b.container(),c)}function o(a,b){var c,d;return b?(c=b.container(),d=b.offset(),A(c)?c.childNodes[d+a]:null):null}function p(a,b){var c=b.ownerDocument.createRange();return a?(c.setStartBefore(b),c.setEndBefore(b)):(c.setStartAfter(b),c.setEndAfter(b)),c}function q(a,b,c){return l(b,a)==l(c,a)}function r(a,b,c){var d,e;for(e=a?"previousSibling&qu
ot;:"nextSibling";c&&c!=b;){if(d=c[e],x(d)&&(d=d[e]),v(d)){if(q(b,d,c))return d;break}if(B(d))break;c=c.parentNode}return null}function s(a,b,d){var f,g,h,i,j=z(r,!0,b),k=z(r,!1,b);if(g=d.startContainer,h=d.startOffset,e.isCaretContainerBlock(g)){if(A(g)||(g=g.parentNode),i=g.getAttribute("data-mce-caret"),"before"==i&&(f=g.nextSibling,v(f)))return C(f);if("after"==i&&(f=g.previousSibling,v(f)))return D(f)}if(!d.collapsed)return d;if(c.isText(g)){if(x(g)){if(1===a){if(f=k(g))return C(f);if(f=j(g))return D(f)}if(a===-1){if(f=j(g))return D(f);if(f=k(g))return C(f)}return d}if(e.endsWithCaretContainer(g)&&h>=g.data.length-1)return 1===a&&(f=k(g))?C(f):d;if(e.startsWithCaretContainer(g)&&h<=1)return a===-1&&(f=j(g))?D(f):d;if(h===g.data.length)return f=k(g),f?C(f):d;if(0===h)return f=j(g),f?D(f):d}return d}function t(a,b){return v(o(a,b))}var u=c.isContentEditableTrue,v=c.isCont
entEditableFalse,w=c.matchStyleValues("display","block table table-cell table-caption"),x=e.isCaretContainer,y=e.isCaretContainerBlock,z=a.curry,A=c.isElement,B=f.isCaretCandidate,C=z(p,!0),D=z(p,!1);return{isForwards:g,isBackwards:h,findNode:j,getEditingHost:k,getParentBlock:l,isInSameBlock:m,isInSameEditingHost:n,isBeforeContentEditableFalse:z(t,0),isAfterContentEditableFalse:z(t,-1),normalizeRange:s}}),g("44",["1j","3w","1n","4v","1g","1r"],function(a,b,c,d,e,f){function g(a,b){for(var c=[];a&&a!=b;)c.push(a),a=a.parentNode;return c}function h(a,b){return a.hasChildNodes()&&b<a.childNodes.length?a.childNodes[b]:null}function i(a,b){if(p(a)){if(r(b.previousSibling)&&!m(b.previousSibling))return c.before(b);if(m(b))return c(b,0)}if(q(a)){if(r(b.nextSibling)&&!m(b.nextSibling))return c.after(b);if(m(b))return c(b,b.data.length)}return q(a)?o(b)?c.before(b):c.a
fter(b):c.before(b)}function j(b,e){var f;return!!a.isBr(b)&&(f=k(1,c.after(b),e),!!f&&!d.isInSameBlock(c.before(b),c.before(f),e))}function k(a,b,o){var u,v,w,x,y,z,A;if(!n(o)||!b)return null;if(A=b.isEqual(c.after(o))&&o.lastChild?c.after(o.lastChild):b,u=A.container(),v=A.offset(),m(u)){if(q(a)&&v>0)return c(u,--v);if(p(a)&&v<u.length)return c(u,++v);w=u}else{if(q(a)&&v>0&&(x=h(u,v-1),r(x)))return!s(x)&&(y=d.findNode(x,a,t,x))?m(y)?c(y,y.data.length):c.after(y):m(x)?c(x,x.data.length):c.before(x);if(p(a)&&v<u.childNodes.length&&(x=h(u,v),r(x)))return j(x,o)?k(a,c.after(x),o):!s(x)&&(y=d.findNode(x,a,t,x))?m(y)?c(y,0):c.before(y):m(x)?c(x,0):c.after(x);w=A.getNode()}return(p(a)&&A.isAtEnd()||q(a)&&A.isAtStart())&&(w=d.findNode(w,a,f.constant(!0),o,!0),t(w))?i(a,w):(x=d.findNode(w,a,t,o),z=e.last(e.filter(g(u,o),l)),!z||x&&z.contains(x)?x?i(a,x):null:A
=p(a)?c.after(z):c.before(z))}var l=a.isContentEditableFalse,m=a.isText,n=a.isElement,o=a.isBr,p=d.isForwards,q=d.isBackwards,r=b.isCaretCandidate,s=b.isAtomic,t=b.isEditableCaretCandidate;return function(a){return{next:function(b){return k(1,b,a)},prev:function(b){return k(-1,b,a)}}}}),g("52",["3s","4h","1n","44"],function(a,b,c,d){var e=function(a,c,e){var f=new d(c);return b.from(a?f.next(e):f.prev(e))},f=function(a,e){var f=new d(e),g=a?c.before(e):c.after(e);return b.from(a?f.next(g):f.prev(g))};return{fromPosition:e,positionIn:f}}),g("4u",["3r","4h","4s","4t","5c","5d"],function(a,b,c,d,e,f){var g=function(b){var c=a.foldl(b,function(a,b){return a[b]=!0,a},{});return function(a){return c[e.name(a)]===!0}},h=g(["h1","h2","h3","h4","h5","h6","p","div","address","pre&q
uot;,"form","blockquote","center","dir","fieldset","header","footer","article","section","hgroup","aside","nav","figure"]),i=function(a){return function(b){return c.eq(a,d.fromDom(b.dom().parentNode))}},j=function(a,d){return c.contains(a,d)?f.closest(d,h,i(a)):b.none()};return{getParentTextBlock:j}}),g("6t",["5d","5a","64"],function(a,b,c){var d=function(a){return b.one(a)},e=function(c,d,e){return a.ancestor(c,function(a){return b.is(a,d)},e)},f=function(c,d){return a.sibling(c,function(a){return b.is(a,d)})},g=function(c,d){return a.child(c,function(a){return b.is(a,d)})},h=function(a,c){return b.one(c,a)},i=function(a,d,f){return c(b.is,e,a,d,f)};return{first:d,ancestor:e,sibling:f,child:g,descendant:h,closest:i}}),g("66",["6t"],function(a){var b=function(b){return a.first(b).isSome()},c=func
tion(b,c,d){return a.ancestor(b,c,d).isSome()},d=function(b,c){return a.sibling(b,c).isSome()},e=function(b,c){return a.child(b,c).isSome()},f=function(b,c){return a.descendant(b,c).isSome()},g=function(b,c,d){return a.closest(b,c,d).isSome()};return{any:b,ancestor:c,sibling:d,child:e,descendant:f,closest:g}}),g("5f",["3s","4s","4t","66","3w","1j","c"],function(a,b,c,d,e,f,g){var h=function(e,f){var g=c.fromDom(e),h=c.fromDom(f);return d.ancestor(h,"pre,code",a.curry(b.eq,g))},i=function(a,b){return f.isText(b)&&/^[ \t\r\n]*$/.test(b.data)&&h(a,b)===!1},j=function(a){return f.isElement(a)&&"A"===a.nodeName&&a.hasAttribute("name")},k=function(a,b){return e.isCaretCandidate(b)&&i(a,b)===!1||j(b)||l(b)},l=f.hasAttribute("data-mce-bookmark"),m=f.hasAttribute("data-mce-bogus"),n=f.hasAttributeValue("data-mce-bogus&q
uot;,"all"),o=function(a){var b,c,d=0;if(k(a,a))return!1;if(c=a.firstChild,!c)return!0;b=new g(c,a);do if(n(c))c=b.next(!0);else if(m(c))c=b.next();else if(f.isBr(c))d++,c=b.next();else{if(k(a,c))return!1;c=b.next()}while(c);return d<=1},p=function(a){return o(a.dom())};return{isEmpty:p}}),g("4p",["3r","3s","4h","4r","57","4s","4t","5c","5d","5e","52","1n","4u","5f","1j"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o){var p=e.immutable("block","position"),q=e.immutable("from","to"),r=function(a,b){var c=g.fromDom(a),d=g.fromDom(b.container());return m.getParentTextBlock(c,d).map(function(a){return p(a,b)})},s=function(a){return f.eq(a.from().block(),a.to().block())===!1},t=function(a){return j.parent(a.from().block()).bind(function(b){return j.parent(a.to().block()).filter(functio
n(a){return f.eq(b,a)})}).isSome()},u=function(a){return o.isContentEditableFalse(a.from().block())===!1&&o.isContentEditableFalse(a.to().block())===!1},v=function(a,b,d){return o.isBr(d.position().getNode())&&n.isEmpty(d.block())===!1?k.positionIn(!1,d.block().dom()).bind(function(e){return e.isEqual(d.position())?k.fromPosition(b,a,e).bind(function(b){return r(a,b)}):c.some(d)}).getOr(d):d},w=function(a,b,c){var e=r(a,l.fromRangeStart(c)),f=e.bind(function(c){return k.fromPosition(b,a,c.position()).bind(function(c){return r(a,c).map(function(c){return v(a,b,c)})})});return d.liftN([e,f],q).filter(function(a){return s(a)&&t(a)&&u(a)})},x=function(a,b,d){return d.collapsed?w(a,b,d):c.none()};return{read:x}}),g("5g",["5e"],function(a){var b=function(b,c){var d=a.parent(b);d.each(function(a){a.dom().insertBefore(c.dom(),b.dom())})},c=function(c,d){var f=a.nextSibling(c);f.fold(function(){var b=a.parent(c);b.each(function(a){e(a,d)})}
,function(a){b(a,d)})},d=function(b,c){var d=a.firstChild(b);d.fold(function(){e(b,c)},function(a){b.dom().insertBefore(c.dom(),a.dom())})},e=function(a,b){a.dom().appendChild(b.dom())},f=function(c,d,f){a.child(c,f).fold(function(){e(c,d)},function(a){b(a,d)})},g=function(a,c){b(a,c),e(c,a)};return{before:b,after:c,prepend:d,append:e,appendAt:f,wrap:g}}),g("67",["3r","5g"],function(a,b){var c=function(c,d){a.each(d,function(a){b.before(c,a)})},d=function(c,d){a.each(d,function(a,e){var f=0===e?c:d[e-1];b.after(f,a)})},e=function(c,d){a.each(d.slice().reverse(),function(a){b.prepend(c,a)})},f=function(c,d){a.each(d,function(a){b.append(c,a)})};return{before:c,after:d,prepend:e,append:f}}),g("5h",["3r","67","5e"],function(a,b,c){var d=function(b){b.dom().textContent="",a.each(c.children(b),function(a){e(a)})},e=function(a){var b=a.dom();null!==b.parentNode&&b.parentNode.removeChild(b)},f=function(
a){var d=c.children(a);d.length>0&&b.before(a,d),e(a)};return{empty:d,remove:e,unwrap:f}}),g("4q",["3r","4h","5g","5h","4t","5e","52","1n","5f","1j"],function(a,b,c,d,e,f,g,h,i,j){var k=function(g,h,k){var l=f.children(g);return j.isBr(k.getNode())&&d.remove(e.fromDom(k.getNode())),a.each(l,function(a){c.append(h,a)}),i.isEmpty(g)&&d.remove(g),l.length>0?b.some(k):b.none()},l=function(a,b,c){return a?g.positionIn(!1,b.dom()).bind(function(a){return k(c,b,a)}):g.positionIn(!1,c.dom()).bind(function(a){return k(b,c,a)})};return{mergeBlocks:l}}),g("40",["4p","4q"],function(a,b){var c=function(c,d){var e;return e=a.read(c.getBody(),d,c.selection.getRng()).bind(function(a){return b.mergeBlocks(d,a.from().block(),a.to().block())}),e.each(function(a){c.selection.setRng(a.toRange())}),e.isSome()};return{backspaceDelete:c}})
,g("41",["4r","4s","4t","4u","4q"],function(a,b,c,d,e){var f=function(f,g){var h=g.getRng();return a.liftN([d.getParentTextBlock(f,c.fromDom(h.startContainer)),d.getParentTextBlock(f,c.fromDom(h.endContainer))],function(a,c){return b.eq(a,c)===!1&&(h.deleteContents(),e.mergeBlocks(!0,a,c).each(function(a){g.setRng(a.toRange())}),!0)}).getOr(!1)},g=function(a,b){var d=c.fromDom(a.getBody());return a.selection.isCollapsed()===!1&&f(d,a.selection)};return{backspaceDelete:g}}),g("5i",["3r","68","62","4i","4j","5b"],function(a,b,c,d,e,f){var g=function(g){if(!c.isArray(g))throw new e("cases must be an array");if(0===g.length)throw new e("there must be at least one case");var h=[],i={};return a.each(g,function(j,k){var l=b.keys(j);if(1!==l.length)throw new e("one and only one name per case");var m=l[0],n=j[m];if(voi
d 0!==i[m])throw new e("duplicate key detected:"+m);if("cata"===m)throw new e("cannot have a case named cata (sorry)");if(!c.isArray(n))throw new e("case arguments must be an array");h.push(m),i[m]=function(){var c=arguments.length;if(c!==n.length)throw new e("Wrong number of arguments to case "+m+". Expected "+n.length+" ("+n+"), got "+c);for(var i=new d(c),j=0;j<i.length;j++)i[j]=arguments[j];var l=function(c){var d=b.keys(c);if(h.length!==d.length)throw new e("Wrong number of arguments to match. Expected: "+h.join(",")+"\nActual: "+d.join(","));var f=a.forall(h,function(b){return a.contains(d,b)});if(!f)throw new e("Not all branches were specified when using match. Specified: "+d.join(", ")+"\nRequired: "+h.join(", "));return c[m].apply(null,i)};return{fold:function(){if(arguments.length!==g.length)throw new e("Wro
ng number of arguments to fold. Expected "+g.length+", got "+arguments.length);var a=arguments[k];return a.apply(null,i)},match:l,log:function(a){f.log(a,{constructors:h,constructor:m,params:i})}}}}),i};return{generate:g}}),g("4w",["5i","4h","52","1n","4v","1j"],function(a,b,c,d,e,f){var g=a.generate([{remove:["element"]},{moveToElement:["element"]},{moveToPosition:["position"]}]),h=function(a,b){var c=b.getNode(a===!1),d=a?"after":"before";return f.isElement(c)&&c.getAttribute("data-mce-caret")===d},i=function(a,d,h){return c.fromPosition(d,a,h).bind(function(a){return d&&f.isContentEditableFalse(a.getNode())?b.some(g.moveToElement(a.getNode())):d===!1&&f.isContentEditableFalse(a.getNode(!0))?b.some(g.moveToElement(a.getNode(!0))):d&&e.isAfterContentEditableFalse(h)?b.some(g.moveToPosition(a)):d===!1&&am
p;e.isBeforeContentEditableFalse(h)?b.some(g.moveToPosition(a)):b.none()})},j=function(a,c){return a&&f.isContentEditableFalse(c.nextSibling)?b.some(g.moveToElement(c.nextSibling)):a===!1&&f.isContentEditableFalse(c.previousSibling)?b.some(g.moveToElement(c.previousSibling)):b.none()},k=function(a,c,d){return h(c,d)?j(c,d.getNode(c===!1)).fold(function(){return i(a,c,d)},b.some):i(a,c,d)},l=function(a,c,f){var h=e.normalizeRange(c?1:-1,a,f),i=d.fromRangeStart(h);return c===!1&&e.isAfterContentEditableFalse(i)?b.some(g.remove(i.getNode(!0))):c&&e.isBeforeContentEditableFalse(i)?b.some(g.remove(i.getNode())):k(a,c,i)};return{read:l}}),g("5j",[],function(){var a=/[\u0591-\u07FF\uFB1D-\uFDFF\uFE70-\uFEFC]/,b=function(b){return a.test(b)};return{hasStrongRtl:b}}),g("51",["3s","4h","4r","1k","52","1n","4v","44","e","5j"],function(a,b,c,d,e
,f,g,h,i,j){var k=function(a){return i.DOM.is(a,"a[href],code")},l=function(a){return"rtl"===i.DOM.getStyle(a,"direction",!0)||j.hasStrongRtl(a.textContent)},m=function(a,c){return b.from(i.DOM.getParent(c.container(),k,a))},n=function(a,b,c){var d=g.getParentBlock(b,a),e=g.getParentBlock(c,a);return d&&d===e},o=function(a,b){return!!b&&m(a,b).isSome()},p=function(a,b){return m(a,b).map(function(a){return s(a,!1,b).isNone()||s(a,!0,b).isNone()}).getOr(!1)},q=function(a){return d.isBeforeInline(a)||d.isAfterInline(a)},r=function(a,b){return e.positionIn(b,a)},s=function(a,b,c){return e.fromPosition(b,a,c)},t=function(a,b){var c=b.container(),e=b.offset();return a?d.isBeforeInline(b)?new f(c,e+1):b:d.isAfterInline(b)?new f(c,e-1):b},u=a.curry(t,!0),v=a.curry(t,!1);return{isInlineTarget:k,findInline:m,isInInline:o,isRtl:l,isAtInlineEndPoint:p,isAtZwsp:q,findCaretPositionIn:r,findCaretPosition:s,normalizePosition:t,normalizeForwards:u,normal
izeBackwards:v,hasSameParentBlock:n}}),g("4x",["3s","4h","5g","5h","4t","5c","5d","3w","1n","5f","1j","51"],function(a,b,c,d,e,f,g,h,i,j,k,l){var m=function(a,b){var c=a.container(),d=a.offset();return i.isTextPosition(a)===!1&&c===b.parentNode&&d>i.before(b).offset()},n=function(a,b){return m(b,a)?new i(b.container(),b.offset()-1):b},o=function(a){return k.isText(a)?new i(a,0):i.before(a)},p=function(a){return k.isText(a)?new i(a,a.data.length):i.after(a)},q=function(a,c,d){return h.isCaretCandidate(d.previousSibling)?b.some(p(d.previousSibling)):h.isCaretCandidate(d.nextSibling)?b.some(o(d)):l.findCaretPosition(c,a,i.before(d)).fold(function(){return l.findCaretPosition(c,!a,i.after(d))},b.some)},r=function(b,c,d){return q(b,c,d).map(a.curry(n,d))},s=function(a,b){b.fold(function(){a.focus()},function(b){a.selection.setRng(b.toRange()
)})},t=function(a){return function(b){return b.dom()===a}},u=function(a,b){return b&&a.schema.getBlockElements().hasOwnProperty(f.name(b))},v=function(a){if(j.isEmpty(a)){var f=e.fromHtml('<br data-mce-bogus="1">');return d.empty(a),c.append(a,f),b.some(i.before(f.dom()))}return b.none()},w=function(c,e,f){var h=r(e,c.getBody(),f.dom()),i=g.ancestor(f,a.curry(u,c),t(c.getBody()));d.remove(f),i.bind(v).fold(function(){s(c,h)},function(a){s(c,b.some(a))})};return{deleteElement:w}}),g("42",["4t","1n","4v","4p","4w","4x","4q","1j"],function(a,b,c,d,e,f,g,h){var i=function(b,c){return function(d){return f.deleteElement(b,c,a.fromDom(d)),!0}},j=function(a,c){return function(d){var e=c?b.before(d):b.after(d);return a.selection.setRng(e.toRange()),!0}},k=function(a){return function(b){return a.selection.setRng(b.toRange()),!0}},l=function(a,b){var c=e.read(a.getBody(),b,a.select
ion.getRng()).map(function(c){return c.fold(i(a,b),j(a,b),k(a))});return c.getOr(!1)},m=function(b,c){var d=b.selection.getNode();return!!h.isContentEditableFalse(d)&&(f.deleteElement(b,c,a.fromDom(b.selection.getNode())),!0)},n=function(a,b){for(;b&&b!==a;){if(h.isContentEditableTrue(b)||h.isContentEditableFalse(b))return b;b=b.parentNode}return null},o=function(a){var c,d=n(a.getBody(),a.selection.getNode());return h.isContentEditableTrue(d)&&a.dom.isBlock(d)&&a.dom.isEmpty(d)&&(c=a.dom.create("br",{"data-mce-bogus":"1"}),a.dom.setHTML(d,""),d.appendChild(c),a.selection.setRng(b.before(c).toRange())),!0},p=function(a,b){return a.selection.isCollapsed()?l(a,b):m(a,b)};return{backspaceDelete:p,paddEmptyElement:o}}),g("5k",["3s","1j","1l"],function(a,b,c){var d=b.isText,e=function(a){return d(a)&&a.data[0]===c.ZWSP},f=function(a){return d(a)&&a.data[
a.data.length-1]===c.ZWSP},g=function(a){return a.ownerDocument.createTextNode(c.ZWSP)},h=function(a){if(d(a.previousSibling))return f(a.previousSibling)?a.previousSibling:(a.previousSibling.appendData(c.ZWSP),a.previousSibling);if(d(a))return e(a)?a:(a.insertData(0,c.ZWSP),a);var b=g(a);return a.parentNode.insertBefore(b,a),b},i=function(a){if(d(a.nextSibling))return e(a.nextSibling)?a.nextSibling:(a.nextSibling.insertData(0,c.ZWSP),a.nextSibling);if(d(a))return f(a)?a:(a.appendData(c.ZWSP),a);var b=g(a);return a.nextSibling?a.parentNode.insertBefore(b,a.nextSibling):a.parentNode.appendChild(b),b},j=function(a,b){return a?h(b):i(b)};return{insertInline:j,insertInlineBefore:a.curry(j,!0),insertInlineAfter:a.curry(j,!1)}}),g("5l",["3r","1k","1n","1j","1l","9"],function(a,b,c,d,e,f){var g=d.isElement,h=d.isText,i=function(a){var b=a.parentNode;b&&b.removeChild(a)},j=function(a){try{return a.nodeValue}catch(a
){return""}},k=function(a,b){0===b.length?i(a):a.nodeValue=b},l=function(a){var b=e.trim(a);return{count:a.length-b.length,text:b}},m=function(a,b){return s(a),b},n=function(a,b){var d=l(a.data.substr(0,b.offset())),e=l(a.data.substr(b.offset())),f=d.text+e.text;return f.length>0?(k(a,f),new c(a,b.offset()-d.count)):b},o=function(b,d){var e=d.container(),f=a.indexOf(e.childNodes,b).map(function(a){return a<d.offset()?new c(e,d.offset()-1):d}).getOr(d);return s(b),f},p=function(a,b){return b.container()===a?n(a,b):m(a,b)},q=function(a,b){return b.container()===a.parentNode?o(a,b):m(a,b)},r=function(a,b){return c.isTextPosition(b)?p(a,b):q(a,b)},s=function(a){if(g(a)&&b.isCaretContainer(a)&&(b.hasContent(a)?a.removeAttribute("data-mce-caret"):i(a)),h(a)){var c=e.trim(j(a));k(a,c)}};return{removeAndReposition:r,remove:s}}),g("4y",["4h","1k","5k","5l","1n","1j","51"]
,function(a,b,c,d,e,f,g){var h=function(a,b){return f.isText(a.container())?c.insertInline(b,a.container()):c.insertInline(b,a.getNode())},i=function(b,f){return f.fold(function(f){d.remove(b.get());var g=c.insertInlineBefore(f);return b.set(g),a.some(new e(g,g.length-1))},function(a){return g.findCaretPositionIn(a,!0).map(function(a){d.remove(b.get());var c=h(a,!0);return b.set(c),new e(c,1)})},function(a){return g.findCaretPositionIn(a,!1).map(function(a){d.remove(b.get());var c=h(a,!1);return b.set(c),new e(c,c.length-1)})},function(f){d.remove(b.get());var g=c.insertInlineAfter(f);return b.set(g),a.some(new e(g,1))})};return{renderCaret:i}}),g("5m",["4h"],function(a){var b=function(b,c){for(var d=0;d<b.length;d++){var e=b[d].apply(null,c);if(e.isSome())return e}return a.none()};return{evaluateUntil:b}}),g("4z",["5i","3s","4h","4r","1k","1n","4v","1j","51",&q
uot;5m"],function(a,b,c,d,e,f,g,h,i,j){var k=a.generate([{before:["element"]
+},{start:["element"]},{end:["element"]},{after:["element"]}]),l=function(a,d){var e=i.normalizeForwards(d);return i.findInline(a,e).fold(function(){return i.findCaretPosition(a,!0,e).bind(b.curry(i.findInline,a)).map(function(a){return k.before(a)})},c.none)},m=function(a,b){var d=i.normalizeBackwards(b);return i.findInline(a,d).bind(function(a){var b=i.findCaretPosition(a,!1,d);return b.isNone()?c.some(k.start(a)):c.none()})},n=function(a,b){var d=i.normalizeForwards(b);return i.findInline(a,d).bind(function(a){var b=i.findCaretPosition(a,!0,d);return b.isNone()?c.some(k.end(a)):c.none()})},o=function(a,d){var e=i.normalizeBackwards(d);return i.findInline(a,e).fold(function(){return i.findCaretPosition(a,!1,e).bind(b.curry(i.findInline,a)).map(function(a){return k.after(a)})},c.none)},p=function(a){return i.isRtl(r(a))===!1},q=function(a,b){var c=j.evaluateUntil([l,m,n,o],[a,b]);return c.filter(p)},r=function(a){return a.fold(b.identity,b.identity,b.id
entity,b.identity)},s=function(a){return a.fold(k.before,k.before,k.after,k.after)},t=function(a){return a.fold(k.start,k.start,k.end,k.end)},u=function(a){return a.fold(b.constant(!1),b.constant(!0),b.constant(!0),b.constant(!1))},v=function(a,b,c,e,f){return d.liftN([i.findInline(b,c),i.findInline(b,e)],function(c,d){return c!==d&&i.hasSameParentBlock(b,c,d)?k.after(a?c:d):f}).getOr(f)},w=function(a,b){return i.findCaretPosition(a,!1,b).isNone()},x=function(a,b){return i.findCaretPosition(a,!0,b).bind(function(b){return h.isBr(b.getNode())?i.findCaretPosition(a,!0,f.after(b.getNode())):c.some(b)}).isNone()},y=function(a,b,c){return a?x(b,c):w(b,c)},z=function(a){return u(a)?c.some(s(a)):c.none()},A=function(a,b,c){return i.findCaretPositionIn(c,b).bind(function(a){return q(c,a).map(s)})},B=function(a,b,d,e,f){var h=g.getParentBlock(d.container(),b);return y(a,h,e)&&u(f)===!1?q(b,d).bind(z):y(a,h,d)?q(b,d).bind(z).orThunk(function(){return c.from(g.getParentBlock(e.
container(),b)).bind(function(c){return A(b,a,c)})}):c.some(f)},C=function(a,c,d){var e=i.normalizePosition(a,d),f=i.findCaretPosition(c,a,e).map(b.curry(i.normalizePosition,a)),g=f.fold(function(){return q(c,e).map(s)},function(d){return q(c,d).bind(b.curry(B,a,c,e,d)).map(b.curry(v,a,c,e,d))});return g.filter(p)};return{readLocation:q,prevLocation:b.curry(C,!1),nextLocation:b.curry(C,!0),getElement:r,outside:s,inside:t}}),g("5n",[],function(){var a=function(b){var c=b,d=function(){return c},e=function(a){c=a},f=function(){return a(d())};return{get:d,set:e,clone:f}};return a}),g("50",["3r","5n","3s","5l","1n","4y","4z","51"],function(a,b,c,d,e,f,g,h){var i=function(a,b){var c=a.dom.createRng();c.setStart(b.container(),b.offset()),c.setEnd(b.container(),b.offset()),a.selection.setRng(c)},j=function(a){return a.settings.inline_boundaries!==!1},k=function(a,b){a?b.setAttribute("dat
a-mce-selected","1"):b.removeAttribute("data-mce-selected","1")},l=function(a,b,c){return f.renderCaret(b,c).map(function(b){return i(a,b),c})},m=function(a,b,c){var d=a.getBody(),f=e.fromRangeStart(a.selection.getRng()),h=c?g.nextLocation(d,f):g.prevLocation(d,f);return h.bind(function(c){return l(a,b,c)})},n=function(b,d){var e=b.select("a[href][data-mce-selected],code[data-mce-selected]"),f=a.filter(d,h.isInlineTarget);a.each(a.difference(e,f),c.curry(k,!1)),a.each(a.difference(f,e),c.curry(k,!0))},o=function(a,b){if(a.selection.isCollapsed()&&a.composing!==!0&&b.get()){var c=e.fromRangeStart(a.selection.getRng());e.isTextPosition(c)&&h.isAtZwsp(c)===!1&&(i(a,d.removeAndReposition(b.get(),c)),b.set(null))}},p=function(b,c,d){if(b.selection.isCollapsed()){var f=a.filter(d,h.isInlineTarget);a.each(f,function(a){var d=e.fromRangeStart(b.selection.getRng());g.readLocation(b.getBody(),d).bind(function(a){retu
rn l(b,c,a)})})}},q=function(a,b,c){return function(){return!!j(a)&&m(a,b,c).isSome()}},r=function(a){var c=new b(null);return a.on("NodeChange",function(b){j(a)&&(n(a.dom,b.parents),o(a,c),p(a,c,b.parents))}),c};return{move:q,setupSelectedState:r,setCaretPosition:i}}),g("43",["3s","4h","4r","4t","1k","1n","4x","4y","4z","50","51"],function(a,b,c,d,e,f,g,h,i,j,k){var l=function(a,b){var c=document.createRange();return c.setStart(a.container(),a.offset()),c.setEnd(b.container(),b.offset()),c},m=function(a,b){return function(c){return h.renderCaret(b,c).map(function(b){return j.setCaretPosition(a,b),!0}).getOr(!1)}},n=function(a,b,c,d){var e=a.getBody();a.undoManager.ignore(function(){a.selection.setRng(l(c,d)),a.execCommand("Delete"),i.readLocation(e,f.fromRangeStart(a.selection.getRng())).map(i.inside).map(m(a,b))}),a.nodeChanged
()},o=function(c,e,f,h){var j=c.getBody(),l=i.readLocation(j,h);return l.bind(function(c){return f?c.fold(a.constant(b.some(i.inside(c))),b.none,a.constant(b.some(i.outside(c))),b.none):c.fold(b.none,a.constant(b.some(i.outside(c))),b.none,a.constant(b.some(i.inside(c))))}).map(m(c,e)).getOrThunk(function(){var a=k.findCaretPosition(j,f,h),b=a.bind(function(a){return i.readLocation(j,a)});return l.isSome()&&b.isSome()?(k.findInline(j,h).bind(function(a){return g.deleteElement(c,f,d.fromDom(a))}),!0):b.map(function(b){return a.map(function(a){f?n(c,e,h,a):n(c,e,a,h)}),!0}).getOr(!1)})},p=function(a,b,c){if(a.selection.isCollapsed()){var d=f.fromRangeStart(a.selection.getRng());return o(a,b,c,d)}return!1};return{backspaceDelete:p}}),g("1v",["40","41","42","43"],function(a,b,c,d){var e=function(a,b){a.getDoc().execCommand(b,!1,null)},f=function(a){var b=a.dom,c=a.getBody();b.isEmpty(c)&&(a.setContent(""),c.firs
tChild&&b.isBlock(c.firstChild)?a.selection.setCursorLocation(c.firstChild,0):a.selection.setCursorLocation(c,0))},g=function(g){c.backspaceDelete(g,!1)||d.backspaceDelete(g,!1)||a.backspaceDelete(g,!1)||b.backspaceDelete(g,!1)||(e(g,"Delete"),f(g))},h=function(f){c.backspaceDelete(f,!0)||d.backspaceDelete(f,!0)||a.backspaceDelete(f,!0)||b.backspaceDelete(f,!0)||e(f,"ForwardDelete")};return{deleteCommand:g,forwardDeleteCommand:h}}),g("45",["52","1n","4v","1j"],function(a,b,c,d){var e=function(a){return d.isElement(a)&&/^(P|H[1-6]|DIV)$/.test(a.nodeName)},f=function(a,b){return b(a.endContainer)},g=function(a,b,c,d){var e=document.createRange();return e.setStart(a,b),e.setEnd(c,d),e},h=function(d){var h=b.fromRangeStart(d),i=b.fromRangeEnd(d),j=d.commonAncestorContainer;return d.collapsed===!1&&f(d,e)&&0===d.endOffset?a.fromPosition(!1,j,i).map(function(a){return!c.isInSameBlock(h,i,
j)&&c.isInSameBlock(h,a,j)?g(h.container(),h.offset(),a.container(),a.offset()):d}).getOr(d):d},i=function(a){return h(a)};return{normalize:i}}),g("46",["9","44","1n"],function(a,b,c){var d=function(a){var b=a.firstChild,c=a.lastChild;return b&&"meta"===b.name&&(b=b.next),c&&"mce_marker"===c.attr("id")&&(c=c.prev),!(!b||b!==c)&&("ul"===b.name||"ol"===b.name)},e=function(a){var b=a.firstChild,c=a.lastChild;return b&&"META"===b.nodeName&&b.parentNode.removeChild(b),c&&"mce_marker"===c.id&&c.parentNode.removeChild(c),a},f=function(a,b,c){var d=b.serialize(c),f=a.createFragment(d);return e(f)},g=function(b){return a.grep(b.childNodes,function(a){return"LI"===a.nodeName})},h=function(a){return!a.firstChild},i=function(a){return a.length>0&&h(a[a.length-1])?a.slice(0,-1):a},j=funct
ion(a,b){var c=a.getParent(b,a.isBlock);return c&&"LI"===c.nodeName?c:null},k=function(a,b){return!!j(a,b)},l=function(a,b){var c=b.cloneRange(),d=b.cloneRange();return c.setStartBefore(a),d.setEndAfter(a),[c.cloneContents(),d.cloneContents()]},m=function(a,d){var e=c.before(a),f=new b(d),g=f.next(e);return g?g.toRange():null},n=function(a,d){var e=c.after(a),f=new b(d),g=f.prev(e);return g?g.toRange():null},o=function(b,c,d,e){var f=l(b,e),g=b.parentNode;return g.insertBefore(f[0],b),a.each(c,function(a){g.insertBefore(a,b)}),g.insertBefore(f[1],b),g.removeChild(b),n(c[c.length-1],d)},p=function(b,c,d){var e=b.parentNode;return a.each(c,function(a){e.insertBefore(a,b)}),m(b,d)},q=function(a,b,c,d){return d.insertAfter(b.reverse(),a),n(b[0],c)},r=function(a,d,e,h){var k=f(d,a,h),l=j(d,e.startContainer),m=i(g(k.firstChild)),n=1,r=2,s=d.getRoot(),t=function(a){var f=c.fromRangeStart(e),g=new b(d.getRoot()),h=a===n?g.prev(f):g.next(f);return!h||j(d,h.getNode())!==l};r
eturn t(n)?p(l,m,s):t(r)?q(l,m,s,d):o(l,m,s,e)};return{isListFragment:d,insertAtCaret:r,isParentBlockLi:k,trimListItems:i,listItems:g}}),g("1w",["1n","44","1q","1j","45","6","n","46","9"],function(a,b,c,d,e,f,g,h,i){var j=d.matchNodeNames("td th"),k=function(a,b,c){if("all"===c.getAttribute("data-mce-bogus"))c.parentNode.insertBefore(a.dom.createFragment(b),c);else{var d=c.firstChild,e=c.lastChild;!d||d===e&&"BR"===d.nodeName?a.dom.setHTML(c,b):a.selection.setContent(b)}},l=function(d,l,m){function n(a){function b(a){return d[a]&&3==d[a].nodeType}var c,d,e;return c=I.getRng(!0),d=c.startContainer,e=c.startOffset,3==d.nodeType&&(e>0?a=a.replace(/^ /," "):b("previousSibling")||(a=a.replace(/^ /," ")),e<d.length?a=a.replace(/ (<br>|)$/," "):b(&quo
t;nextSibling")||(a=a.replace(/( | )(<br>|)$/," "))),a}function o(){var a,b,c;a=I.getRng(!0),b=a.startContainer,c=a.startOffset,3==b.nodeType&&a.collapsed&&("\xa0"===b.data[c]?(b.deleteData(c,1),/[\u00a0| ]$/.test(l)||(l+=" ")):"\xa0"===b.data[c-1]&&(b.deleteData(c-1,1),/[\u00a0| ]$/.test(l)||(l=" "+l)))}function p(){if(G){var a=d.getBody(),b=new c(J);i.each(J.select("*[data-mce-fragment]"),function(c){for(var d=c.parentNode;d&&d!=a;d=d.parentNode)H[c.nodeName.toLowerCase()]&&b.compare(d,c)&&J.remove(c,!0)})}}function q(a){for(var b=a;b=b.walk();)1===b.type&&b.attr("data-mce-fragment","1")}function r(a){i.each(a.getElementsByTagName("*"),function(a){a.removeAttribute("data-mce-fragment")})}function s(a){return!!a.getAttribute("data-mce-fragment")}function t(a){return a&&!d.schema.get
ShortEndedElements()[a.nodeName]}function u(c){function e(a){for(var b=d.getBody();a&&a!==b;a=a.parentNode)if("false"===d.dom.getContentEditable(a))return a;return null}function g(c){var e=a.fromRangeStart(c),f=new b(d.getBody());if(e=f.next(e))return e.toRange()}var h,i,k;if(c){if(I.scrollIntoView(c),h=e(c))return J.remove(c),void I.select(h);C=J.createRng(),D=c.previousSibling,D&&3==D.nodeType?(C.setStart(D,D.nodeValue.length),f.ie||(E=c.nextSibling,E&&3==E.nodeType&&(D.appendData(E.data),E.parentNode.removeChild(E)))):(C.setStartBefore(c),C.setEndBefore(c)),i=J.getParent(c,J.isBlock),J.remove(c),i&&J.isEmpty(i)&&(d.$(i).empty(),C.setStart(i,0),C.setEnd(i,0),j(i)||s(i)||!(k=g(C))?J.add(i,J.create("br",{"data-mce-bogus":"1"})):(C=k,J.remove(i))),I.setRng(C)}}var v,w,x,y,z,A,B,C,D,E,F,G,H=d.schema.getTextInlineElements(),I=d.selection,J=d.dom;/^ | $/.test(l)&&(l=n(l)),v=d.parser,G=m.merge
,w=new g({validate:d.settings.validate},d.schema),F='<span id="mce_marker" data-mce-type="bookmark">​</span>',A={content:l,format:"html",selection:!0},d.fire("BeforeSetContent",A),l=A.content,l.indexOf("{$caret}")==-1&&(l+="{$caret}"),l=l.replace(/\{\$caret\}/,F),C=I.getRng();var K=C.startContainer||(C.parentElement?C.parentElement():null),L=d.getBody();K===L&&I.isCollapsed()&&J.isBlock(L.firstChild)&&t(L.firstChild)&&J.isEmpty(L.firstChild)&&(C=J.createRng(),C.setStart(L.firstChild,0),C.setEnd(L.firstChild,0),I.setRng(C)),I.isCollapsed()||(d.selection.setRng(e.normalize(d.selection.getRng())),d.getDoc().execCommand("Delete",!1,null),o()),x=I.getNode();var M={context:x.nodeName.toLowerCase(),data:m.data};if(z=v.parse(l,M),m.paste===!0&&h.isListFragment(z)&&h.isParentBlockLi(J,x))return C=h.insertAtCaret(w,J,d.selecti
on.getRng(!0),z),d.selection.setRng(C),void d.fire("SetContent",A);if(q(z),D=z.lastChild,"mce_marker"==D.attr("id"))for(B=D,D=D.prev;D;D=D.walk(!0))if(3==D.type||!J.isBlock(D.name)){d.schema.isValidChild(D.parent.name,"span")&&D.parent.insert(B,D,"br"===D.name);break}if(d._selectionOverrides.showBlockCaretContainer(x),M.invalid){for(I.setContent(F),x=I.getNode(),y=d.getBody(),9==x.nodeType?x=D=y:D=x;D!==y;)x=D,D=D.parentNode;l=x==y?y.innerHTML:J.getOuterHTML(x),l=w.serialize(v.parse(l.replace(/<span (id="mce_marker"|id=mce_marker).+?<\/span>/i,function(){return w.serialize(z)}))),x==y?J.setHTML(y,l):J.setOuterHTML(x,l)}else l=w.serialize(z),k(d,l,x);p(),u(J.get("mce_marker")),r(d.getBody()),d.fire("SetContent",A),d.addVisual()},m=function(a){var b;return"string"!=typeof a?(b=i.extend({paste:a.paste,data:{paste:a.paste}},a),{content:a.content,details:b}):{content:a,details:{}}},
n=function(a,b){var c=m(b);l(a,c.content,c.details)};return{insertAtCaret:n}}),g("v",["1v","1j","h","c","6","1w","9"],function(a,b,c,d,e,f,g){var h=g.each,i=g.extend,j=g.map,k=g.inArray,l=g.explode,m=e.ie&&e.ie<11,n=!0,o=!1;return function(g){function p(a,b,c,d){var e,f,i=0;if(/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint)$/.test(a)||d&&d.skip_focus||g.focus(),d=g.fire("BeforeExecCommand",{command:a,ui:b,value:c}),d.isDefaultPrevented())return!1;if(f=a.toLowerCase(),e=H.exec[f])return e(f,b,c),g.fire("ExecCommand",{command:a,ui:b,value:c}),!0;if(h(g.plugins,function(d){if(d.execCommand&&d.execCommand(a,b,c))return g.fire("ExecCommand",{command:a,ui:b,value:c}),i=!0,!1}),i)return i;if(g.theme&&g.theme.execCommand&&g.theme.execCommand(a,b,c))return g.fire("ExecCommand",{command:a,ui:b,value:c}),!0;try{i=g.g
etDoc().execCommand(a,b,c)}catch(a){}return!!i&&(g.fire("ExecCommand",{command:a,ui:b,value:c}),!0)}function q(a){var b;if(!g.quirks.isHidden()){if(a=a.toLowerCase(),b=H.state[a])return b(a);try{return g.getDoc().queryCommandState(a)}catch(a){}return!1}}function r(a){var b;if(!g.quirks.isHidden()){if(a=a.toLowerCase(),b=H.value[a])return b(a);try{return g.getDoc().queryCommandValue(a)}catch(a){}}}function s(a,b){b=b||"exec",h(a,function(a,c){h(c.toLowerCase().split(","),function(c){H[b][c]=a})})}function t(a,b,c){a=a.toLowerCase(),H.exec[a]=function(a,d,e,f){return b.call(c||g,d,e,f)}}function u(a){if(a=a.toLowerCase(),H.exec[a])return!0;try{return g.getDoc().queryCommandSupported(a)}catch(a){}return!1}function v(a,b,c){a=a.toLowerCase(),H.state[a]=function(){return b.call(c||g)}}function w(a,b,c){a=a.toLowerCase(),H.value[a]=function(){return b.call(c||g)}}function x(a){return a=a.toLowerCase(),!!H.exec[a]}function y(a,b,c){return void 0===b&am
p;&(b=o),void 0===c&&(c=null),g.getDoc().execCommand(a,b,c)}function z(a){return F.match(a)}function A(a,b){F.toggle(a,b?{value:b}:void 0),g.nodeChanged()}function B(a){G=E.getBookmark(a)}function C(){E.moveToBookmark(G)}var D,E,F,G,H={state:{},exec:{},value:{}},I=g.settings;g.on("PreInit",function(){D=g.dom,E=g.selection,I=g.settings,F=g.formatter}),i(this,{execCommand:p,queryCommandState:q,queryCommandValue:r,queryCommandSupported:u,addCommands:s,addCommand:t,addQueryStateHandler:v,addQueryValueHandler:w,hasCustomCommand:x}),s({"mceResetDesignMode,mceBeginUndoLevel":function(){},"mceEndUndoLevel,mceAddUndoLevel":function(){g.undoManager.add()},"Cut,Copy,Paste":function(a){var b,c=g.getDoc();try{y(a)}catch(a){b=n}if("paste"!==a||c.queryCommandEnabled(a)||(b=!0),b||!c.queryCommandSupported(a)){var d=g.translate("Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X/C/V keyboard shortcuts
instead.");e.mac&&(d=d.replace(/Ctrl\+/g,"\u2318+")),g.notificationManager.open({text:d,type:"error"})}},unlink:function(){if(E.isCollapsed()){var a=g.dom.getParent(g.selection.getStart(),"a");return void(a&&g.dom.remove(a,!0))}F.remove("link")},"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull,JustifyNone":function(a){var b=a.substring(7);"full"==b&&(b="justify"),h("left,center,right,justify".split(","),function(a){b!=a&&F.remove("align"+a)}),"none"!=b&&A("align"+b)},"InsertUnorderedList,InsertOrderedList":function(a){var b,c;y(a),b=D.getParent(E.getNode(),"ol,ul"),b&&(c=b.parentNode,/^(H[1-6]|P|ADDRESS|PRE)$/.test(c.nodeName)&&(B(),D.split(c,b),C()))},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(a){A(a)},"ForeColor,HiliteColor,FontName":f
unction(a,b,c){A(a,c)},FontSize:function(a,b,c){var d,e;c>=1&&c<=7&&(e=l(I.font_size_style_values),d=l(I.font_size_classes),c=d?d[c-1]||c:e[c-1]||c),A(a,c)},RemoveFormat:function(a){F.remove(a)},mceBlockQuote:function(){A("blockquote")},FormatBlock:function(a,b,c){return A(c||"p")},mceCleanup:function(){var a=E.getBookmark();g.setContent(g.getContent({cleanup:n}),{cleanup:n}),E.moveToBookmark(a)},mceRemoveNode:function(a,b,c){var d=c||E.getNode();d!=g.getBody()&&(B(),g.dom.remove(d,n),C())},mceSelectNodeDepth:function(a,b,c){var d=0;D.getParent(E.getNode(),function(a){if(1==a.nodeType&&d++==c)return E.select(a),o},g.getBody())},mceSelectNode:function(a,b,c){E.select(c)},mceInsertContent:function(a,b,c){f.insertAtCaret(g,c)},mceInsertRawHTML:function(a,b,c){E.setContent("tiny_mce_marker"),g.setContent(g.getContent().replace(/tiny_mce_marker/g,function(){return c}))},mceToggleFormat:function(a,b,c){A(c)},mceSetContent
:function(a,b,c){g.setContent(c)},"Indent,Outdent":function(a){var b,c,d;b=I.indentation,c=/[a-z%]+$/i.exec(b),b=parseInt(b,10),q("InsertUnorderedList")||q("InsertOrderedList")?y(a):(I.forced_root_block||D.getParent(E.getNode(),D.isBlock)||F.apply("div"),h(E.getSelectedBlocks(),function(e){if("false"!==D.getContentEditable(e)&&"LI"!==e.nodeName){var f=g.getParam("indent_use_margin",!1)?"margin":"padding";f="TABLE"===e.nodeName?"margin":f,f+="rtl"==D.getStyle(e,"direction",!0)?"Right":"Left","outdent"==a?(d=Math.max(0,parseInt(e.style[f]||0,10)-b),D.setStyle(e,f,d?d+c:"")):(d=parseInt(e.style[f]||0,10)+b+c,D.setStyle(e,f,d))}}))},mceRepaint:function(){},InsertHorizontalRule:function(){g.execCommand("mceInsertContent",!1,"<hr />")},mceToggleVisualAid:function(){g.hasVisual=!g.hasVisua
l,g.addVisual()},mceReplaceContent:function(a,b,c){g.execCommand("mceInsertContent",!1,c.replace(/\{\$selection\}/g,E.getContent({format:"text"})))},mceInsertLink:function(a,b,c){var d;"string"==typeof c&&(c={href:c}),d=D.getParent(E.getNode(),"a"),c.href=c.href.replace(" ","%20"),d&&c.href||F.remove("link"),c.href&&F.apply("link",c,d)},selectAll:function(){var a,c=D.getRoot();if(E.getRng().setStart){var d=D.getParent(E.getStart(),b.isContentEditableTrue);d&&(a=D.createRng(),a.selectNodeContents(d),E.setRng(a))}else a=E.getRng(),a.item||(a.moveToElementText(c),a.select())},"delete":function(){a.deleteCommand(g)},forwardDelete:function(){a.forwardDeleteCommand(g)},mceNewDocument:function(){g.setContent("")},InsertLineBreak:function(a,b,e){function f(){for(var a,b=new d(p,r),c=g.schema.getNonEmptyElements();a=b.next();)if(c[a.nodeName.toLowerCase()]||a.le
ngth>0)return!0}var h,i,j,k=e,l=E.getRng(!0);new c(D).normalize(l);var o=l.startOffset,p=l.startContainer;if(1==p.nodeType&&p.hasChildNodes()){var q=o>p.childNodes.length-1;p=p.childNodes[Math.min(o,p.childNodes.length-1)]||p,o=q&&3==p.nodeType?p.nodeValue.length:0}var r=D.getParent(p,D.isBlock),s=r?r.nodeName.toUpperCase():"",t=r?D.getParent(r.parentNode,D.isBlock):null,u=t?t.nodeName.toUpperCase():"",v=k&&k.ctrlKey;"LI"!=u||v||(r=t,s=u),p&&3==p.nodeType&&o>=p.nodeValue.length&&(m||f()||(h=D.create("br"),l.insertNode(h),l.setStartAfter(h),l.setEndAfter(h),i=!0)),h=D.create("br"),l.insertNode(h);var w=D.doc.documentMode;return m&&"PRE"==s&&(!w||w<8)&&h.parentNode.insertBefore(D.doc.createTextNode("\r"),h),j=D.create("span",{}," "),h.parentNode.insertBefore(j,h),E.scrollIntoView(j),D.remove(j),i?(l.setSt
artBefore(h),l.setEndBefore(h)):(l.setStartAfter(h),l.setEndAfter(h)),E.setRng(l),g.undoManager.add(),n}}),s({"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(a){var b="align"+a.substring(7),c=E.isCollapsed()?[D.getParent(E.getNode(),D.isBlock)]:E.getSelectedBlocks(),d=j(c,function(a){return!!F.matchNode(a,b)});return k(d,n)!==-1},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(a){return z(a)},mceBlockQuote:function(){return z("blockquote")},Outdent:function(){var a;if(I.inline_styles){if((a=D.getParent(E.getStart(),D.isBlock))&&parseInt(a.style.paddingLeft,10)>0)return n;if((a=D.getParent(E.getEnd(),D.isBlock))&&parseInt(a.style.paddingLeft,10)>0)return n}return q("InsertUnorderedList")||q("InsertOrderedList")||!I.inline_styles&&!!D.getParent(E.getNode(),"BLOCKQUOTE")},"InsertUnorderedList,InsertOrderedList":function(a){var b=D.getParent(E.
getNode(),"ul,ol");return b&&("insertunorderedlist"===a&&"UL"===b.tagName||"insertorderedlist"===a&&"OL"===b.tagName)}},"state"),s({"FontSize,FontName":function(a){var b,c=0;return(b=D.getParent(E.getNode(),"span"))&&(c="fontsize"==a?b.style.fontSize:b.style.fontFamily.replace(/, /g,",").replace(/[\'\"]/g,"").toLowerCase()),c}},"value"),s({Undo:function(){g.undoManager.undo()},Redo:function(){g.undoManager.redo()}})}}),g("w",["1x","9"],function(a,b){function c(b,g){var h,i,j=this;if(b=e(b),g=j.settings=g||{},h=g.base_uri,/^([\w\-]+):([^\/]{2})/i.test(b)||/^\s*#/.test(b))return void(j.source=b);var k=0===b.indexOf("//");0!==b.indexOf("/")||k||(b=(h?h.protocol||"http":"http")+"://mce_host"+b),/^[\w\-]*:?\/\//.test(b)||(i=g.base_uri?g.base_uri.path:new
c(a.location.href).directory,""===g.base_uri.protocol?b="//mce_host"+j.toAbsPath(i,b):(b=/([^#?]*)([#?]?.*)/.exec(b),b=(h&&h.protocol||"http")+"://mce_host"+j.toAbsPath(i,b[1])+b[2])),b=b.replace(/@@/g,"(mce_at)"),b=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(b),d(f,function(a,c){var d=b[c];d&&(d=d.replace(/\(mce_at\)/g,"@@")),j[a]=d}),h&&(j.protocol||(j.protocol=h.protocol),j.userInfo||(j.userInfo=h.userInfo),j.port||"mce_host"!==j.host||(j.port=h.port),j.host&&"mce_host"!==j.host||(j.host=h.host),j.source=""),k&&(j.protocol="")}var d=b.each,e=b.trim,f="source protocol authority userInfo user password host port relative path directory file query anchor".split(" "),g={ftp:
21,http:80,https:443,mailto:25};return c.prototype={setPath:function(a){var b=this;a=/^(.*?)\/?(\w+)?$/.exec(a),b.path=a[0],b.directory=a[1],b.file=a[2],b.source="",b.getURI()},toRelative:function(a){var b,d=this;if("./"===a)return a;if(a=new c(a,{base_uri:d}),"mce_host"!=a.host&&d.host!=a.host&&a.host||d.port!=a.port||d.protocol!=a.protocol&&""!==a.protocol)return a.getURI();var e=d.getURI(),f=a.getURI();return e==f||"/"==e.charAt(e.length-1)&&e.substr(0,e.length-1)==f?e:(b=d.toRelPath(d.path,a.path),a.query&&(b+="?"+a.query),a.anchor&&(b+="#"+a.anchor),b)},toAbsolute:function(a,b){return a=new c(a,{base_uri:this}),a.getURI(b&&this.isSameOrigin(a))},isSameOrigin:function(a){if(this.host==a.host&&this.protocol==a.protocol){if(this.port==a.port)return!0;var b=g[this.protocol];if(b&&(this.port||b)==(a.port||b))return!0}return!1},toRelPath:functi
on(a,b){var c,d,e,f=0,g="";if(a=a.substring(0,a.lastIndexOf("/")),a=a.split("/"),c=b.split("/"),a.length>=c.length)for(d=0,e=a.length;d<e;d++)if(d>=c.length||a[d]!=c[d]){f=d+1;break}if(a.length<c.length)for(d=0,e=c.length;d<e;d++)if(d>=a.length||a[d]!=c[d]){f=d+1;break}if(1===f)return b;for(d=0,e=a.length-(f-1);d<e;d++)g+="../";for(d=f-1,e=c.length;d<e;d++)g+=d!=f-1?"/"+c[d]:c[d];return g},toAbsPath:function(a,b){var c,e,f,g=0,h=[];for(e=/\/$/.test(b)?"/":"",a=a.split("/"),b=b.split("/"),d(a,function(a){a&&h.push(a)}),a=h,c=b.length-1,h=[];c>=0;c--)0!==b[c].length&&"."!==b[c]&&(".."!==b[c]?g>0?g--:h.push(b[c]):g++);return c=a.length-g,f=c<=0?h.reverse().join("/"):a.slice(0,c).join("/")+"/"+h.reverse().join("/"),0!==f.indexOf("/")&&(f="/"+f),e
&&f.lastIndexOf("/")!==f.length-1&&(f+=e),f},getURI:function(a){var b,c=this;return c.source&&!a||(b="",a||(b+=c.protocol?c.protocol+"://":"//",c.userInfo&&(b+=c.userInfo+"@"),c.host&&(b+=c.host),c.port&&(b+=":"+c.port)),c.path&&(b+=c.path),c.query&&(b+="?"+c.query),c.anchor&&(b+="#"+c.anchor),c.source=b),c.source}},c.parseDataUri=function(a){var b,c;return a=decodeURIComponent(a).split(","),c=/data:([^;]+)/.exec(a[0]),c&&(b=c[1]),{type:b,data:a[1]}},c.getDocumentBaseUrl=function(a){var b;return b=0!==a.protocol.indexOf("http")&&"file:"!==a.protocol?a.href:a.protocol+"//"+a.host+a.pathname,/^[^:]+:\/\/\/?[^\/]+\//.test(b)&&(b=b.replace(/[\?#].*$/,"").replace(/[\/\\][^\/]+$/,""),/[\/\\]$/.test(b)||(b+="/")),b},c}),g("x",["9&quo
t;],function(a){function b(){}var c,d,e=a.each,f=a.extend;return b.extend=c=function(a){function b(){var a,b,c,e=this;if(!d&&(e.init&&e.init.apply(e,arguments),b=e.Mixins))for(a=b.length;a--;)c=b[a],c.init&&c.init.apply(e,arguments)}function g(){return this}function h(a,b){return function(){var c,d=this,e=d._super;return d._super=m[a],c=b.apply(d,arguments),d._super=e,c}}var i,j,k,l=this,m=l.prototype;d=!0,i=new l,d=!1,a.Mixins&&(e(a.Mixins,function(b){for(var c in b)"init"!==c&&(a[c]=b[c])}),m.Mixins&&(a.Mixins=m.Mixins.concat(a.Mixins))),a.Methods&&e(a.Methods.split(","),function(b){a[b]=g}),a.Properties&&e(a.Properties.split(","),function(b){var c="_"+b;a[b]=function(a){var b,d=this;return a!==b?(d[c]=a,d):d[c]}}),a.Statics&&e(a.Statics,function(a,c){b[c]=a}),a.Defaults&&m.Defaults&&(a.Defaults=f({},m.Defaults,a.Defaults));for(j in a)k=a[j],"functio
n"==typeof k&&m[j]?i[j]=h(j,k):i[j]=k;return b.prototype=i,b.constructor=b,b.extend=c,b},b}),g("y",["9"],function(a){function b(b){function c(){return!1}function d(){return!0}function e(a,e){var f,h,i,k;if(a=a.toLowerCase(),e=e||{},e.type=a,e.target||(e.target=j),e.preventDefault||(e.preventDefault=function(){e.isDefaultPrevented=d},e.stopPropagation=function(){e.isPropagationStopped=d},e.stopImmediatePropagation=function(){e.isImmediatePropagationStopped=d},e.isDefaultPrevented=c,e.isPropagationStopped=c,e.isImmediatePropagationStopped=c),b.beforeFire&&b.beforeFire(e),f=m[a])for(h=0,i=f.length;h<i;h++){if(k=f[h],k.once&&g(a,k.func),e.isImmediatePropagationStopped())return e.stopPropagation(),e;if(k.func.call(j,e)===!1)return e.preventDefault(),e}return e}function f(b,d,e,f){var g,h,i;if(d===!1&&(d=c),d)for(d={func:d},f&&a.extend(d,f),h=b.toLowerCase().split(" "),i=h.length;i--;)b=h[i],g=m[b],g||(g=m[b]=[]
,k(b,!0)),e?g.unshift(d):g.push(d);return l}function g(a,b){var c,d,e,f,g;if(a)for(f=a.toLowerCase().split(" "),c=f.length;c--;){if(a=f[c],d=m[a],!a){for(e in m)k(e,!1),delete m[e];return l}if(d){if(b)for(g=d.length;g--;)d[g].func===b&&(d=d.slice(0,g).concat(d.slice(g+1)),m[a]=d);else d.length=0;d.length||(k(a,!1),delete m[a])}}else{for(a in m)k(a,!1);m={}}return l}function h(a,b,c){return f(a,b,c,{once:!0})}function i(a){return a=a.toLowerCase(),!(!m[a]||0===m[a].length)}var j,k,l=this,m={};b=b||{},j=b.scope||l,k=b.toggleEvent||c,l.fire=e,l.on=f,l.off=g,l.once=h,l.has=i}var c=a.makeMap("focus blur focusin focusout click dblclick mousedown mouseup mousemove mouseover beforepaste paste cut copy selectionchange mouseout mouseenter mouseleave wheel keydown keypress keyup input contextmenu dragstart dragend dragover draggesture dragdrop drop drag submit compositionstart compositionend compositionupdate touchstart touchmove touchend"," ");return b.is
Native=function(a){return!!c[a.toLowerCase()]},b}),g("z",["y"],function(a){function b(b){return b._eventDispatcher||(b._eventDispatcher=new a({scope:b,toggleEvent:function(c,d){a.isNative(c)&&b.toggleNativeEvent&&b.toggleNativeEvent(c,d)}})),b._eventDispatcher}return{fire:function(a,c,d){var e=this;if(e.removed&&"remove"!==a)return c;if(c=b(e).fire(a,c,d),d!==!1&&e.parent)for(var f=e.parent();f&&!c.isPropagationStopped();)f.fire(a,c,!1),f=f.parent();return c},on:function(a,c,d){return b(this).on(a,c,d)},off:function(a,c){return b(this).off(a,c)},once:function(a,c){return b(this).once(a,c)},hasEventListeners:function(a){return b(this).has(a)}}}),g("53",[],function(){function a(a){this.create=a.create}return a.create=function(b,c){return new a({create:function(a,d){function e(b){a.set(d,b.value)}function f(a){b.set(c,a.value)}var g;return a.on("change:"+d,f),b.on("change:"+c,e),g=a._bin
dings,g||(g=a._bindings=[],a.on("destroy",function(){for(var a=g.length;a--;)g[a]()})),g.push(function(){b.off("change:"+c,e)}),b.get(c)}})},a}),g("47",["53","x","z","9"],function(a,b,c,d){function e(a){return a.nodeType>0}function f(a,b){var c,g;if(a===b)return!0;if(null===a||null===b)return a===b;if("object"!=typeof a||"object"!=typeof b)return a===b;if(d.isArray(b)){if(a.length!==b.length)return!1;for(c=a.length;c--;)if(!f(a[c],b[c]))return!1}if(e(a)||e(b))return a===b;g={};for(c in b){if(!f(a[c],b[c]))return!1;g[c]=!0}for(c in a)if(!g[c]&&!f(a[c],b[c]))return!1;return!0}return b.extend({Mixins:[c],init:function(b){var c,d;b=b||{};for(c in b)d=b[c],d instanceof a&&(b[c]=d.create(this,c));this.data=b},set:function(b,c){var d,e,g=this.data[b];if(c instanceof a&&(c=c.create(this,b)),"object"==typeof b){for(d in b)this.set(d,b[d]);return this}return f(g,c)||(
this.data[b]=c,e={target:this,name:b,value:c,oldValue:g},this.fire("change:"+b,e),this.fire("change",e)),this},get:function(a){return this.data[a]},has:function(a){return a in this.data},bind:function(b){return a.create(this,b)},destroy:function(){this.fire("destroy")}})}),g("27",["x"],function(a){"use strict";function b(a){for(var b,c=[],d=a.length;d--;)b=a[d],b.__checked||(c.push(b),b.__checked=1);for(d=c.length;d--;)delete c[d].__checked;return c}var c,d=/^([\w\\*]+)?(?:#([\w\-\\]+))?(?:\.([\w\\\.]+))?(?:\[\@?([\w\\]+)([\^\$\*!~]?=)([\w\\]+)\])?(?:\:(.+))?/i,e=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,f=/^\s*|\s*$/g,g=a.extend({init:function(a){function b(a){if(a)return a=a.toLowerCase(),function(b){return"*"===a||b.type===a}}function c(a){if(a)return function(b){return b._name===a}}function g(a
){if(a)return a=a.split("."),function(b){for(var c=a.length;c--;)if(!b.classes.contains(a[c]))return!1;return!0}}function h(a,b,c){if(a)return function(d){var e=d[a]?d[a]():"";return b?"="===b?e===c:"*="===b?e.indexOf(c)>=0:"~="===b?(" "+e+" ").indexOf(" "+c+" ")>=0:"!="===b?e!=c:"^="===b?0===e.indexOf(c):"$="===b&&e.substr(e.length-c.length)===c:!!c}}function i(a){var b;if(a)return a=/(?:not\((.+)\))|(.+)/i.exec(a),a[1]?(b=k(a[1],[]),function(a){return!l(a,b)}):(a=a[2],function(b,c,d){return"first"===a?0===c:"last"===a?c===d-1:"even"===a?c%2===0:"odd"===a?c%2===1:!!b[a]&&b[a]()})}function j(a,e,j){function k(a){a&&e.push(a)}var l;return l=d.exec(a.replace(f,"")),k(b(l[1])),k(c(l[2])),k(g(l[3])),k(h(l[4],l[5],l[6])),k(i(l[7])),e.pseudo=!!l[7],e.direct=j,e}function k(a,b){var c,d,f,g=[];
do if(e.exec(""),d=e.exec(a),d&&(a=d[3],g.push(d[1]),d[2])){c=d[3];break}while(d);for(c&&k(c,b),a=[],f=0;f<g.length;f++)">"!=g[f]&&a.push(j(g[f],[],">"===g[f-1]));return b.push(a),b}var l=this.match;this._selectors=k(a,[])},match:function(a,b){var c,d,e,f,g,h,i,j,k,l,m,n,o;for(b=b||this._selectors,c=0,d=b.length;c<d;c++){for(g=b[c],f=g.length,o=a,n=0,e=f-1;e>=0;e--)for(j=g[e];o;){if(j.pseudo)for(m=o.parent().items(),k=l=m.length;k--&&m[k]!==o;);for(h=0,i=j.length;h<i;h++)if(!j[h](o,k,l)){h=i+1;break}if(h===i){n++;break}if(e===f-1)break;o=o.parent()}if(n===f)return!0}return!1},find:function(a){function d(a,b,c){var e,f,g,i,j,k=b[c];for(e=0,f=a.length;e<f;e++){for(j=a[e],g=0,i=k.length;g<i;g++)if(!k[g](j,e,f)){g=i+1;break}if(g===i)c==b.length-1?h.push(j):j.items&&d(j.items(),b,c+1);else if(k.direct)return;j.items&&d(j.items(),b,c)}}var e,f,h=[],i=this._selectors;if(a.items){for(e=0,f=
i.length;e<f;e++)d(a.items(),i[e],0);f>1&&(h=b(h))}return c||(c=g.Collection),new c(h)}});return g}),g("28",["9","27","x"],function(a,b,c){"use strict";var d,e,f=Array.prototype.push,g=Array.prototype.slice;return e={length:0,init:function(a){a&&this.add(a)},add:function(b){var c=this;return a.isArray(b)?f.apply(c,b):b instanceof d?c.add(b.toArray()):f.call(c,b),c},set:function(a){var b,c=this,d=c.length;for(c.length=0,c.add(a),b=c.length;b<d;b++)delete c[b];return c},filter:function(a){var c,e,f,g,h=this,i=[];for("string"==typeof a?(a=new b(a),g=function(b){return a.match(b)}):g=a,c=0,e=h.length;c<e;c++)f=h[c],g(f)&&i.push(f);return new d(i)},slice:function(){return new d(g.apply(this,arguments))},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},each:function(b){return a.each(this,b),
+this},toArray:function(){return a.toArray(this)},indexOf:function(a){for(var b=this,c=b.length;c--&&b[c]!==a;);return c},reverse:function(){return new d(a.toArray(this).reverse())},hasClass:function(a){return!!this[0]&&this[0].classes.contains(a)},prop:function(a,b){var c,d,e=this;return b!==c?(e.each(function(c){c[a]&&c[a](b)}),e):(d=e[0],d&&d[a]?d[a]():void 0)},exec:function(b){var c=this,d=a.toArray(arguments).slice(1);return c.each(function(a){a[b]&&a[b].apply(a,d)}),c},remove:function(){for(var a=this.length;a--;)this[a].remove();return this},addClass:function(a){return this.each(function(b){b.classes.add(a)})},removeClass:function(a){return this.each(function(b){b.classes.remove(a)})}},a.each("fire on off show hide append prepend before after reflow".split(" "),function(b){e[b]=function(){var c=a.toArray(arguments);return this.each(function(a){b in a&&a[b].apply(a,c)}),this}}),a.each("text name disabled a
ctive selected checked visible parent value data".split(" "),function(a){e[a]=function(b){return this.prop(a,b)}}),d=c.extend(e),b.Collection=d,d}),g("48",["6","9","e"],function(a,b,c){"use strict";var d=0,e={id:function(){return"mceu_"+d++},create:function(a,d,e){var f=document.createElement(a);return c.DOM.setAttribs(f,d),"string"==typeof e?f.innerHTML=e:b.each(e,function(a){a.nodeType&&f.appendChild(a)}),f},createFragment:function(a){return c.DOM.createFragment(a)},getWindowSize:function(){return c.DOM.getViewPort()},getSize:function(a){var b,c;if(a.getBoundingClientRect){var d=a.getBoundingClientRect();b=Math.max(d.width||d.right-d.left,a.offsetWidth),c=Math.max(d.height||d.bottom-d.bottom,a.offsetHeight)}else b=a.offsetWidth,c=a.offsetHeight;return{width:b,height:c}},getPos:function(a,b){return c.DOM.getPos(a,b||e.getContainer())},getContainer:function(){return a.container?a.container:d
ocument.body},getViewPort:function(a){return c.DOM.getViewPort(a)},get:function(a){return document.getElementById(a)},addClass:function(a,b){return c.DOM.addClass(a,b)},removeClass:function(a,b){return c.DOM.removeClass(a,b)},hasClass:function(a,b){return c.DOM.hasClass(a,b)},toggleClass:function(a,b,d){return c.DOM.toggleClass(a,b,d)},css:function(a,b,d){return c.DOM.setStyle(a,b,d)},getRuntimeStyle:function(a,b){return c.DOM.getStyle(a,b,!0)},on:function(a,b,d,e){return c.DOM.bind(a,b,d,e)},off:function(a,b,d){return c.DOM.unbind(a,b,d)},fire:function(a,b,d){return c.DOM.fire(a,b,d)},innerHtml:function(a,b){c.DOM.setHTML(a,b)}};return e}),g("49",[],function(){"use strict";return{parseBox:function(a){var b,c=10;if(a)return"number"==typeof a?(a=a||0,{top:a,left:a,bottom:a,right:a}):(a=a.split(" "),b=a.length,1===b?a[1]=a[2]=a[3]=a[0]:2===b?(a[2]=a[0],a[3]=a[1]):3===b&&(a[3]=a[1]),{top:parseInt(a[0],c)||0,right:parseInt(a[1],c)||0,botto
m:parseInt(a[2],c)||0,left:parseInt(a[3],c)||0})},measureBox:function(a,b){function c(b){var c=document.defaultView;return c?(b=b.replace(/[A-Z]/g,function(a){return"-"+a}),c.getComputedStyle(a,null).getPropertyValue(b)):a.currentStyle[b]}function d(a){var b=parseFloat(c(a),10);return isNaN(b)?0:b}return{top:d(b+"TopWidth"),right:d(b+"RightWidth"),bottom:d(b+"BottomWidth"),left:d(b+"LeftWidth")}}}}),g("4a",["9"],function(a){"use strict";function b(){}function c(a){this.cls=[],this.cls._map={},this.onchange=a||b,this.prefix=""}return a.extend(c.prototype,{add:function(a){return a&&!this.contains(a)&&(this.cls._map[a]=!0,this.cls.push(a),this._change()),this},remove:function(a){if(this.contains(a)){for(var b=0;b<this.cls.length&&this.cls[b]!==a;b++);this.cls.splice(b,1),delete this.cls._map[a],this._change()}return this},toggle:function(a,b){var c=this.contains(a);retur
n c!==b&&(c?this.remove(a):this.add(a),this._change()),this},contains:function(a){return!!this.cls._map[a]},_change:function(){delete this.clsValue,this.onchange.call(this)}}),c.prototype.toString=function(){var a;if(this.clsValue)return this.clsValue;a="";for(var b=0;b<this.cls.length;b++)b>0&&(a+=" "),a+=this.prefix+this.cls[b];return a},c}),g("29",["5"],function(a){var b,c={};return{add:function(d){var e=d.parent();if(e){if(!e._layout||e._layout.isNative())return;c[e._id]||(c[e._id]=e),b||(b=!0,a.requestAnimationFrame(function(){var a,d;b=!1;for(a in c)d=c[a],d.state.get("rendered")&&d.reflow();c={}},document.body))}},remove:function(a){c[a._id]&&delete c[a._id]}}}),g("2a",["x","9","y","47","28","48","a","49","4a","29"],function(a,b,c,d,e,f,g,h,i,j){"use strict";function k(a)
{return a._eventDispatcher||(a._eventDispatcher=new c({scope:a,toggleEvent:function(b,d){d&&c.isNative(b)&&(a._nativeEvents||(a._nativeEvents={}),a._nativeEvents[b]=!0,a.state.get("rendered")&&l(a))}})),a._eventDispatcher}function l(a){function b(b){var c=a.getParentCtrl(b.target);c&&c.fire(b.type,b)}function c(){var a=j._lastHoverCtrl;a&&(a.fire("mouseleave",{target:a.getEl()}),a.parents().each(function(a){a.fire("mouseleave",{target:a.getEl()})}),j._lastHoverCtrl=null)}function d(b){var c,d,e,f=a.getParentCtrl(b.target),g=j._lastHoverCtrl,h=0;if(f!==g){if(j._lastHoverCtrl=f,d=f.parents().toArray().reverse(),d.push(f),g){for(e=g.parents().toArray().reverse(),e.push(g),h=0;h<e.length&&d[h]===e[h];h++);for(c=e.length-1;c>=h;c--)g=e[c],g.fire("mouseleave",{target:g.getEl()})}for(c=h;c<d.length;c++)f=d[c],f.fire("mouseenter",{target:f.getEl()})}}function e(b){b.preventDefault(),&q
uot;mousewheel"==b.type?(b.deltaY=-.025*b.wheelDelta,b.wheelDeltaX&&(b.deltaX=-.025*b.wheelDeltaX)):(b.deltaX=0,b.deltaY=b.detail),b=a.fire("wheel",b)}var f,h,i,j,k,l;if(k=a._nativeEvents){for(i=a.parents().toArray(),i.unshift(a),f=0,h=i.length;!j&&f<h;f++)j=i[f]._eventsRoot;for(j||(j=i[i.length-1]||a),a._eventsRoot=j,h=f,f=0;f<h;f++)i[f]._eventsRoot=j;var m=j._delegates;m||(m=j._delegates={});for(l in k){if(!k)return!1;"wheel"!==l||o?("mouseenter"===l||"mouseleave"===l?j._hasMouseEnter||(g(j.getEl()).on("mouseleave",c).on("mouseover",d),j._hasMouseEnter=1):m[l]||(g(j.getEl()).on(l,b),m[l]=!0),k[l]=!1):n?g(a.getEl()).on("mousewheel",e):g(a.getEl()).on("DOMMouseScroll",e)}}}var m,n="onmousewheel"in document,o=!1,p="mce-",q=0,r={Statics:{classPrefix:p},isRtl:function(){return m.rtl},classPrefix:p,init:function(a){function c(a){var b;for(a=a.split(" "
),b=0;b<a.length;b++)j.classes.add(a[b])}var e,f,j=this;j.settings=a=b.extend({},j.Defaults,a),j._id=a.id||"mceu_"+q++,j._aria={role:a.role},j._elmCache={},j.$=g,j.state=new d({visible:!0,active:!1,disabled:!1,value:""}),j.data=new d(a.data),j.classes=new i(function(){j.state.get("rendered")&&(j.getEl().className=this.toString())}),j.classes.prefix=j.classPrefix,e=a.classes,e&&(j.Defaults&&(f=j.Defaults.classes,f&&e!=f&&c(f)),c(e)),b.each("title text name visible disabled active value".split(" "),function(b){b in a&&j[b](a[b])}),j.on("click",function(){if(j.disabled())return!1}),j.settings=a,j.borderBox=h.parseBox(a.border),j.paddingBox=h.parseBox(a.padding),j.marginBox=h.parseBox(a.margin),a.hidden&&j.hide()},Properties:"parent,name",getContainerElm:function(){return f.getContainer()},getParentCtrl:function(a){for(var b,c=this.getRoot().controlIdLookup;a&
amp;&c&&!(b=c[a.id]);)a=a.parentNode;return b},initLayoutRect:function(){var a,b,c,d,e,g,i,j,k,l,m=this,n=m.settings,o=m.getEl();a=m.borderBox=m.borderBox||h.measureBox(o,"border"),m.paddingBox=m.paddingBox||h.measureBox(o,"padding"),m.marginBox=m.marginBox||h.measureBox(o,"margin"),l=f.getSize(o),j=n.minWidth,k=n.minHeight,e=j||l.width,g=k||l.height,c=n.width,d=n.height,i=n.autoResize,i="undefined"!=typeof i?i:!c&&!d,c=c||e,d=d||g;var p=a.left+a.right,q=a.top+a.bottom,r=n.maxWidth||65535,s=n.maxHeight||65535;return m._layoutRect=b={x:n.x||0,y:n.y||0,w:c,h:d,deltaW:p,deltaH:q,contentW:c-p,contentH:d-q,innerW:c-p,innerH:d-q,startMinWidth:j||0,startMinHeight:k||0,minW:Math.min(e,r),minH:Math.min(g,s),maxW:r,maxH:s,autoResize:i,scrollW:0},m._lastLayoutRect={},b},layoutRect:function(a){var b,c,d,e,f,g,h=this,i=h._layoutRect;return i||(i=h.initLayoutRect()),a?(d=i.deltaW,e=i.deltaH,a.x!==f&&(i.x=a.x),a.y!==f&&(i.
y=a.y),a.minW!==f&&(i.minW=a.minW),a.minH!==f&&(i.minH=a.minH),c=a.w,c!==f&&(c=c<i.minW?i.minW:c,c=c>i.maxW?i.maxW:c,i.w=c,i.innerW=c-d),c=a.h,c!==f&&(c=c<i.minH?i.minH:c,c=c>i.maxH?i.maxH:c,i.h=c,i.innerH=c-e),c=a.innerW,c!==f&&(c=c<i.minW-d?i.minW-d:c,c=c>i.maxW-d?i.maxW-d:c,i.innerW=c,i.w=c+d),c=a.innerH,c!==f&&(c=c<i.minH-e?i.minH-e:c,c=c>i.maxH-e?i.maxH-e:c,i.innerH=c,i.h=c+e),a.contentW!==f&&(i.contentW=a.contentW),a.contentH!==f&&(i.contentH=a.contentH),b=h._lastLayoutRect,b.x===i.x&&b.y===i.y&&b.w===i.w&&b.h===i.h||(g=m.repaintControls,g&&g.map&&!g.map[h._id]&&(g.push(h),g.map[h._id]=!0),b.x=i.x,b.y=i.y,b.w=i.w,b.h=i.h),h):i},repaint:function(){var a,b,c,d,e,f,g,h,i,j,k=this;i=document.createRange?function(a){return a}:Math.round,a=k.getEl().style,d=k._layoutRect,h=k._lastRepaintRect||{},e=k.borderBox,f=e.left+e.right,g=e.top+e.bottom,d.x!==
h.x&&(a.left=i(d.x)+"px",h.x=d.x),d.y!==h.y&&(a.top=i(d.y)+"px",h.y=d.y),d.w!==h.w&&(j=i(d.w-f),a.width=(j>=0?j:0)+"px",h.w=d.w),d.h!==h.h&&(j=i(d.h-g),a.height=(j>=0?j:0)+"px",h.h=d.h),k._hasBody&&d.innerW!==h.innerW&&(j=i(d.innerW),c=k.getEl("body"),c&&(b=c.style,b.width=(j>=0?j:0)+"px"),h.innerW=d.innerW),k._hasBody&&d.innerH!==h.innerH&&(j=i(d.innerH),c=c||k.getEl("body"),c&&(b=b||c.style,b.height=(j>=0?j:0)+"px"),h.innerH=d.innerH),k._lastRepaintRect=h,k.fire("repaint",{},!1)},updateLayoutRect:function(){var a=this;a.parent()._lastRect=null,f.css(a.getEl(),{width:"",height:""}),a._layoutRect=a._lastRepaintRect=a._lastLayoutRect=null,a.initLayoutRect()},on:function(a,b){function c(a){var b,c;return"string"!=typeof a?a:function(e){return b||d.parentsAndSelf().each(functio
n(d){var e=d.settings.callbacks;if(e&&(b=e[a]))return c=d,!1}),b?b.call(c,e):(e.action=a,void this.fire("execute",e))}}var d=this;return k(d).on(a,c(b)),d},off:function(a,b){return k(this).off(a,b),this},fire:function(a,b,c){var d=this;if(b=b||{},b.control||(b.control=d),b=k(d).fire(a,b),c!==!1&&d.parent)for(var e=d.parent();e&&!b.isPropagationStopped();)e.fire(a,b,!1),e=e.parent();return b},hasEventListeners:function(a){return k(this).has(a)},parents:function(a){var b,c=this,d=new e;for(b=c.parent();b;b=b.parent())d.add(b);return a&&(d=d.filter(a)),d},parentsAndSelf:function(a){return new e(this).add(this.parents(a))},next:function(){var a=this.parent().items();return a[a.indexOf(this)+1]},prev:function(){var a=this.parent().items();return a[a.indexOf(this)-1]},innerHtml:function(a){return this.$el.html(a),this},getEl:function(a){var b=a?this._id+"-"+a:this._id;return this._elmCache[b]||(this._elmCache[b]=g("#"+b)[0]),th
is._elmCache[b]},show:function(){return this.visible(!0)},hide:function(){return this.visible(!1)},focus:function(){try{this.getEl().focus()}catch(a){}return this},blur:function(){return this.getEl().blur(),this},aria:function(a,b){var c=this,d=c.getEl(c.ariaTarget);return"undefined"==typeof b?c._aria[a]:(c._aria[a]=b,c.state.get("rendered")&&d.setAttribute("role"==a?a:"aria-"+a,b),c)},encode:function(a,b){return b!==!1&&(a=this.translate(a)),(a||"").replace(/[&<>"]/g,function(a){return"&#"+a.charCodeAt(0)+";"})},translate:function(a){return m.translate?m.translate(a):a},before:function(a){var b=this,c=b.parent();return c&&c.insert(a,c.items().indexOf(b),!0),b},after:function(a){var b=this,c=b.parent();return c&&c.insert(a,c.items().indexOf(b)),b},remove:function(){var a,b,c=this,d=c.getEl(),e=c.parent();if(c.items){var f=c.items().toArray();for(b=f.length;b--;)f[
b].remove()}e&&e.items&&(a=[],e.items().each(function(b){b!==c&&a.push(b)}),e.items().set(a),e._lastRect=null),c._eventsRoot&&c._eventsRoot==c&&g(d).off();var h=c.getRoot().controlIdLookup;return h&&delete h[c._id],d&&d.parentNode&&d.parentNode.removeChild(d),c.state.set("rendered",!1),c.state.destroy(),c.fire("remove"),c},renderBefore:function(a){return g(a).before(this.renderHtml()),this.postRender(),this},renderTo:function(a){return g(a||this.getContainerElm()).append(this.renderHtml()),this.postRender(),this},preRender:function(){},render:function(){},renderHtml:function(){return'<div id="'+this._id+'" class="'+this.classes+'"></div>'},postRender:function(){var a,b,c,d,e,f=this,h=f.settings;f.$el=g(f.getEl()),f.state.set("rendered",!0);for(d in h)0===d.indexOf("on")&&f.on(d.substr(2),h[d]);if(f._eventsRoot){for(c=f.parent();!e&&c
;c=c.parent())e=c._eventsRoot;if(e)for(d in e._nativeEvents)f._nativeEvents[d]=!0}l(f),h.style&&(a=f.getEl(),a&&(a.setAttribute("style",h.style),a.style.cssText=h.style)),f.settings.border&&(b=f.borderBox,f.$el.css({"border-top-width":b.top,"border-right-width":b.right,"border-bottom-width":b.bottom,"border-left-width":b.left}));var i=f.getRoot();i.controlIdLookup||(i.controlIdLookup={}),i.controlIdLookup[f._id]=f;for(var k in f._aria)f.aria(k,f._aria[k]);f.state.get("visible")===!1&&(f.getEl().style.display="none"),f.bindStates(),f.state.on("change:visible",function(a){var b,c=a.value;f.state.get("rendered")&&(f.getEl().style.display=c===!1?"none":"",f.getEl().getBoundingClientRect()),b=f.parent(),b&&(b._lastRect=null),f.fire(c?"show":"hide"),j.add(f)}),f.fire("postrender",{},!1)},bindStates:funct
ion(){},scrollIntoView:function(a){function b(a,b){var c,d,e=a;for(c=d=0;e&&e!=b&&e.nodeType;)c+=e.offsetLeft||0,d+=e.offsetTop||0,e=e.offsetParent;return{x:c,y:d}}var c,d,e,f,g,h,i=this.getEl(),j=i.parentNode,k=b(i,j);return c=k.x,d=k.y,e=i.offsetWidth,f=i.offsetHeight,g=j.clientWidth,h=j.clientHeight,"end"==a?(c-=g-e,d-=h-f):"center"==a&&(c-=g/2-e/2,d-=h/2-f/2),j.scrollLeft=c,j.scrollTop=d,this},getRoot:function(){for(var a,b=this,c=[];b;){if(b.rootControl){a=b.rootControl;break}c.push(b),a=b,b=b.parent()}a||(a=this);for(var d=c.length;d--;)c[d].rootControl=a;return a},reflow:function(){j.remove(this);var a=this.parent();return a&&a._layout&&!a._layout.isNative()&&a.reflow(),this}};return b.each("text title visible disabled active value".split(" "),function(a){r[a]=function(b){return 0===arguments.length?this.state.get(a):("undefined"!=typeof b&&this.state.set(a,b),this)}}),m=
a.extend(r)}),g("2b",[],function(){"use strict";var a={};return{add:function(b,c){a[b.toLowerCase()]=c},has:function(b){return!!a[b.toLowerCase()]},create:function(b,c){var d;if("string"==typeof b?(c=c||{},c.type=b):(c=b,b=c.type),b=b.toLowerCase(),d=a[b],!d)throw new Error("Could not find control by type: "+b);return d=new d(c),d.type=b,d}}}),g("2c",[],function(){"use strict";var a=function(a){return!!a.getAttribute("data-mce-tabstop")};return function(b){function c(a){return a&&1===a.nodeType}function d(a){return a=a||u,c(a)?a.getAttribute("role"):null}function e(a){for(var b,c=a||u;c=c.parentNode;)if(b=d(c))return b}function f(a){var b=u;if(c(b))return b.getAttribute("aria-"+a)}function g(a){var b=a.tagName.toUpperCase();return"INPUT"==b||"TEXTAREA"==b||"SELECT"==b}function h(b){return!(!g(b)||b.hidden)||(!!a(b)||!!/^(button|menuitem|checkbox|tab|menuite
mcheckbox|option|gridcell|slider)$/.test(d(b)))}function i(a){function b(a){if(1==a.nodeType&&"none"!=a.style.display&&!a.disabled){h(a)&&c.push(a);for(var d=0;d<a.childNodes.length;d++)b(a.childNodes[d])}}var c=[];return b(a||w.getEl()),c}function j(a){var b,c;a=a||v,c=a.parents().toArray(),c.unshift(a);for(var d=0;d<c.length&&(b=c[d],!b.settings.ariaRoot);d++);return b}function k(a){var b=j(a),c=i(b.getEl());b.settings.ariaRemember&&"lastAriaIndex"in b?l(b.lastAriaIndex,c):l(0,c)}function l(a,b){return a<0?a=b.length-1:a>=b.length&&(a=0),b[a]&&b[a].focus(),a}function m(a,b){var c=-1,d=j();b=b||i(d.getEl());for(var e=0;e<b.length;e++)b[e]===u&&(c=e);c+=a,d.lastAriaIndex=l(c,b)}function n(){var a=e();"tablist"==a?m(-1,i(u.parentNode)):v.parent().submenu?s():m(-1)}function o(){var a=d(),b=e();"tablist"==b?m(1,i(u.parentNode)):"menuitem"==a&&"me
nu"==b&&f("haspopup")?t():m(1)}function p(){m(-1)}function q(){var a=d(),b=e();"menuitem"==a&&"menubar"==b?t():"button"==a&&f("haspopup")?t({key:"down"}):m(1)}function r(a){var b=e();if("tablist"==b){var c=i(v.getEl("body"))[0];c&&c.focus()}else m(a.shiftKey?-1:1)}function s(){v.fire("cancel")}function t(a){a=a||{},v.fire("click",{target:u,aria:a})}var u,v,w=b.root;try{u=document.activeElement}catch(a){u=document.body}return v=w.getParentCtrl(u),w.on("keydown",function(b){function c(b,c){g(u)||a(u)||"slider"!==d(u)&&c(b)!==!1&&b.preventDefault()}if(!b.isDefaultPrevented())switch(b.keyCode){case 37:c(b,n);break;case 39:c(b,o);break;case 38:c(b,p);break;case 40:c(b,q);break;case 27:s();break;case 14:case 13:case 32:c(b,t);break;case 9:r(b)!==!1&&b.preventDefault()}}),w.on("focusin",function(a){u=a
.target,v=a.control}),{focusFirst:k}}}),g("2d",["2a","28","27","2b","2c","9","a","4a","29"],function(a,b,c,d,e,f,g,h,i){"use strict";var j={};return a.extend({init:function(a){var c=this;c._super(a),a=c.settings,a.fixed&&c.state.set("fixed",!0),c._items=new b,c.isRtl()&&c.classes.add("rtl"),c.bodyClasses=new h(function(){c.state.get("rendered")&&(c.getEl("body").className=this.toString())}),c.bodyClasses.prefix=c.classPrefix,c.classes.add("container"),c.bodyClasses.add("container-body"),a.containerCls&&c.classes.add(a.containerCls),c._layout=d.create((a.layout||"")+"layout"),c.settings.items?c.add(c.settings.items):c.add(c.render()),c._hasBody=!0},items:function(){return this._items},find:function(a){return a=j[a]=j[a]||new c(a),a.find(this)},add:function(a){var b=
this;return b.items().add(b.create(a)).parent(b),b},focus:function(a){var b,c,d,e=this;return a&&(c=e.keyboardNav||e.parents().eq(-1)[0].keyboardNav)?void c.focusFirst(e):(d=e.find("*"),e.statusbar&&d.add(e.statusbar.items()),d.each(function(a){return a.settings.autofocus?(b=null,!1):void(a.canFocus&&(b=b||a))}),b&&b.focus(),e)},replace:function(a,b){for(var c,d=this.items(),e=d.length;e--;)if(d[e]===a){d[e]=b;break}e>=0&&(c=b.getEl(),c&&c.parentNode.removeChild(c),c=a.getEl(),c&&c.parentNode.removeChild(c)),b.parent(this)},create:function(b){var c,e=this,g=[];return f.isArray(b)||(b=[b]),f.each(b,function(b){b&&(b instanceof a||("string"==typeof b&&(b={type:b}),c=f.extend({},e.settings.defaults,b),b.type=c.type=c.type||b.type||e.settings.defaultType||(c.defaults?c.defaults.type:null),b=d.create(c)),g.push(b))}),g},renderNew:function(){var a=this;return a.items().each(function(b,c){var d;b
.parent(a),b.state.get("rendered")||(d=a.getEl("body"),d.hasChildNodes()&&c<=d.childNodes.length-1?g(d.childNodes[c]).before(b.renderHtml()):g(d).append(b.renderHtml()),b.postRender(),i.add(b))}),a._layout.applyClasses(a.items().filter(":visible")),a._lastRect=null,a},append:function(a){return this.add(a).renderNew()},prepend:function(a){var b=this;return b.items().set(b.create(a).concat(b.items().toArray())),b.renderNew()},insert:function(a,b,c){var d,e,f,g=this;return a=g.create(a),d=g.items(),!c&&b<d.length-1&&(b+=1),b>=0&&b<d.length&&(e=d.slice(0,b).toArray(),f=d.slice(b).toArray(),d.set(e.concat(a,f))),g.renderNew()},fromJSON:function(a){var b=this;for(var c in a)b.find("#"+c).value(a[c]);return b},toJSON:function(){var a=this,b={};return a.find("*").each(function(a){var c=a.name(),d=a.value();c&&"undefined"!=typeof d&&(b[c]=d)}),b},renderHtml:function
(){var a=this,b=a._layout,c=this.settings.role;return a.preRender(),b.preRender(a),'<div id="'+a._id+'" class="'+a.classes+'"'+(c?' role="'+this.settings.role+'"':"")+'><div id="'+a._id+'-body" class="'+a.bodyClasses+'">'+(a.settings.html||"")+b.renderHtml(a)+"</div></div>"},postRender:function(){var a,b=this;return b.items().exec("postRender"),b._super(),b._layout.postRender(b),b.state.set("rendered",!0),b.settings.style&&b.$el.css(b.settings.style),b.settings.border&&(a=b.borderBox,b.$el.css({"border-top-width":a.top,"border-right-width":a.right,"border-bottom-width":a.bottom,"border-left-width":a.left})),b.parent()||(b.keyboardNav=new e({root:b})),b},initLayoutRect:function(){var a=this,b=a._super();return a._layout.recalc(a),b},recalc:function(){var a=this,b=a._layoutRect,c=a._lastRect;if(!c||c.w!=b.w|
|c.h!=b.h)return a._layout.recalc(a),b=a.layoutRect(),a._lastRect={x:b.x,y:b.y,w:b.w,h:b.h},!0},reflow:function(){var b;if(i.remove(this),this.visible()){for(a.repaintControls=[],a.repaintControls.map={},this.recalc(),b=a.repaintControls.length;b--;)a.repaintControls[b].repaint();"flow"!==this.settings.layout&&"stack"!==this.settings.layout&&this.repaint(),a.repaintControls=[]}return this}})}),g("2e",["a"],function(a){"use strict";function b(a){var b,c,d,e,f,g,h,i,j=Math.max;return b=a.documentElement,c=a.body,d=j(b.scrollWidth,c.scrollWidth),e=j(b.clientWidth,c.clientWidth),f=j(b.offsetWidth,c.offsetWidth),g=j(b.scrollHeight,c.scrollHeight),h=j(b.clientHeight,c.clientHeight),i=j(b.offsetHeight,c.offsetHeight),{width:d<f?e:d,height:g<i?h:g}}function c(a){var b,c;if(a.changedTouches)for(b="screenX screenY pageX pageY clientX clientY".split(" "),c=0;c<b.length;c++)a[b[c]]=a.changedTouches[0]
[b[c]]}return function(d,e){function f(){return n.getElementById(e.handle||d)}var g,h,i,j,k,l,m,n=e.document||document;e=e||{},i=function(d){var i,o,p=b(n);c(d),d.preventDefault(),h=d.button,i=f(),l=d.screenX,m=d.screenY,o=window.getComputedStyle?window.getComputedStyle(i,null).getPropertyValue("cursor"):i.runtimeStyle.cursor,g=a("<div></div>").css({position:"absolute",top:0,left:0,width:p.width,height:p.height,zIndex:2147483647,opacity:1e-4,cursor:o}).appendTo(n.body),a(n).on("mousemove touchmove",k).on("mouseup touchend",j),e.start(d)},k=function(a){return c(a),a.button!==h?j(a):(a.deltaX=a.screenX-l,a.deltaY=a.screenY-m,a.preventDefault(),void e.drag(a))},j=function(b){c(b),a(n).off("mousemove touchmove",k).off("mouseup touchend",j),g.remove(),e.stop&&e.stop(b)},this.destroy=function(){a(f()).off()},a(f()).on("mousedown touchstart",i)}}),g("2f",["a","2e&quo
t;],function(a,b){"use strict";return{init:function(){var a=this;a.on("repaint",a.renderScroll)},renderScroll:function(){function c(){function b(b,g,h,i,j,k){var l,m,n,o,p,q,r,s,t;if(m=e.getEl("scroll"+b)){if(s=g.toLowerCase(),t=h.toLowerCase(),a(e.getEl("absend")).css(s,e.layoutRect()[i]-1),!j)return void a(m).css("display","none");a(m).css("display","block"),l=e.getEl("body"),n=e.getEl("scroll"+b+"t"),o=l["client"+h]-2*f,o-=c&&d?m["client"+k]:0,p=l["scroll"+h],q=o/p,r={},r[s]=l["offset"+g]+f,r[t]=o,a(m).css(r),r={},r[s]=l["scroll"+g]*q,r[t]=o*q,a(n).css(r)}}var c,d,g;g=e.getEl("body"),c=g.scrollWidth>g.clientWidth,d=g.scrollHeight>g.clientHeight,b("h","Left","Width","contentW",c,"Height"),b("v","Top","Height","conten
tH",d,"Width")}function d(){function c(c,d,g,h,i){var j,k=e._id+"-scroll"+c,l=e.classPrefix;a(e.getEl()).append('<div id="'+k+'" class="'+l+"scrollbar "+l+"scrollbar-"+c+'"><div id="'+k+'t" class="'+l+'scrollbar-thumb"></div></div>'),e.draghelper=new b(k+"t",{start:function(){j=e.getEl("body")["scroll"+d],a("#"+k).addClass(l+"active")},drag:function(a){var b,k,l,m,n=e.layoutRect();k=n.contentW>n.innerW,l=n.contentH>n.innerH,m=e.getEl("body")["client"+g]-2*f,m-=k&&l?e.getEl("scroll"+c)["client"+i]:0,b=m/e.getEl("body")["scroll"+g],e.getEl("body")["scroll"+d]=j+a["delta"+h]/b},stop:function(){a("#"+k).removeClass(l+"active")}})}e.classes.add("scroll"),c("v","Top","Height&q
uot;,"Y","Width"),c("h","Left","Width","X","Height")}var e=this,f=2;e.settings.autoScroll&&(e._hasScroll||(e._hasScroll=!0,d(),e.on("wheel",function(a){var b=e.getEl("body");b.scrollLeft+=10*(a.deltaX||0),b.scrollTop+=10*a.deltaY,c()}),a(e.getEl("body")).on("scroll",c)),c())}}}),g("2g",["2d","2f"],function(a,b){"use strict";return a.extend({Defaults:{layout:"fit",containerCls:"panel"},Mixins:[b],renderHtml:function(){var a=this,b=a._layout,c=a.settings.html;return a.preRender(),b.preRender(a),"undefined"==typeof c?c='<div id="'+a._id+'-body" class="'+a.bodyClasses+'">'+b.renderHtml(a)+"</div>":("function"==typeof c&&(c=c.call(a)),a._hasBody=!1),'<div id="'+a._id+'" class="'+a.classes+'" hidefocus="1" tabind
ex="-1" role="group">'+(a._preBodyHtml||"")+c+"</div>"}})}),g("2h",["48"],function(a){"use strict";function b(b,c,d){var e,f,g,h,i,j,k,l,m,n;return m=a.getViewPort(),f=a.getPos(c),g=f.x,h=f.y,b.state.get("fixed")&&"static"==a.getRuntimeStyle(document.body,"position")&&(g-=m.x,h-=m.y),e=b.getEl(),n=a.getSize(e),i=n.width,j=n.height,n=a.getSize(c),k=n.width,l=n.height,d=(d||"").split(""),"b"===d[0]&&(h+=l),"r"===d[1]&&(g+=k),"c"===d[0]&&(h+=Math.round(l/2)),"c"===d[1]&&(g+=Math.round(k/2)),"b"===d[3]&&(h-=j),"r"===d[4]&&(g-=i),"c"===d[3]&&(h-=Math.round(j/2)),"c"===d[4]&&(g-=Math.round(i/2)),{x:g,y:h,w:i,h:j}}return{testMoveRel:function(c,d){for(var e=a.getViewPort(),f=0;f<d.length;f++){var g=b(thi
s,c,d[f]);if(this.state.get("fixed")){if(g.x>0&&g.x+g.w<e.w&&g.y>0&&g.y+g.h<e.h)return d[f]}else if(g.x>e.x&&g.x+g.w<e.w+e.x&&g.y>e.y&&g.y+g.h<e.h+e.y)return d[f]}return d[0]},moveRel:function(a,c){"string"!=typeof c&&(c=this.testMoveRel(a,c));var d=b(this,a,c);return this.moveTo(d.x,d.y)},moveBy:function(a,b){var c=this,d=c.layoutRect();return c.moveTo(d.x+a,d.y+b),c},moveTo:function(b,c){function d(a,b,c){return a<0?0:a+c>b?(a=b-c,a<0?0:a):a}var e=this;if(e.settings.constrainToViewport){var f=a.getViewPort(window),g=e.layoutRect();b=d(b,f.w+f.x,g.w),c=d(c,f.h+f.y,g.h)}return e.state.get("rendered")?e.layoutRect({x:b,y:c}).repaint():(e.settings.x=b,e.settings.y=c),e.fire("move",{x:b,y:c}),e}}}),g("2i",["48"],function(a){"use strict";return{resizeToContent:function(){this._layoutRect.autoResize=!0,this._lastRect=null,this.refl
ow()},resizeTo:function(b,c){if(b<=1||c<=1){var d=a.getWindowSize();b=b<=1?b*d.w:b,c=c<=1?c*d.h:c}return this._layoutRect.autoResize=!1,this.layoutRect({minW:b,minH:c,w:b,h:c}).reflow()},resizeBy:function(a,b){var c=this,d=c.layoutRect();return c.resizeTo(d.w+a,d.h+b)}}}),g("2j",["2g","2h","2i","48","a","5"],function(a,b,c,d,e,f){"use strict";function g(a,b){for(;a;){if(a==b)return!0;a=a.parent()}}function h(a){for(var b=s.length;b--;){var c=s[b],d=c.getParentCtrl(a.target);if(c.settings.autohide){if(d&&(g(d,c)||c.parent()===d))continue;a=c.fire("autohide",{target:a.target}),a.isDefaultPrevented()||c.hide()}}}function i(){o||(o=function(a){2!=a.button&&h(a)},e(document).on("click touchstart",o))}function j(){p||(p=function(){var a;for(a=s.length;a--;)l(s[a])},e(window).on("scroll",p))}function k(){if(!q){var a=document.documentElement,b=a.clientWi
dth,c=a.clientHeight;q=function(){document.all&&b==a.clientWidth&&c==a.clientHeight||(b=a.clientWidth,c=a.clientHeight,u.hideAll())},e(window).on("resize",q)}}function l(a){function b(b,c){for(var d,e=0;e<s.length;e++)if(s[e]!=a)for(d=s[e].parent();d&&(d=d.parent());)d==a&&s[e].fixed(b).moveBy(0,c).repaint()}var c=d.getViewPort().y;a.settings.autofix&&(a.state.get("fixed")?a._autoFixY>c&&(a.fixed(!1).layoutRect({y:a._autoFixY}).repaint(),b(!1,a._autoFixY-c)):(a._autoFixY=a.layoutRect().y,a._autoFixY<c&&(a.fixed(!0).layoutRect({y:0}).repaint(),b(!0,c-a._autoFixY))))}function m(a,b){var c,d,f=u.zIndex||65535;if(a)t.push(b);else for(c=t.length;c--;)t[c]===b&&t.splice(c,1);if(t.length)for(c=0;c<t.length;c++)t[c].modal&&(f++,d=t[c]),t[c].getEl().style.zIndex=f,t[c].zIndex=f,f++;var g=e("#"+b.classPrefix+"modal-block",b.getContainerElm())[0];d?e(g).css("z-index&
quot;,d.zIndex-1):g&&(g.parentNode.removeChild(g),r=!1),u.currentZIndex=f}function n(a){var b;for(b=s.length;b--;)s[b]===a&&s.splice(b,1);for(b=t.length;b--;)t[b]===a&&t.splice(b,1)}var o,p,q,r,s=[],t=[],u=a.extend({Mixins:[b,c],init:function(a){var b=this;b._super(a),b._eventsRoot=b,b.classes.add("floatpanel"),a.autohide&&(i(),k(),s.push(b)),a.autofix&&(j(),b.on("move",function(){l(this)})),b.on("postrender show",function(a){if(a.control==b){var c,d=b.classPrefix;b.modal&&!r&&(c=e("#"+d+"modal-block",b.getContainerElm()),c[0]||(c=e('<div id="'+d+'modal-block" class="'+d+"reset "+d+'fade"></div>').appendTo(b.getContainerElm())),f.setTimeout(function(){c.addClass(d+"in"),e(b.getEl()).addClass(d+"in")}),r=!0),m(!0,b)}}),b.on("show",function(){b.parents().each(function(a){if(a.state.get("fixed"))retur
n b.fixed(!0),!1})}),a.popover&&(b._preBodyHtml='<div class="'+b.classPrefix+'arrow"></div>',b.classes.add("popover").add("bottom").add(b.isRtl()?"end":"start")),b.aria("label",a.ariaLabel),b.aria("labelledby",b._id),b.aria("describedby",b.describedBy||b._id+"-none")},fixed:function(a){var b=this;if(b.state.get("fixed")!=a){if(b.state.get("rendered")){var c=d.getViewPort();a?b.layoutRect().y-=c.y:b.layoutRect().y+=c.y}b.classes.toggle("fixed",a),b.state.set("fixed",a)}return b},show:function(){var a,b=this,c=b._super();for(a=s.length;a--&&s[a]!==b;);return a===-1&&s.push(b),c},hide:function(){return n(this),m(!1,this),this._super()},hideAll:function(){u.hideAll()},close:function(){var a=this;return a.fire("close").isDefaultPrevented()||(a.remove(),m(!1,a)),a},remove:function(){n(this),this._super()},postRender
:function(){var a=this;return a.settings.bodyRole&&this.getEl("body").setAttribute("role",a.settings.bodyRole),a._super()}});return u.hideAll=function(){for(var a=s.length;a--;){var b=s[a];b&&b.settings.autohide&&(b.hide(),s.splice(a,1))}},u}),g("1y",["2j","2g","48","a","2e","49","6","5"],function(a,b,c,d,e,f,g,h){"use strict";function i(a){var b,c="width=device-width,initial-scale=1.0,user-scalable=0,minimum-scale=1.0,maximum-scale=1.0",e=d("meta[name=viewport]")[0];g.overrideViewPort!==!1&&(e||(e=document.createElement("meta"),e.setAttribute("name","viewport"),document.getElementsByTagName("head")[0].appendChild(e)),b=e.getAttribute("content"),b&&"undefined"!=typeof n&&(n=b),e.setAttribute("content",a?c:n))}function j(a,b){k()&
amp;&b===!1&&d([document.documentElement,document.body]).removeClass(a+"fullscreen")}function k(){for(var a=0;a<m.length;a++)if(m[a]._fullscreen)return!0;return!1}function l(){function a(){var a,b,d=c.getWindowSize();for(a=0;a<m.length;a++)b=m[a].layoutRect(),m[a].moveTo(m[a].settings.x||Math.max(0,d.w/2-b.w/2),m[a].settings.y||Math.max(0,d.h/2-b.h/2))}if(!g.desktop){var b={w:window.innerWidth,h:window.innerHeight};h.setInterval(function(){var a=window.innerWidth,c=window.innerHeight;b.w==a&&b.h==c||(b={w:a,h:c},d(window).trigger("resize"))},100)}d(window).on("resize",a)}var m=[],n="",o=a.extend({modal:!0,Defaults:{border:1,layout:"flex",containerCls:"panel",role:"dialog",callbacks:{submit:function(){this.fire("submit",{data:this.toJSON()})},close:function(){this.close()}}},init:function(a){var d=this;d._super(a),d.isRtl()&&d.classes.add("rtl"),d.classes.add(&q
uot;window"),d.bodyClasses.add("window-body"),d.state.set("fixed",!0),a.buttons&&(d.statusbar=new b({layout:"flex",border:"1 0 0 0",spacing:3,padding:10,align:"center",pack:d.isRtl()?"start":"end",defaults:{type:"button"},items:a.buttons}),d.statusbar.classes.add("foot"),d.statusbar.parent(d)),d.on("click",function(a){var b=d.classPrefix+"close";(c.hasClass(a.target,b)||c.hasClass(a.target.parentNode,b))&&d.close()}),d.on("cancel",function(){d.close()}),d.aria("describedby",d.describedBy||d._id+"-none"),d.aria("label",a.title),d._fullscreen=!1},recalc:function(){var a,b,d,e,f=this,g=f.statusbar;f._fullscreen&&(f.layoutRect(c.getWindowSize()),f.layoutRect().contentH=f.layoutRect().innerH),f._super(),a=f.layoutRect(),f.settings.title&&!f._fullscreen&&(b=a.headerW,b>a.w&&(d=a.x-Math.
max(0,b/2),f.layoutRect({w:b,x:d}),e=!0)),g&&(g.layoutRect({w:f.layoutRect().innerW}).recalc(),b=g.layoutRect().minW+a.deltaW,b>a.w&&(d=a.x-Math.max(0,b-a.w),f.layoutRect({w:b,x:d}),e=!0)),e&&f.recalc()},initLayoutRect:function(){var a,b=this,d=b._super(),e=0;if(b.settings.title&&!b._fullscreen){a=b.getEl("head");var f=c.getSize(a);d.headerW=f.width,d.headerH=f.height,e+=d.headerH}b.statusbar&&(e+=b.statusbar.layoutRect().h),d.deltaH+=e,d.minH+=e,d.h+=e;var g=c.getWindowSize();return d.x=b.settings.x||Math.max(0,g.w/2-d.w/2),d.y=b.settings.y||Math.max(0,g.h/2-d.h/2),d},renderHtml:function(){var a=this,b=a._layout,c=a._id,d=a.classPrefix,e=a.settings,f="",g="",h=e.html;return a.preRender(),b.preRender(a),e.title&&(f='<div id="'+c+'-head" class="'+d+'window-head"><div id="'+c+'-title" class="'+d+'title">'+a.encode(e.title)+'</div><div id="'
+c+'-dragh" class="'+d+'dragh"></div><button type="button" class="'+d+'close" aria-hidden="true"><i class="mce-ico mce-i-remove"></i></button></div>'),
+e.url&&(h='<iframe src="'+e.url+'" tabindex="-1"></iframe>'),"undefined"==typeof h&&(h=b.renderHtml(a)),a.statusbar&&(g=a.statusbar.renderHtml()),'<div id="'+c+'" class="'+a.classes+'" hidefocus="1"><div class="'+a.classPrefix+'reset" role="application">'+f+'<div id="'+c+'-body" class="'+a.bodyClasses+'">'+h+"</div>"+g+"</div></div>"},fullscreen:function(a){var b,e,g=this,i=document.documentElement,j=g.classPrefix;if(a!=g._fullscreen)if(d(window).on("resize",function(){var a;if(g._fullscreen)if(b)g._timer||(g._timer=h.setTimeout(function(){var a=c.getWindowSize();g.moveTo(0,0).resizeTo(a.w,a.h),g._timer=0},50));else{a=(new Date).getTime();var d=c.getWindowSize();g.moveTo(0,0).resizeTo(d.w,d.h),(new Date).getTime()-a>50&&(b=!0)}}),e=g.layoutRect(),g._fullscreen=a,a){g._initi
al={x:e.x,y:e.y,w:e.w,h:e.h},g.borderBox=f.parseBox("0"),g.getEl("head").style.display="none",e.deltaH-=e.headerH+2,d([i,document.body]).addClass(j+"fullscreen"),g.classes.add("fullscreen");var k=c.getWindowSize();g.moveTo(0,0).resizeTo(k.w,k.h)}else g.borderBox=f.parseBox(g.settings.border),g.getEl("head").style.display="",e.deltaH+=e.headerH,d([i,document.body]).removeClass(j+"fullscreen"),g.classes.remove("fullscreen"),g.moveTo(g._initial.x,g._initial.y).resizeTo(g._initial.w,g._initial.h);return g.reflow()},postRender:function(){var a,b=this;setTimeout(function(){b.classes.add("in"),b.fire("open")},0),b._super(),b.statusbar&&b.statusbar.postRender(),b.focus(),this.dragHelper=new e(b._id+"-dragh",{start:function(){a={x:b.layoutRect().x,y:b.layoutRect().y}},drag:function(c){b.moveTo(a.x+c.deltaX,a.y+c.deltaY)}}),b.on("submit",function(a){a.isDef
aultPrevented()||b.close()}),m.push(b),i(!0)},submit:function(){return this.fire("submit",{data:this.toJSON()})},remove:function(){var a,b=this;for(b.dragHelper.destroy(),b._super(),b.statusbar&&this.statusbar.remove(),j(b.classPrefix,!1),a=m.length;a--;)m[a]===b&&m.splice(a,1);i(m.length>0)},getContentWindow:function(){var a=this.getEl().getElementsByTagName("iframe")[0];return a?a.contentWindow:null}});return l(),o}),g("1z",["1y"],function(a){"use strict";var b=a.extend({init:function(a){a={border:1,padding:20,layout:"flex",pack:"center",align:"center",containerCls:"panel",autoScroll:!0,buttons:{type:"button",text:"Ok",action:"ok"},items:{type:"label",multiline:!0,maxWidth:500,maxHeight:200}},this._super(a)},Statics:{OK:1,OK_CANCEL:2,YES_NO:3,YES_NO_CANCEL:4,msgBox:function(c){function d(a,b,c){return{type:"button",text:a,su
btype:c?"primary":"",onClick:function(a){a.control.parents()[1].close(),f(b)}}}var e,f=c.callback||function(){};switch(c.buttons){case b.OK_CANCEL:e=[d("Ok",!0,!0),d("Cancel",!1)];break;case b.YES_NO:case b.YES_NO_CANCEL:e=[d("Yes",1,!0),d("No",0)],c.buttons==b.YES_NO_CANCEL&&e.push(d("Cancel",-1));break;default:e=[d("Ok",!0,!0)]}return new a({padding:20,x:c.x,y:c.y,minWidth:300,minHeight:100,layout:"flex",pack:"center",align:"center",buttons:e,title:c.title,role:"alertdialog",items:{type:"label",multiline:!0,maxWidth:500,maxHeight:200,text:c.text},onPostRender:function(){this.aria("describedby",this.items()[0]._id)},onClose:c.onClose,onCancel:function(){f(!1)}}).renderTo(document.body).reflow()},alert:function(a,c){return"string"==typeof a&&(a={text:a}),a.callback=c,b.msgBox(a)},confirm:function(a,c){return"string
"==typeof a&&(a={text:a}),a.callback=c,a.buttons=b.OK_CANCEL,b.msgBox(a)}}});return b}),g("10",["1y","1z"],function(a,b){return function(c){function d(){if(h.length)return h[h.length-1]}function e(a){c.fire("OpenWindow",{win:a})}function f(a){c.fire("CloseWindow",{win:a})}var g=this,h=[];g.windows=h,c.on("remove",function(){for(var a=h.length;a--;)h[a].close()}),g.open=function(b,d){var g;return c.editorManager.setActive(c),b.title=b.title||" ",b.url=b.url||b.file,b.url&&(b.width=parseInt(b.width||320,10),b.height=parseInt(b.height||240,10)),b.body&&(b.items={defaults:b.defaults,type:b.bodyType||"form",items:b.body,data:b.data,callbacks:b.commands}),b.url||b.buttons||(b.buttons=[{text:"Ok",subtype:"primary",onclick:function(){g.find("form")[0].submit()}},{text:"Cancel",onclick:function(){g.close()}}]),g=new a(b),h.push(g),g.on("clo
se",function(){for(var a=h.length;a--;)h[a]===g&&h.splice(a,1);h.length||c.focus(),f(g)}),b.data&&g.on("postRender",function(){this.find("*").each(function(a){var c=a.name();c in b.data&&a.value(b.data[c])})}),g.features=b||{},g.params=d||{},1===h.length&&c.nodeChanged(),g=g.renderTo().reflow(),e(g),g},g.alert=function(a,d,g){var h;h=b.alert(a,function(){d?d.call(g||this):c.focus()}),h.on("close",function(){f(h)}),e(h)},g.confirm=function(a,c,d){var g;g=b.confirm(a,function(a){c.call(d||this,a)}),g.on("close",function(){f(g)}),e(g)},g.close=function(){d()&&d().close()},g.getParams=function(){return d()?d().params:null},g.setParams=function(a){d()&&(d().params=a)},g.getWindows=function(){return h}}}),g("2k",["2a","2h"],function(a,b){return a.extend({Mixins:[b],Defaults:{classes:"widget tooltip tooltip-n"},renderHtml:function(){var a=this,b=a.classPrefix
;return'<div id="'+a._id+'" class="'+a.classes+'" role="presentation"><div class="'+b+'tooltip-arrow"></div><div class="'+b+'tooltip-inner">'+a.encode(a.state.get("text"))+"</div></div>"},bindStates:function(){var a=this;return a.state.on("change:text",function(b){a.getEl().lastChild.innerHTML=a.encode(b.value)}),a._super()},repaint:function(){var a,b,c=this;a=c.getEl().style,b=c._layoutRect,a.left=b.x+"px",a.top=b.y+"px",a.zIndex=131070}})}),g("2l",["2a","2k"],function(a,b){"use strict";var c,d=a.extend({init:function(a){var b=this;b._super(a),a=b.settings,b.canFocus=!0,a.tooltip&&d.tooltips!==!1&&(b.on("mouseenter",function(c){var d=b.tooltip().moveTo(-65535);if(c.control==b){var e=d.text(a.tooltip).show().testMoveRel(b.getEl(),["bc-tc","bc-tl","bc-tr"]
);d.classes.toggle("tooltip-n","bc-tc"==e),d.classes.toggle("tooltip-nw","bc-tl"==e),d.classes.toggle("tooltip-ne","bc-tr"==e),d.moveRel(b.getEl(),e)}else d.hide()}),b.on("mouseleave mousedown click",function(){b.tooltip().hide()})),b.aria("label",a.ariaLabel||a.tooltip)},tooltip:function(){return c||(c=new b({type:"tooltip"}),c.renderTo()),c},postRender:function(){var a=this,b=a.settings;a._super(),a.parent()||!b.width&&!b.height||(a.initLayoutRect(),a.repaint()),b.autofocus&&a.focus()},bindStates:function(){function a(a){c.aria("disabled",a),c.classes.toggle("disabled",a)}function b(a){c.aria("pressed",a),c.classes.toggle("active",a)}var c=this;return c.state.on("change:disabled",function(b){a(b.value)}),c.state.on("change:active",function(a){b(a.value)}),c.state.get("disabled")&&a(!0),c.state.get(&q
uot;active")&&b(!0),c._super()},remove:function(){this._super(),c&&(c.remove(),c=null)}});return d}),g("2m",["2l"],function(a){"use strict";return a.extend({Defaults:{value:0},init:function(a){var b=this;b._super(a),b.classes.add("progress"),b.settings.filter||(b.settings.filter=function(a){return Math.round(a)})},renderHtml:function(){var a=this,b=a._id,c=this.classPrefix;return'<div id="'+b+'" class="'+a.classes+'"><div class="'+c+'bar-container"><div class="'+c+'bar"></div></div><div class="'+c+'text">0%</div></div>'},postRender:function(){var a=this;return a._super(),a.value(a.settings.value),a},bindStates:function(){function a(a){a=b.settings.filter(a),b.getEl().lastChild.innerHTML=a+"%",b.getEl().firstChild.firstChild.style.width=a+"%"}var b=this;return b.state.on("change:value",function(b){
a(b.value)}),a(b.state.get("value")),b._super()}})}),g("20",["2a","2h","2m","5"],function(a,b,c,d){return a.extend({Mixins:[b],Defaults:{classes:"widget notification"},init:function(a){var b=this;b._super(a),a.text&&b.text(a.text),a.icon&&(b.icon=a.icon),a.color&&(b.color=a.color),a.type&&b.classes.add("notification-"+a.type),a.timeout&&(a.timeout<0||a.timeout>0)&&!a.closeButton?b.closeButton=!1:(b.classes.add("has-close"),b.closeButton=!0),a.progressBar&&(b.progressBar=new c),b.on("click",function(a){a.target.className.indexOf(b.classPrefix+"close")!=-1&&b.close()})},renderHtml:function(){var a=this,b=a.classPrefix,c="",d="",e="",f="";return a.icon&&(c='<i class="'+b+"ico "+b+"i-"+a.icon+'"></i>'),a.color&&(f
=' style="background-color: '+a.color+'"'),a.closeButton&&(d='<button type="button" class="'+b+'close" aria-hidden="true">\xd7</button>'),a.progressBar&&(e=a.progressBar.renderHtml()),'<div id="'+a._id+'" class="'+a.classes+'"'+f+' role="presentation">'+c+'<div class="'+b+'notification-inner">'+a.state.get("text")+"</div>"+e+d+"</div>"},postRender:function(){var a=this;return d.setTimeout(function(){a.$el.addClass(a.classPrefix+"in")}),a._super()},bindStates:function(){var a=this;return a.state.on("change:text",function(b){a.getEl().childNodes[1].innerHTML=b.value}),a.progressBar&&a.progressBar.bindStates(),a._super()},close:function(){var a=this;return a.fire("close").isDefaultPrevented()||a.remove(),a},repaint:function(){var a,b,c=this;a=c.getEl().style,b=c._layoutRect,a.left=b.x+&quo
t;px",a.top=b.y+"px",a.zIndex=65534}})}),g("11",["20","5","9"],function(a,b,c){return function(d){function e(){if(m.length)return m[m.length-1]}function f(){b.requestAnimationFrame(function(){g(),h()})}function g(){for(var a=0;a<m.length;a++)m[a].moveTo(0,0)}function h(){if(m.length>0){var a=m.slice(0,1)[0],b=d.inline?d.getElement():d.getContentAreaContainer();if(a.moveRel(b,"tc-tc"),m.length>1)for(var c=1;c<m.length;c++)m[c].moveRel(m[c-1].getEl(),"bc-tc")}}function i(a,b){if(!k(b))return null;var d=c.grep(a,function(a){return j(b,a)});return 0===d.length?null:d[0]}function j(a,b){return a.type===b.settings.type&&a.text===b.settings.text}function k(a){return!a.progressBar&&!a.timeout}var l=this,m=[];l.notifications=m,d.on("remove",function(){for(var a=m.length;a--;)m[a].close()}),d.on("ResizeEditor",h),d.on("ResizeWindow",f),l.open=function(b){if(!d.r
emoved){var c;d.editorManager.setActive(d);var e=i(m,b);return null===e?(c=new a(b),m.push(c),b.timeout>0&&(c.timer=setTimeout(function(){c.close()},b.timeout)),c.on("close",function(){var a=m.length;for(c.timer&&d.getWin().clearTimeout(c.timer);a--;)m[a]===c&&m.splice(a,1);h()}),c.renderTo(),h()):c=e,c}},l.close=function(){e()&&e().close()},l.getNotifications=function(){return m},d.on("SkinLoaded",function(){var a=d.settings.service_message;a&&d.notificationManager.open({text:a,type:"warning",timeout:0,icon:""})})}}),g("12",["z","e","9"],function(a,b,c){function d(a,b){return"selectionchange"==b?a.getDoc():!a.inline&&/^mouse|touch|click|contextmenu|drop|dragover|dragend/.test(b)?a.getDoc().documentElement:a.settings.event_root?(a.eventRoot||(a.eventRoot=g.select(a.settings.event_root)[0]),a.eventRoot):a.getBody()}function e(a,b){function c(a){
return!a.hidden&&!a.readonly}var e,h=d(a,b);if(a.delegates||(a.delegates={}),!a.delegates[b])if(a.settings.event_root){if(f||(f={},a.editorManager.on("removeEditor",function(){var b;if(!a.editorManager.activeEditor&&f){for(b in f)a.dom.unbind(d(a,b));f=null}})),f[b])return;e=function(d){for(var e=d.target,f=a.editorManager.editors,h=f.length;h--;){var i=f[h].getBody();(i===e||g.isChildOf(e,i))&&c(f[h])&&f[h].fire(b,d)}},f[b]=e,g.bind(h,b,e)}else e=function(d){c(a)&&a.fire(b,d)},g.bind(h,b,e),a.delegates[b]=e}var f,g=b.DOM,h={bindPendingEventDelegates:function(){var a=this;c.each(a._pendingNativeEvents,function(b){e(a,b)})},toggleNativeEvent:function(a,b){var c=this;"focus"!=a&&"blur"!=a&&(b?c.initialized?e(c,a):c._pendingNativeEvents?c._pendingNativeEvents.push(a):c._pendingNativeEvents=[a]:c.initialized&&(c.dom.unbind(d(c,a),a,c.delegates[a]),delete c.delegates[a]))},unbindAllNativeEvents:
function(){var a,b=this;if(b.delegates){for(a in b.delegates)b.dom.unbind(d(b,a),a,b.delegates[a]);delete b.delegates}b.inline||(b.getBody().onload=null,b.dom.unbind(b.getWin()),b.dom.unbind(b.getDoc())),b.dom.unbind(b.getBody()),b.dom.unbind(b.getContainer())}};return h=c.extend({},a,h)}),g("13",["9","6"],function(a,b){var c=a.each,d=a.explode,e={f9:120,f10:121,f11:122},f=a.makeMap("alt,ctrl,shift,meta,access");return function(g){function h(a){var g,h,i={};c(d(a,"+"),function(a){a in f?i[a]=!0:/^[0-9]{2,}$/.test(a)?i.keyCode=parseInt(a,10):(i.charCode=a.charCodeAt(0),i.keyCode=e[a]||a.toUpperCase().charCodeAt(0))}),g=[i.keyCode];for(h in f)i[h]?g.push(h):i[h]=!1;return i.id=g.join(","),i.access&&(i.alt=!0,b.mac?i.ctrl=!0:i.shift=!0),i.meta&&(b.mac?i.meta=!0:(i.ctrl=!0,i.meta=!1)),i}function i(b,c,e,f){var i;return i=a.map(d(b,">"),h),i[i.length-1]=a.extend(i[i.length-1],{func:e,scope:f||g}),a.e
xtend(i[0],{desc:g.translate(c),subpatterns:i.slice(1)})}function j(a){return a.altKey||a.ctrlKey||a.metaKey}function k(a){return"keydown"===a.type&&a.keyCode>=112&&a.keyCode<=123}function l(a,b){return!!b&&(b.ctrl==a.ctrlKey&&b.meta==a.metaKey&&(b.alt==a.altKey&&b.shift==a.shiftKey&&(!!(a.keyCode==b.keyCode||a.charCode&&a.charCode==b.charCode)&&(a.preventDefault(),!0))))}function m(a){return a.func?a.func.call(a.scope):null}var n=this,o={},p=[];g.on("keyup keypress keydown",function(a){!j(a)&&!k(a)||a.isDefaultPrevented()||(c(o,function(b){if(l(a,b))return p=b.subpatterns.slice(0),"keydown"==a.type&&m(b),!0}),l(a,p[0])&&(1===p.length&&"keydown"==a.type&&m(p[0]),p.shift()))}),n.add=function(b,e,f,h){var j;return j=f,"string"==typeof f?f=function(){g.execCommand(j,!1,null)}:a.isArray(j)&&(f=function(){g.execCom
mand(j[0],j[1],j[2])}),c(d(a.trim(b.toLowerCase())),function(a){var b=i(a,e,f,h);o[b.id]=b}),!0},n.remove=function(a){var b=i(a);return!!o[b.id]&&(delete o[b.id],!0)}}}),h("4b",window),g("25",["g"],function(a){var b=a.PluginManager,c=function(a,c){for(var d in b.urls){var e=b.urls[d]+"/plugin"+c+".js";if(e===a)return d}return null},d=function(a,b){var d=c(b,a.suffix);return d?"Failed to load plugin: "+d+" from url "+b:"Failed to load plugin url: "+b},e=function(a,b){a.notificationManager.open({type:"error",text:b})},f=function(a,b){a._skinLoaded?e(a,b):a.on("SkinLoaded",function(){e(a,b)})},g=function(a,b){f(a,"Failed to upload image: "+b)},h=function(a,b){f(a,d(a,b))},i=function(a,b){f(a,"Failed to load content css: "+b[0])},j=function(a){var b=window.console;b&&!window.test&&(b.error?b.error.apply(b,arguments):b.log.apply(b,arguments))};re
turn{pluginLoadError:h,uploadError:g,displayError:f,contentCssError:i,initError:j}}),g("5o",["3s","1k"],function(a,b){var c=function(a){return a.dom.select("*[data-mce-caret]")[0]},d=function(a){a.selection.setRng(a.selection.getRng())},e=function(a,c){c.hasAttribute("data-mce-caret")&&(b.showCaretContainerBlock(c),d(a),a.selection.scrollIntoView(c))},f=function(a,d){var f=c(a);if(f)return"compositionstart"===d.type?(d.preventDefault(),d.stopPropagation(),void e(f)):void(b.hasContent(f)&&e(a,f))},g=function(b){b.on("keyup compositionstart",a.curry(f,b))};return{setup:g}}),g("69",["4","9","1r"],function(a,b,c){return function(c,d){function e(a,b){return a?a.replace(/\/$/,"")+"/"+b.replace(/^\//,""):b}function f(a,b,c,f){var g,h;g=new XMLHttpRequest,g.open("POST",d.url),g.withCredentials=d.credentials,g.upload.onprogress=
function(a){f(a.loaded/a.total*100)},g.onerror=function(){c("Image upload failed due to a XHR Transport error. Code: "+g.status)},g.onload=function(){var a;return 200!=g.status?void c("HTTP Error: "+g.status):(a=JSON.parse(g.responseText),a&&"string"==typeof a.location?void b(e(d.basePath,a.location)):void c("Invalid JSON: "+g.responseText))},h=new FormData,h.append("file",a.blob(),a.filename()),g.send(h)}function g(){return new a(function(a){a([])})}function h(a,b){return{url:b,blobInfo:a,status:!0}}function i(a,b){return{url:"",blobInfo:a,status:!1,error:b}}function j(a,c){b.each(p[a],function(a){a(c)}),delete p[a]}function k(b,d,e){return c.markPending(b.blobUri()),new a(function(a){var f,g,k=function(){};try{var l=function(){f&&(f.close(),g=k)},m=function(d){l(),c.markUploaded(b.blobUri(),d),j(b.blobUri(),h(b,d)),a(h(b,d))},n=function(d){l(),c.removeFailed(b.blobUri()),j(b.blobUri(),i(b,d)),a(i(b,d))};g=
function(a){a<0||a>100||(f||(f=e()),f.progressBar.value(a))},d(b,m,n,g)}catch(c){a(i(b,c.message))}})}function l(a){return a===f}function m(b){var c=b.blobUri();return new a(function(a){p[c]=p[c]||[],p[c].push(a)})}function n(e,f){return e=b.grep(e,function(a){return!c.isUploaded(a.blobUri())}),a.all(b.map(e,function(a){return c.isPending(a.blobUri())?m(a):k(a,d.handler,f)}))}function o(a,b){return!d.url&&l(d.handler)?g():n(a,b)}var p={};return d=b.extend({credentials:!1,handler:f},d),{upload:o}}}),g("6u",["4"],function(a){function b(b){return new a(function(a,c){var d=function(){c("Cannot convert "+b+" to Blob. Resource might not exist or is inaccessible.")};try{var e=new XMLHttpRequest;e.open("GET",b,!0),e.responseType="blob",e.onload=function(){200==this.status?a(this.response):d()},e.onerror=d,e.send()}catch(a){d()}})}function c(a){var b,c;return a=decodeURIComponent(a).split(","),c=/data:([^;]+)
/.exec(a[0]),c&&(b=c[1]),{type:b,data:a[1]}}function d(b){return new a(function(a){var d,e,f;b=c(b);try{d=atob(b.data)}catch(b){return void a(new Blob([]))}for(e=new Uint8Array(d.length),f=0;f<e.length;f++)e[f]=d.charCodeAt(f);a(new Blob([e],{type:b.type}))})}function e(a){return 0===a.indexOf("blob:")?b(a):0===a.indexOf("data:")?d(a):null}function f(b){return new a(function(a){var c=new FileReader;c.onloadend=function(){a(c.result)},c.readAsDataURL(b)})}return{uriToBlob:e,blobToDataUri:f,parseDataUri:c}}),g("6a",["4","1g","1r","6u","6"],function(a,b,c,d,e){var f=0,g=function(a){return(a||"blobid")+f++};return function(f,h){function i(i,k){function l(a,b,c){var e,f;return 0===a.src.indexOf("blob:")?(f=h.getByUri(a.src),void(f?b({image:a,blobInfo:f}):d.uriToBlob(a.src).then(function(c){d.blobToDataUri(c).then(function(i){e=d.parseDataUri(i).data,f=h.create(g(),c,e),h.add(f),
b({image:a,blobInfo:f})})},function(a){c(a)}))):(e=d.parseDataUri(a.src).data,f=h.findFirst(function(a){return a.base64()===e}),void(f?b({image:a,blobInfo:f}):d.uriToBlob(a.src).then(function(c){f=h.create(g(),c,e),h.add(f),b({image:a,blobInfo:f})},function(a){c(a)})))}var m,n;return k||(k=c.constant(!0)),m=b.filter(i.getElementsByTagName("img"),function(a){var b=a.src;return!!e.fileApi&&(!a.hasAttribute("data-mce-bogus")&&(!a.hasAttribute("data-mce-placeholder")&&(!(!b||b==e.transparentSrc)&&(0===b.indexOf("blob:")?!f.isUploaded(b):0===b.indexOf("data:")&&k(a)))))}),n=b.map(m,function(b){var c;return j[b.src]?new a(function(a){j[b.src].then(function(c){return"string"==typeof c?c:void a({image:b,blobInfo:c.blobInfo})})}):(c=new a(function(a,c){l(b,a,c)}).then(function(a){return delete j[a.image.src],a})["catch"](function(a){return delete j[b.src],a}),j[b.src]=c,c)}),a.all(n)
}var j={};return{findAll:i}}}),g("24",[],function(){var a=0,b=function(){var a=function(){return Math.round(4294967295*Math.random()).toString(36)},b=(new Date).getTime();return"s"+b.toString(36)+a()+a()+a()},c=function(c){return c+a++ +b()};return{uuid:c}}),h("6v",URL),g("6b",["1g","1r","24","6v"],function(a,b,c,d){return function(){function e(a){var b={"image/jpeg":"jpg","image/jpg":"jpg","image/gif":"gif","image/png":"png"};return b[a.toLowerCase()]||"dat"}function f(a,b,c,d){return g("object"==typeof a?a:{id:a,name:d,blob:b,base64:c})}function g(a){var b,f;if(!a.blob||!a.base64)throw"blob and base64 representations of the image are required for BlobInfo to be created";return b=a.id||c.uuid("blobid"),f=a.name||b,{id:o(b),name:o(f),filename:o(f+"."+e(a.blob.type)),blob:o(a.b
lob),base64:o(a.base64),blobUri:o(a.blobUri||d.createObjectURL(a.blob)),uri:o(a.uri)}}function h(a){i(a.id())||n.push(a)}function i(a){return j(function(b){return b.id()===a})}function j(b){return a.filter(n,b)[0]}function k(a){return j(function(b){return b.blobUri()==a})}function l(b){n=a.filter(n,function(a){return a.blobUri()!==b||(d.revokeObjectURL(a.blobUri()),!1)})}function m(){a.each(n,function(a){d.revokeObjectURL(a.blobUri())}),n=[]}var n=[],o=b.constant;return{create:f,add:h,get:i,getByUri:k,findFirst:j,removeByUri:l,destroy:m}}}),g("6c",[],function(){return function(){function a(a,b){return{status:a,resultUri:b}}function b(a){return a in l}function c(a){var b=l[a];return b?b.resultUri:null}function d(a){return!!b(a)&&l[a].status===j}function e(a){return!!b(a)&&l[a].status===k}function f(b){l[b]=a(j,null)}function g(b,c){l[b]=a(k,c)}function h(a){delete l[a]}function i(){l={}}var j=1,k=2,l={};return{hasBlobUri:b,getResultUri:c,isPending:d,isUpload
ed:e,markPending:f,markUploaded:g,removeFailed:h,destroy:i}}}),g("5p",["1g","69","6a","6b","6c","25"],function(a,b,c,d,e,f){return function(g){function h(a){return function(b){return g.selection?a(b):[]}}function i(){return"?"+(new Date).getTime()}function j(a,b,c){var d=0;do d=a.indexOf(b,d),d!==-1&&(a=a.substring(0,d)+c+a.substr(d+b.length),d+=c.length-b.length+1);while(d!==-1);return a}function k(a,b,c){return a=j(a,'src="'+b+'"','src="'+c+'"'),a=j(a,'data-mce-src="'+b+'"','data-mce-src="'+c+'"')}function l(b,c){a.each(g.undoManager.data,function(d){"fragmented"===d.type?d.fragments=a.map(d.fragments,function(a){return k(a,b,c)}):d.content=k(d.content,b,c)})}function m(){return g.notificationManager.open({text:g.translate("Image uploading..."),type:"info",timeout:-1,progressBar:!0})}function n(a,b){w.removeByUri(a.src),l(a.s
rc,b),g.$(a).attr({src:x.images_reuse_filename?b+i():b,"data-mce-src":g.convertURL(b,"src")})}function o(c){return u||(u=new b(y,{url:x.images_upload_url,basePath:x.images_upload_base_path,credentials:x.images_upload_credentials,handler:x.images_upload_handler})),r().then(h(function(b){var d;return d=a.map(b,function(a){return a.blobInfo}),u.upload(d,m).then(h(function(d){var e=a.map(d,function(a,c){var d=b[c].image;return a.status&&g.settings.images_replace_blob_uris!==!1?n(d,a.url):a.error&&f.uploadError(g,a.error),{element:d,status:a.status}});return c&&c(e),e}))}))}function p(a){if(x.automatic_uploads!==!1)return o(a)}function q(a){return!x.images_dataimg_filter||x.images_dataimg_filter(a)}function r(){return v||(v=new c(y,w)),v.findAll(g.getBody(),q).then(h(function(b){return b=a.filter(b,function(a){return"string"!=typeof a||(f.displayError(g,a),!1)}),a.each(b,function(a){l(a.image.src,a.blobInfo.blobUri()),a.image.src=a.bl
obInfo.blobUri(),a.image.removeAttribute("data-mce-src")}),b}))}function s(){w.destroy(),y.destroy(),v=u=null}function t(b){return b.replace(/src="(blob:[^"]+)"/g,function(b,c){var d=y.getResultUri(c);if(d)return'src="'+d+'"';var e=w.getByUri(c);return e||(e=a.reduce(g.editorManager.editors,function(a,b){return a||b.editorUpload&&b.editorUpload.blobCache.getByUri(c)},null)),e?'src="data:'+e.blob().type+";base64,"+e.base64()+'"':b})}var u,v,w=new d,x=g.settings,y=new e;return g.on("setContent",function(){g.settings.automatic_uploads!==!1?p():r()}),g.on("RawSaveContent",function(a){a.content=t(a.content)}),g.on("getContent",function(a){a.source_view||"raw"==a.format||(a.content=t(a.content))}),g.on("PostRender",function(){g.parser.addNodeFilter("img",function(b){a.each(b,function(a){var b=a.attr("src");if(!w.getByUri(b)){var c=y.getResultUri(b);c&&am
p;a.attr("src",c)}})})}),{blobCache:w,uploadImages:o,uploadImagesAuto:p,scanForImages:r,destroy:s}}}),g("5q",["3s"],function(a){var b=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n=a.settings,o=a.dom,p=a.selection,q=a.schema,r=q.getBlockElements(),s=p.getStart(),t=a.getBody(),u=-16777215;if(m=n.forced_root_block,s&&1===s.nodeType&&m){for(;s&&s!==t;){if(r[s.nodeName])return;s=s.parentNode}if(b=p.getRng(),b.setStart){c=b.startContainer,d=b.startOffset,e=b.endContainer,f=b.endOffset;try{j=a.getDoc().activeElement===t}catch(a){}}else b.item&&(s=b.item(0),b=a.getDoc().body.createTextRange(),b.moveToElementText(s)),j=b.parentElement().ownerDocument===a.getDoc(),k=b.duplicate(),k.collapse(!0),d=k.move("character",u)*-1,k.collapsed||(k=b.duplicate(),k.collapse(!1),f=k.move("character",u)*-1-d);for(s=t.firstChild,l=t.nodeName.toLowerCase();s;)if((3===s.nodeType||1==s.nodeType&&!r[s.nodeName])&&q.isVa
lidChild(l,m.toLowerCase())){if(3===s.nodeType&&0===s.nodeValue.length){h=s,s=s.nextSibling,o.remove(h);continue}g||(g=o.create(m,a.settings.forced_root_block_attrs),s.parentNode.insertBefore(g,s),i=!0),h=s,s=s.nextSibling,g.appendChild(h)}else g=null,s=s.nextSibling;if(i&&j){if(b.setStart)b.setStart(c,d),b.setEnd(e,f),p.setRng(b);else try{b=a.getDoc().body.createTextRange(),b.moveToElementText(t),b.collapse(!0),b.moveStart("character",d),f>0&&b.moveEnd("character",f),b.select()}catch(a){}a.nodeChanged()}}},c=function(c){c.settings.forced_root_block&&c.on("NodeChange",a.curry(b,c))};return{setup:c}}),g("73",["62","4i","4j"],function(a,b,c){var d=function(a,b){return b},e=function(b,c){var d=a.isObject(b)&&a.isObject(c);return d?g(b,c):c},f=function(a){return function(){for(var d=new b(arguments.length),e=0;e<d.length;e++)d[e]=arguments[e];if(0===d.length)throw new c(&q
uot;Can't merge zero objects");for(var f={},g=0;g<d.length;g++){var h=d[g];for(var i in h)h.hasOwnProperty(i)&&(f[i]=a(f[i],h[i]))}return f}},g=f(e),h=f(d);return{deepMerge:g,merge:h}}),g("6w",["3r","3s","73"],function(a,b,c){var d=function(d){return a.map(d,function(a){return c.merge({shiftKey:!1,altKey:!1,ctrlKey:!1,metaKey:!1,keyCode:0,action:b.noop},a)})},e=function(a,b){return b.keyCode===a.keyCode&&b.shiftKey===a.shiftKey&&b.altKey===a.altKey&&b.ctrlKey===a.ctrlKey&&b.metaKey===a.metaKey},f=function(b,c){return a.bind(d(b),function(a){return e(a,c)?[a]:[]})},g=function(a){var b=Array.prototype.slice.call(arguments,1);return function(){return a.apply(null,b)}};return{match:f,action:g}}),g("6d",["3r","5n","50","6w","p"],function(a,b,c,d,e){var f=function(b,f){b.on("keydown",function(g){var h=d.match([{keyCode:e.RIGHT,action
:c.move(b,f,!0)},{keyCode:e.LEFT,action:c.move(b,f,!1)}],g);a.find(h,function(a){return a.action()}).each(function(a){g.preventDefault()})})};return{setup:f}}),g("6e",["3r","40","41","42","43","6w","p"],function(a,b,c,d,e,f,g){var h=function(h,i){h.on("keydown",function(j){var k=f.match([{keyCode:g.BACKSPACE,action:f.action(e.backspaceDelete,h,i,!1)},{keyCode:g.DELETE,action:f.action(e.backspaceDelete,h,i,!0)},{keyCode:g.BACKSPACE,action:f.action(d.backspaceDelete,h,!1)},{keyCode:g.DELETE,action:f.action(d.backspaceDelete,h,!0)},{keyCode:g.BACKSPACE,action:f.action(c.backspaceDelete,h,!1)},{keyCode:g.DELETE,action:f.action(c.backspaceDelete,h,!0)},{keyCode:g.BACKSPACE,action:f.action(b.backspaceDelete,h,!1)},{keyCode:g.DELETE,action:f.action(b.backspaceDelete,h,!0)}],j);a.find(k,function(a){return a.action()}).each(function(a){j.preventDefault()})})},i=function(b){b.on("keyup",functio
n(c){var e=f.match([{keyCode:g.BACKSPACE,action:f.action(d.paddEmptyElement,b)},{keyCode:g.DELETE,action:f.action(d.paddEmptyElement,b)}],c);a.find(e,function(a){return a.action()})})},j=function(a,b){h(a,b),i(a)};return{setup:j}}),g("6f",["1k","1j","h","c","6","1l","9"],function(a,b,c,d,e,f,g){var h=e.ie&&e.ie<11,i=function(a){return a&&"A"===a.nodeName&&0===g.trim(f.trim(a.innerText||a.textContent)).length},j=function(a){return a&&/^(TD|TH|CAPTION)$/.test(a.nodeName)},k=function(a){a.innerHTML=h?"":'<br data-mce-bogus="1">'},l=function(a,b){return b&&a.isBlock(b)&&!/^(TD|TH|CAPTION|FORM)$/.test(b.nodeName)&&!/^(fixed|absolute)/i.test(b.style.position)&&"true"!==a.getContentEditable(b)},m=function(a,b,c){var d;a.isBlock(c)&&(d=b.getRng(),c.appendChild(a.create("span",null,&q
uot;\xa0")),b.select(c),c.lastChild.outerHTML="",b.setRng(d))},n=function(a,b,c){var d,e=c,f=[];if(e){for(;e=e.firstChild;){if(a.isBlock(e))return;1!=e.nodeType||b[e.nodeName.toLowerCase()]||f.push(e)}for(d=f.length;d--;)e=f[d],!e.hasChildNodes()||e.firstChild==e.lastChild&&""===e.firstChild.nodeValue?a.remove(e):i(e)&&a.remove(e)}},o=function(a,c,d){return b.isText(c)===!1?d:a?1===d&&c.data.charAt(d-1)===f.ZWSP?0:d:d===c.data.length-1&&c.data.charAt(d)===f.ZWSP?c.data.length:d},p=function(a){var b=a.cloneRange();return b.setStart(a.startContainer,o(!0,a.startContainer,a.startOffset)),b.setEnd(a.endContainer,o(!1,a.endContainer,a.endOffset)),b},q=function(a){for(;a;){if(1===a.nodeType||3===a.nodeType&&a.data&&/[\r\n\s]/.test(a.data))return a;a=a.nextSibling}},r=function(b){function f(f){function w(a){var b,c,f,h,j=a;if(a){if(e.ie&&e.ie<9&&M&&M.firstChild&&M.firstChild==M.lastC
hild&&"BR"==M.firstChild.tagName&&g.remove(M.firstChild),/^(LI|DT|DD)$/.test(a.nodeName)){var k=q(a.firstChild);k&&/^(UL|OL|DL)$/.test(k.nodeName)&&a.insertBefore(g.doc.createTextNode("\xa0"),a.firstChild)}if(f=g.createRng(),e.ie||a.normalize(),a.hasChildNodes()){for(b=new d(a,a);c=b.current();){if(3==c.nodeType){f.setStart(c,0),f.setEnd(c,0);break}if(v[c.nodeName.toLowerCase()]){f.setStartBefore(c),f.setEndBefore(c);break}j=c,c=b.next()}c||(f.setStart(j,0),f.setEnd(j,0))}else"BR"==a.nodeName?a.nextSibling&&g.isBlock(a.nextSibling)?((!N||N<9)&&(h=g.create("br"),a.parentNode.insertBefore(h,a)),f.setStartBefore(a),f.setEndBefore(a)):(f.setStartAfter(a),f.setEndAfter(a)):(f.setStart(a,0),f.setEnd(a,0));i.setRng(f),g.remove(h),i.scrollIntoView(a)}}function x(a){var b=r.forced_root_block;b&&b.toLowerCase()===a.tagName.toLowerCase()&&g.setAttribs(a,r.forced_root_block_attrs)}function
y(a){var b,c,d,e=K,f=t.getTextInlineElements();if(a||"TABLE"==S?(b=g.create(a||U),x(b)):b=M.cloneNode(!1),d=b,r.keep_styles===!1)g.setAttrib(b,"style",null),g.setAttrib(b,"class",null);else do if(f[e.nodeName]){if("_mce_caret"==e.id)continue;c=e.cloneNode(!1),g.setAttrib(c,"id",""),b.hasChildNodes()?(c.appendChild(b.firstChild),b.appendChild(c)):(d=c,b.appendChild(c))}while((e=e.parentNode)&&e!=J);return h||(d.innerHTML='<br data-mce-bogus="1">'),b}function z(a){var b,c,e,f;if(f=o(a,K,L),3==K.nodeType&&(a?f>0:f<K.nodeValue.length))return!1;if(K.parentNode==M&&V&&!a)return!0;if(a&&1==K.nodeType&&K==M.firstChild)return!0;if("TABLE"===K.nodeName||K.previousSibling&&"TABLE"==K.previousSibling.nodeName)return V&&!a||!V&&a;for(b=new d(K,M),3==K.nodeType&&(a&&0===f?b.prev():a||f!=K.nodeValue.length||b.
next());c=b.current();){if(1===c.nodeType){if(!c.getAttribute("data-mce-bogus")&&(e=c.nodeName.toLowerCase(),u[e]&&"br"!==e))return!1}else if(3===c.nodeType&&!/^[ \t\r\n]*$/.test(c.nodeValue))return!1;a?b.prev():b.next()}return!0}function A(a,c){var d,e,f,h,i,k,m=U||"P";if(e=g.getParent(a,g.isBlock),!e||!l(g,e)){if(e=e||J,k=e==b.getBody()||j(e)?e.nodeName.toLowerCase():e.parentNode.nodeName.toLowerCase(),!e.hasChildNodes())return d=g.create(m),x(d),e.appendChild(d),H.setStart(d,0),H.setEnd(d,0),d;for(h=a;h.parentNode!=e;)h=h.parentNode;for(;h&&!g.isBlock(h);)f=h,h=h.previousSibling;if(f&&t.isValidChild(k,m.toLowerCase())){for(d=g.create(m),x(d),f.parentNode.insertBefore(d,f),h=f;h&&!g.isBlock(h);)i=h.nextSibling,d.appendChild(h),h=i;H.setStart(a,c),H.setEnd(a,c)}}return a}function B(){function a(a){for(var b=R[a?"firstChild":"lastChild"];b&&1!=b.nodeType;)b=b[a?"nextSibling
":"previousSibling"];return b===M}function c(){var a=R.parentNode;return/^(LI|DT|DD)$/.test(a.nodeName)?a:R}if(R!=b.getBody()){var d=R.parentNode.nodeName;/^(OL|UL|LI)$/.test(d)&&(U="LI"),P=U?y(U):g.create("BR"),a(!0)&&a()?"LI"==d?g.insertAfter(P,c()):g.replace(P,R):a(!0)?"LI"==d?(g.insertAfter(P,c()),P.appendChild(g.doc.createTextNode(" ")),P.appendChild(R)):R.parentNode.insertBefore(P,R):a()?(g.insertAfter(P,c()),m(g,i,P)):(R=c(),I=H.cloneRange(),I.setStartAfter(M),I.setEndAfter(R),Q=I.extractContents(),"LI"==U&&"LI"==Q.firstChild.nodeName?(P=Q.firstChild,g.insertAfter(Q,R)):(g.insertAfter(Q,R),g.insertAfter(P,R))),g.remove(M),w(P),s.add()}}function C(){b.execCommand("InsertLineBreak",!1,f)}function D(a){do 3===a.nodeType&&(a.nodeValue=a.nodeValue.replace(/^[\r\n]+/,"")),a=a.firstChild;while(a)}function E(a){var b,c,d=g.getRoot();for(b=a;b!==d&am
p;&"false"!==g.getContentEditable(b);)"true"===g.getContentEditable(b)&&(c=b),b=b.parentNode;return b!==d?c:d}function F(a){var b;h||(a.normalize(),b=a.lastChild,b&&!/^(left|right)$/gi.test(g.getStyle(b,"float",!0))||g.add(a,"br"))}function G(){P=/^(H[1-6]|PRE|FIGURE)$/.test(S)&&"HGROUP"!=T?y(U):y(),r.end_container_on_empty_block&&l(g,R)&&g.isEmpty(M)?P=g.split(R,M):g.insertAfter(P,M),w(P)}var H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V;if(H=i.getRng(!0),
+!f.isDefaultPrevented()){if(!H.collapsed)return void b.execCommand("Delete");if(new c(g).normalize(H),K=H.startContainer,L=H.startOffset,U=(r.force_p_newlines?"p":"")||r.forced_root_block,U=U?U.toUpperCase():"",N=g.doc.documentMode,O=f.shiftKey,1==K.nodeType&&K.hasChildNodes()&&(V=L>K.childNodes.length-1,K=K.childNodes[Math.min(L,K.childNodes.length-1)]||K,L=V&&3==K.nodeType?K.nodeValue.length:0),J=E(K)){if(s.beforeChange(),!g.isBlock(J)&&J!=g.getRoot())return void(U&&!O||C());if((U&&!O||!U&&O)&&(K=A(K,L)),M=g.getParent(K,g.isBlock),R=M?g.getParent(M.parentNode,g.isBlock):null,S=M?M.nodeName.toUpperCase():"",T=R?R.nodeName.toUpperCase():"","LI"!=T||f.ctrlKey||(M=R,S=T),b.undoManager.typing&&(b.undoManager.typing=!1,b.undoManager.add()),/^(LI|DT|DD)$/.test(S)){if(!U&&O)return void C();if(g.isEmpty(M))return void B()}if("PRE"
;==S&&r.br_in_pre!==!1){if(!O)return void C()}else if(!U&&!O&&"LI"!=S||U&&O)return void C();U&&M===b.getBody()||(U=U||"P",a.isCaretContainerBlock(M)?(P=a.showCaretContainerBlock(M),g.isEmpty(M)&&k(M),w(P)):z()?G():z(!0)?(P=M.parentNode.insertBefore(y(),M),m(g,i,P),w(M)):(I=p(H).cloneRange(),I.setEndAfter(M),Q=I.extractContents(),D(Q),P=Q.firstChild,g.insertAfter(Q,M),n(g,u,P),F(M),g.isEmpty(M)&&k(M),P.normalize(),g.isEmpty(P)?(g.remove(P),G()):w(P)),g.setAttrib(P,"id",""),b.fire("NewBlock",{newBlock:P}),s.typing=!1,s.add())}}}var g=b.dom,i=b.selection,r=b.settings,s=b.undoManager,t=b.schema,u=t.getNonEmptyElements(),v=t.getMoveCaretBeforeOnEnterElements();b.on("keydown",function(a){13==a.keyCode&&f(a)!==!1&&a.preventDefault()})};return{setup:r}}),g("6x",["3s","1n","1j","4z"],function(a,b,c,d){var e=funct
ion(a,b){return i(a)&&c.isText(b.container())},f=function(a,b){var c=b.container(),d=b.offset();c.insertData(d,"\xa0"),a.selection.setCursorLocation(c,d+1)},g=function(a,b,c){return!!e(c,b)&&(f(a,b),!0)},h=function(c){var e=b.fromRangeStart(c.selection.getRng()),f=d.readLocation(c.getBody(),e);return f.map(a.curry(g,c,e)).getOr(!1)},i=function(b){return b.fold(a.constant(!1),a.constant(!0),a.constant(!0),a.constant(!1))},j=function(a){return!!a.selection.isCollapsed()&&h(a)};return{insertAtSelection:j}}),g("6g",["3r","6x","6w","p"],function(a,b,c,d){var e=function(e,f){e.on("keydown",function(f){var g=c.match([{keyCode:d.SPACEBAR,action:c.action(b.insertAtSelection,e)}],f);a.find(g,function(a){return a.action()}).each(function(a){f.preventDefault()})})},f=function(a){e(a)};return{setup:f}}),g("5r",["6d","50","6e","6f","6g"],functio
n(a,b,c,d,e){var f=function(f){var g=b.setupSelectedState(f);a.setup(f,g),c.setup(f,g),d.setup(f),e.setup(f)};return{setup:f}}),g("5s",["h","6","5"],function(a,b,c){return function(d){function e(a){var b,c;if(c=d.$(a).parentsUntil(d.getBody()).add(a),c.length===g.length){for(b=c.length;b>=0&&c[b]===g[b];b--);if(b===-1)return g=c,!0}return g=c,!1}var f,g=[];"onselectionchange"in d.getDoc()||d.on("NodeChange Click MouseUp KeyUp Focus",function(b){var c,e;c=d.selection.getRng(),e={startContainer:c.startContainer,startOffset:c.startOffset,endContainer:c.endContainer,endOffset:c.endOffset},"nodechange"!=b.type&&a.compareRanges(e,f)||d.fire("SelectionChange"),f=e}),d.on("contextmenu",function(){d.fire("SelectionChange")}),d.on("SelectionChange",function(){var a=d.selection.getStart(!0);!b.range&&d.selection.isCollapsed()||!e(a)&&d.dom.isChildOf(a
,d.getBody())&&d.nodeChanged({selectionChange:!0})}),d.on("MouseUp",function(a){a.isDefaultPrevented()||("IMG"==d.selection.getNode().nodeName?c.setEditorTimeout(d,function(){d.nodeChanged()}):d.nodeChanged())}),this.nodeChanged=function(a){var b,c,e,f=d.selection;d.initialized&&f&&!d.settings.disable_nodechange&&!d.readonly&&(e=d.getBody(),b=f.getStart(!0)||e,b.ownerDocument==d.getDoc()&&d.dom.isChildOf(b,e)||(b=e),c=[],d.dom.getParent(b,function(a){return a===e||void c.push(a)}),a=a||{},a.element=b,a.parents=c,d.fire("NodeChange",a))}}}),g("6h",["1k","5l","1n","a","1j","h","3x","5"],function(a,b,c,d,e,f,g,h){var i=e.isContentEditableFalse;return function(c,e){function f(a,b){var d,e,f,h,i,j=g.collapse(a.getBoundingClientRect(),b);return"BODY"==c.tagName?(d=c.ownerDocument.documentElement,e=c.scrollLeft||d.
scrollLeft,f=c.scrollTop||d.scrollTop):(i=c.getBoundingClientRect(),e=c.scrollLeft-i.left,f=c.scrollTop-i.top),j.left+=e,j.right+=e,j.top+=f,j.bottom+=f,j.width=1,h=a.offsetWidth-a.clientWidth,h>0&&(b&&(h*=-1),j.left+=h,j.right+=h),j}function j(){var b,e,f,g,h;for(b=d("*[contentEditable=false]",c),g=0;g<b.length;g++)e=b[g],f=e.previousSibling,a.endsWithCaretContainer(f)&&(h=f.data,1==h.length?f.parentNode.removeChild(f):f.deleteData(h.length-1,1)),f=e.nextSibling,a.startsWithCaretContainer(f)&&(h=f.data,1==h.length?f.parentNode.removeChild(f):f.deleteData(0,1));return null}function k(b,g){var h,j;return l(),e(g)?(r=a.insertBlock("p",g,b),h=f(g,b),d(r).css("top",h.top),q=d('<div class="mce-visual-caret" data-mce-bogus="all"></div>').css(h).appendTo(c),b&&q.addClass("mce-visual-caret-before"),m(),j=g.ownerDocument.createRange(),j.setStart(r,0),j.setEnd(r,0),j):(r=a.ins
ertInline(g,b),j=g.ownerDocument.createRange(),i(r.nextSibling)?(j.setStart(r,0),j.setEnd(r,0)):(j.setStart(r,1),j.setEnd(r,1)),j)}function l(){j(),r&&(b.remove(r),r=null),q&&(q.remove(),q=null),clearInterval(p)}function m(){p=h.setInterval(function(){d("div.mce-visual-caret",c).toggleClass("mce-visual-caret-hidden")},500)}function n(){h.clearInterval(p)}function o(){return".mce-visual-caret {position: absolute;background-color: black;background-color: currentcolor;}.mce-visual-caret-hidden {display: none;}*[data-mce-caret] {position: absolute;left: -1000px;right: auto;top: 0;margin: 0;padding: 0;}"}var p,q,r;return{show:k,hide:l,getCss:o,destroy:n}}}),g("6y",["1g","1j","3x"],function(a,b,c){function d(e){function f(b){return a.map(b,function(a){return a=c.clone(a),a.node=e,a})}if(a.isArray(e))return a.reduce(e,function(a,b){return a.concat(d(b))},[]);if(b.isElement(e))return f(e.getClientRects());
if(b.isText(e)){var g=e.ownerDocument.createRange();return g.setStart(e,0),g.setEnd(e,e.data.length),f(g.getClientRects())}}return{getClientRects:d}}),g("6i",["1r","1g","6y","3w","4v","44","1n","3x"],function(a,b,c,d,e,f,g,h){function i(a,b,c,f){for(;f=e.findNode(f,a,d.isEditableCaretCandidate,b);)if(c(f))return}function j(a,d,e,f,g,h){function j(f){var h,i,j;for(j=c.getClientRects(f),a==-1&&(j=j.reverse()),h=0;h<j.length;h++)if(i=j[h],!e(i,l)){if(n.length>0&&d(i,b.last(n))&&m++,i.line=m,g(i))return!0;n.push(i)}}var k,l,m=0,n=[];return(l=b.last(h.getClientRects()))?(k=h.getNode(),j(k),i(a,f,j,k),n):n}function k(a,b){return b.line>a}function l(a,b){return b.line===a}function m(a,c,d,e){function i(c){return 1==a?b.last(c.getClientRects()):b.last(c.getClientRects())}var j,k,l,m,n,o,p=new f(c),q=[],r=0;1==a?(j=p.next,k=h.isBelow,l=h.isAbove,m=g.after(e)):(j=p.prev,k
=h.isAbove,l=h.isBelow,m=g.before(e)),o=i(m);do if(m.isVisible()&&(n=i(m),!l(n,o))){if(q.length>0&&k(n,b.last(q))&&r++,n=h.clone(n),n.position=m,n.line=r,d(n))return q;q.push(n)}while(m=j(m));return q}var n=a.curry,o=n(j,-1,h.isAbove,h.isBelow),p=n(j,1,h.isBelow,h.isAbove);return{upUntil:o,downUntil:p,positionsUntil:m,isAboveLine:n(k),isLine:n(l)}}),g("6j",["1r","1g","1j","6y","3x","4v","3w"],function(a,b,c,d,e,f,g){function h(a,b){return Math.abs(a.left-b)}function i(a,b){return Math.abs(a.right-b)}function j(a,c){function d(a,b){return a>=b.left&&a<=b.right}return b.reduce(a,function(a,b){var e,f;return e=Math.min(h(a,c),i(a,c)),f=Math.min(h(b,c),i(b,c)),d(c,b)?b:d(c,a)?a:f==e&&p(b.node)?b:f<e?b:a})}function k(a,b,c,d){for(;d=q(d,a,g.isEditableCaretCandidate,b);)if(c(d))return}function l(a,c){function f(a,e){var f;return f=b.filter(d.getClientRects(e)
,function(b){return!a(b,c)}),g=g.concat(f),0===f.length}var g=[];return g.push(c),k(-1,a,r(f,e.isAbove),c.node),k(1,a,r(f,e.isBelow),c.node),g}function m(a){return b.filter(b.toArray(a.getElementsByTagName("*")),p)}function n(a,b){return{node:a.node,before:h(a,b)<i(a,b)}}function o(a,c,e){var f,g;return f=d.getClientRects(m(a)),f=b.filter(f,function(a){return e>=a.top&&e<=a.bottom}),g=j(f,c),g&&(g=j(l(a,g),c),g&&p(g.node))?n(g,c):null}var p=c.isContentEditableFalse,q=f.findNode,r=a.curry;return{findClosestClientRect:j,findLineNodeRects:l,closestCaret:o}}),g("6z",[],function(){var a=function(a){var b,c,d,e;return e=a.getBoundingClientRect(),b=a.ownerDocument,c=b.documentElement,d=b.defaultView,{top:e.top+d.pageYOffset-c.clientTop,left:e.left+d.pageXOffset-c.clientLeft}},b=function(b){return b.inline?a(b.getBody()):{left:0,top:0}},c=function(a){var b=a.getBody();return a.inline?{left:b.scrollLeft,top:b.scrollTop}:{left:0,top:0}},d=f
unction(a){var b=a.getBody(),c=a.getDoc().documentElement,d={left:b.scrollLeft,top:b.scrollTop},e={left:b.scrollLeft||c.scrollLeft,top:b.scrollTop||c.scrollTop};return a.inline?d:e},e=function(b,c){if(c.target.ownerDocument!==b.getDoc()){var e=a(b.getContentAreaContainer()),f=d(b);return{left:c.pageX-e.left+f.left,top:c.pageY-e.top+f.top}}return{left:c.pageX,top:c.pageY}},f=function(a,b,c){return{pageX:c.left-a.left+b.left,pageY:c.top-a.top+b.top}},g=function(a,d){return f(b(a),c(a),e(a,d))};return{calc:g}}),g("6k",["1j","1g","1r","5","e","6z"],function(a,b,c,d,e,f){var g=a.isContentEditableFalse,h=a.isContentEditableTrue,i=function(a,b){return g(b)&&b!==a},j=function(a,b,c){return b!==c&&!a.dom.isChildOf(b,c)&&!g(b)},k=function(a){var b=a.cloneNode(!0);return b.removeAttribute("data-mce-selected"),b},l=function(a,b,c,d){var e=b.cloneNode(!0);a.dom.setStyles(e,{width:c,height:d}),
a.dom.setAttrib(e,"data-mce-selected",null);var f=a.dom.create("div",{"class":"mce-drag-container","data-mce-bogus":"all",unselectable:"on",contenteditable:"false"});return a.dom.setStyles(f,{position:"absolute",opacity:.5,overflow:"hidden",border:0,padding:0,margin:0,width:c,height:d}),a.dom.setStyles(e,{margin:0,boxSizing:"border-box"}),f.appendChild(e),f},m=function(a,b){a.parentNode!==b&&b.appendChild(a)},n=function(a,b,c,d,e,f){var g=0,h=0;a.style.left=b.pageX+"px",a.style.top=b.pageY+"px",b.pageX+c>e&&(g=b.pageX+c-e),b.pageY+d>f&&(h=b.pageY+d-f),a.style.width=c-g+"px",a.style.height=d-h+"px"},o=function(a){a&&a.parentNode&&a.parentNode.removeChild(a)},p=function(a){return 0===a.button},q=function(a){return a.element},r=function(a,b){return{pageX:b.pageX-a.relX,pageY:b.pageY+5}},s=func
tion(a,d){return function(e){if(p(e)){var f=b.find(d.dom.getParents(e.target),c.or(g,h));if(i(d.getBody(),f)){var j=d.dom.getPos(f),k=d.getBody(),m=d.getDoc().documentElement;a.element=f,a.screenX=e.screenX,a.screenY=e.screenY,a.maxX=(d.inline?k.scrollWidth:m.offsetWidth)-2,a.maxY=(d.inline?k.scrollHeight:m.offsetHeight)-2,a.relX=e.pageX-j.x,a.relY=e.pageY-j.y,a.width=f.offsetWidth,a.height=f.offsetHeight,a.ghost=l(d,f,a.width,a.height)}}}},t=function(a,b){var c=d.throttle(function(a,c){b._selectionOverrides.hideFakeCaret(),b.selection.placeCaretAt(a,c)},0);return function(d){var e=Math.max(Math.abs(d.screenX-a.screenX),Math.abs(d.screenY-a.screenY));if(q(a)&&!a.dragging&&e>10){var g=b.fire("dragstart",{target:a.element});if(g.isDefaultPrevented())return;a.dragging=!0,b.focus()}if(a.dragging){var h=r(a,f.calc(b,d));m(a.ghost,b.getBody()),n(a.ghost,h,a.width,a.height,a.maxX,a.maxY),c(d.clientX,d.clientY)}}},u=function(a){var b=a.getSel().getRangeAt(0),c=b
.startContainer;return 3===c.nodeType?c.parentNode:c},v=function(a,b){return function(c){if(a.dragging&&j(b,u(b.selection),a.element)){var d=k(a.element),e=b.fire("drop",{targetClone:d,clientX:c.clientX,clientY:c.clientY});e.isDefaultPrevented()||(d=e.targetClone,b.undoManager.transact(function(){o(a.element),b.insertContent(b.dom.getOuterHTML(d)),b._selectionOverrides.hideFakeCaret()}))}x(a)}},w=function(a,b){return function(){x(a),a.dragging&&b.fire("dragend")}},x=function(a){a.dragging=!1,a.element=null,o(a.ghost)},y=function(a){var b,c,d,f,g,h,i={};b=e.DOM,h=document,c=s(i,a),d=t(i,a),f=v(i,a),g=w(i,a),a.on("mousedown",c),a.on("mousemove",d),a.on("mouseup",f),b.bind(h,"mousemove",d),b.bind(h,"mouseup",g),a.on("remove",function(){b.unbind(h,"mousemove",d),b.unbind(h,"mouseup",g)})},z=function(a){a.on("drop",function(b){var c="undefined"!=typeof b
.clientX?a.getDoc().elementFromPoint(b.clientX,b.clientY):null;(g(c)||g(a.dom.getContentEditableParent(c)))&&b.preventDefault()})},A=function(a){y(a),z(a)};return{init:A}}),g("5t",["6","44","1n","1k","5l","4v","6h","6i","6j","1j","h","3x","p","1r","1g","5","6k"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q){function r(a,b){for(;b=a(b);)if(b.isVisible())return b;return b}function s(e){function k(a){return e.dom.hasClass(a,"mce-offscreen-selection")}function s(){var a=e.dom.get(da);return a?a.getElementsByTagName("*")[0]:a}function z(a){return e.dom.isBlock(a)}function A(a){a&&e.selection.setRng(a)}function B(){return e.selection.getRng()}function C(a,b){e.selection.scrollIntoView(a,b)}function D(a,b,c){var d;return d=e.fire("ShowCaret",{target:b,direction:a,before
:c}),d.isDefaultPrevented()?null:(C(b,a===-1),ca.show(c,b))}function E(a){var b;return b=e.fire("BeforeObjectSelected",{target:a}),b.isDefaultPrevented()?null:F(a)}function F(a){var b=a.ownerDocument.createRange();return b.selectNode(a),b}function G(a,b){var c=f.isInSameBlock(a,b);return!(c||!j.isBr(a.getNode()))||c}function H(a,b){return b=f.normalizeRange(a,$,b),a==-1?c.fromRangeStart(b):c.fromRangeEnd(b)}function I(a){return d.isCaretContainerBlock(a.startContainer)}function J(a,b,c,d){var e,f,g,h;return!d.collapsed&&(e=y(d),v(e))?D(a,e,a==-1):(h=I(d),f=H(a,d),c(f)?E(f.getNode(a==-1)):(f=b(f))?c(f)?D(a,f.getNode(a==-1),1==a):(g=b(f),c(g)&&G(f,g)?D(a,g.getNode(a==-1),1==a):h?Q(f.toRange()):null):h?d:null)}function K(a,b,c){var d,e,f,g,j,k,l,m,n;if(n=y(c),d=H(a,c),e=b($,h.isAboveLine(1),d),f=o.filter(e,h.isLine(1)),j=o.last(d.getClientRects()),x(d)&&(n=d.getNode()),w(d)&&(n=d.getNode(!0)),!j)return null;if(k=j.left,g=i.findClosestClientRect
(f,k),g&&v(g.node))return l=Math.abs(k-g.left),m=Math.abs(k-g.right),D(a,g.node,l<m);if(n){var p=h.positionsUntil(a,$,h.isAboveLine(1),n);if(g=i.findClosestClientRect(o.filter(p,h.isLine(1)),k))return Q(g.position.toRange());if(g=o.last(o.filter(p,h.isLine(0))))return Q(g.position.toRange())}}function L(b,d){function f(){var b=e.dom.create(e.settings.forced_root_block);return(!a.ie||a.ie>=11)&&(b.innerHTML='<br data-mce-bogus="1">'),b}var g,h,i;if(d.collapsed&&e.settings.forced_root_block){if(g=e.dom.getParent(d.startContainer,"PRE"),!g)return;h=1==b?aa(c.fromRangeStart(d)):ba(c.fromRangeStart(d)),h||(i=f(),1==b?e.$(g).after(i):e.$(g).before(i),e.selection.select(i,!0),e.selection.collapse())}}function M(a,b,c,d){var e;return(e=J(a,b,c,d))?e:(e=L(a,d),e?e:null)}function N(a,b,c){var d;return(d=K(a,b,c))?d:(d=L(a,c),d?d:null)}function O(a){a.hasAttribute("data-mce-caret")&&(d.showCaretContainerBlock(a),A(B()),C
(a[0]))}function P(a){var b,d;return a=f.normalizeRange(1,$,a),b=c.fromRangeStart(a),v(b.getNode())?D(1,b.getNode(),!b.isAtEnd()):v(b.getNode(!0))?D(1,b.getNode(!0),!1):(d=e.dom.getParent(b.getNode(),n.or(v,u)),v(d)?D(1,d,!1):null)}function Q(a){var b;return a&&a.collapsed?(b=P(a),b?b:a):a}function R(){function d(a,b){if(a.isDefaultPrevented()===!1){var c=b(B());c&&(a.preventDefault(),A(c))}}function f(a){for(var b=e.getBody();a&&a!=b;){if(u(a)||v(a))return a;a=a.parentNode}return null}function g(a,b,c){return!c.collapsed&&o.reduce(c.getClientRects(),function(c,d){return c||l.containsXY(d,a,b)},!1)}function j(a){var b=!1;a.on("touchstart",function(){b=!1}),a.on("touchmove",function(){b=!0}),a.on("touchend",function(a){var c=f(a.target);v(c)&&(b||(a.preventDefault(),V(E(c))))})}var n=t(M,1,aa,x),r=t(M,-1,ba,w),y=t(N,-1,h.upUntil),z=t(N,1,h.downUntil);e.on("mouseup",function(){var a=B();a.collapsed&&am
p;A(P(a))}),e.on("click",function(a){var b;b=f(a.target),b&&(v(b)&&(a.preventDefault(),e.focus()),u(b)&&e.dom.isChildOf(b,e.selection.getNode())&&W())}),e.on("blur NewBlock",function(){W(),Y()});var C=function(a){var d=new b(a);if(!a.firstChild)return!1;var e=c.before(a.firstChild),f=d.next(e);return f&&!x(f)&&!w(f)},F=function(a,b){var c=e.dom.getParent(a,e.dom.isBlock),d=e.dom.getParent(b,e.dom.isBlock);return c===d},G=function(a){return!(a.keyCode>=112&&a.keyCode<=123)},H=function(a,b){var c=e.dom.getParent(a,e.dom.isBlock),d=e.dom.getParent(b,e.dom.isBlock);return c&&!F(c,d)&&C(c)};j(e),e.on("mousedown",function(a){var b;if(b=f(a.target))v(b)?(a.preventDefault(),V(E(b))):g(a.clientX,a.clientY,e.selection.getRng())||e.selection.placeCaretAt(a.clientX,a.clientY);else{W(),Y();var c=i.closestCaret($,a.clientX,a.clientY);c&&(H(a.target,c.node)||(a.preventDefault(),e.get
Body().focus(),A(D(1,c.node,c.before))))}}),e.on("keydown",function(a){if(!m.modifierPressed(a))switch(a.keyCode){case m.RIGHT:d(a,n);break;case m.DOWN:d(a,z);break;case m.LEFT:d(a,r);break;case m.UP:d(a,y);break;default:v(e.selection.getNode())&&G(a)&&a.preventDefault()}}),e.on("getSelectionRange",function(a){var b=a.range;if(Z){if(!Z.parentNode)return void(Z=null);b=b.cloneRange(),b.selectNode(Z),a.range=b}}),e.on("setSelectionRange",function(a){var b;b=V(a.range),b&&(a.range=b)}),e.on("AfterSetSelectionRange",function(a){var b=a.range;U(b)||Y(),k(b.startContainer.parentNode)||W()}),e.on("focus",function(){p.setEditorTimeout(e,function(){e.selection.setRng(Q(e.selection.getRng()))},0)}),e.on("copy",function(b){var c=b.clipboardData;if(!b.isDefaultPrevented()&&b.clipboardData&&!a.ie){var d=s();d&&(b.preventDefault(),c.clearData(),c.setData("text/html",d.outerHTML),c
.setData("text/plain",d.outerText))}}),q.init(e)}function S(){var a=e.contentStyles,b=".mce-content-body";a.push(ca.getCss()),a.push(b+" .mce-offscreen-selection {position: absolute;left: -9999999999px;max-width: 1000000px;}"+b+" *[contentEditable=false] {cursor: default;}"+b+" *[contentEditable=true] {cursor: text;}")}function T(a){return d.isCaretContainer(a)||d.startsWithCaretContainer(a)||d.endsWithCaretContainer(a)}function U(a){return T(a.startContainer)||T(a.endContainer)}function V(b){var c,d,f,g,h,i,j,k,l,m,n=e.$,o=e.dom;if(!b)return null;if(b.collapsed){if(!U(b)){if(k=H(1,b),v(k.getNode()))return D(1,k.getNode(),!k.isAtEnd());if(v(k.getNode(!0)))return D(1,k.getNode(!0),!1)}return null}return g=b.startContainer,h=b.startOffset,i=b.endOffset,3==g.nodeType&&0==h&&v(g.parentNode)&&(g=g.parentNode,h=o.nodeIndex(g),g=g.parentNode),1!=g.nodeType?null:(i==h+1&&(c=g.childNodes[h]),v(c)?(l=m=c.cloneNo
de(!0),j=e.fire("ObjectSelected",{target:c,targetClone:l}),j.isDefaultPrevented()?null:(l=j.targetClone,d=n("#"+da),0===d.length&&(d=n('<div data-mce-bogus="all" class="mce-offscreen-selection"></div>').attr("id",da),d.appendTo(e.getBody())),b=e.dom.createRng(),l===m&&a.ie?(d.empty().append('<p style="font-size: 0" data-mce-bogus="all">\xa0</p>').append(l),b.setStartAfter(d[0].firstChild.firstChild),b.setEndAfter(l)):(d.empty().append("\xa0").append(l).append("\xa0"),b.setStart(d[0].firstChild,1),b.setEnd(d[0].lastChild,0)),d.css({top:o.getPos(c,e.getBody()).y}),d[0].focus(),f=e.selection.getSel(),f.removeAllRanges(),f.addRange(b),e.$("*[data-mce-selected]").removeAttr("data-mce-selected"),c.setAttribute("data-mce-selected",1),Z=c,Y(),b)):null)}function W(){Z&&(Z.removeAttribute("data-mce-selected"),e.$(&quo
t;#"+da).remove(),Z=null)}function X(){ca.destroy(),Z=null}function Y(){ca.hide()}var Z,$=e.getBody(),_=new b($),aa=t(r,_.next),ba=t(r,_.prev),ca=new g(e.getBody(),z),da="sel-"+e.dom.uniqueId();return a.ceFalse&&(R(),S()),{showBlockCaretContainer:O,hideFakeCaret:Y,destroy:X}}var t=n.curry,u=j.isContentEditableTrue,v=j.isContentEditableFalse,w=f.isAfterContentEditableFalse,x=f.isBeforeContentEditableFalse,y=k.getSelectedNode;return s}),g("6l",["e"],function(a){function b(b,c,d){for(var e=[];c&&c!=b;c=c.parentNode)e.push(a.nodeIndex(c,d));return e}function c(a,b){var c,d,e;for(d=a,c=b.length-1;c>=0;c--){if(e=d.childNodes,b[c]>e.length-1)return null;d=e[b[c]]}return d}return{create:b,resolve:c}}),g("5u",["p","h","c","6l","i","d","6","9","5","1k","1n","44"],function(a,b,c,d,e,f,g,h,i,j,k,l){return funct
ion(c){function d(a,b){try{c.getDoc().execCommand(a,!1,b)}catch(a){}}function m(){var a=c.getDoc().documentMode;return a?a:6}function n(a){return a.isDefaultPrevented()}function o(a){var b,d;a.dataTransfer&&(c.selection.isCollapsed()&&"IMG"==a.target.tagName&&_.select(a.target),b=c.selection.getContent(),b.length>0&&(d=ga+escape(c.id)+","+escape(b),a.dataTransfer.setData(ha,d)))}function p(a){var b;return a.dataTransfer&&(b=a.dataTransfer.getData(ha),b&&b.indexOf(ga)>=0)?(b=b.substr(ga.length).split(","),{id:unescape(b[0]),html:unescape(b[1])}):null}function q(a,b){c.queryCommandSupported("mceInsertClipboardContent")?c.execCommand("mceInsertClipboardContent",!1,{content:a,internal:b}):c.execCommand("mceInsertContent",!1,a)}function r(){function a(a){var b=$.create("body"),c=a.cloneContents();return b.appendChild(c),_.serializer.serialize(b,{format:"html&qu
ot;})}function d(d){if(!d.setStart){if(d.item)return!1;var e=d.duplicate();return e.moveToElementText(c.getBody()),b.compareRanges(d,e)}var f=a(d),g=$.createRng();g.selectNode(c.getBody());var h=a(g);return f===h}c.on("keydown",function(a){var b,e,f=a.keyCode;if(!n(a)&&(f==Z||f==Y)){if(b=c.selection.isCollapsed(),e=c.getBody(),b&&!$.isEmpty(e))return;if(!b&&!d(c.selection.getRng()))return;a.preventDefault(),c.setContent(""),e.firstChild&&$.isBlock(e.firstChild)?c.selection.setCursorLocation(e.firstChild,0):c.selection.setCursorLocation(e,0),c.nodeChanged()}})}function s(){c.shortcuts.add("meta+a",null,"SelectAll")}function t(){c.settings.content_editable||$.bind(c.getDoc(),"mousedown mouseup",function(a){var b;if(a.target==c.getDoc().documentElement)if(b=_.getRng(),c.getBody().focus(),"mousedown"==a.type){if(j.isCaretContainer(b.startContainer))return;_.placeCaretAt(a.clientX,a.clientY)}else
_.setRng(b)})}function u(){c.on("keydown",function(a){if(!n(a)&&a.keyCode===Y){if(!c.getBody().getElementsByTagName("hr").length)return;if(_.isCollapsed()&&0===_.getRng(!0).startOffset){var b=_.getNode(),d=b.previousSibling;if("HR"==b.nodeName)return $.remove(b),void a.preventDefault();d&&d.nodeName&&"hr"===d.nodeName.toLowerCase()&&($.remove(d),a.preventDefault())}}})}function v(){window.Range.prototype.getClientRects||c.on("mousedown",function(a){if(!n(a)&&"HTML"===a.target.nodeName){var b=c.getBody();b.blur(),i.setEditorTimeout(c,function(){b.focus()})}})}function w(){c.on("click",function(a){var b=a.target;/^(IMG|HR)$/.test(b.nodeName)&&"false"!==$.getContentEditableParent(b)&&(a.preventDefault(),c.selection.select(b),c.nodeChanged()),"A"==b.nodeName&&$.hasClass(b,"mce-item-anchor")&&(a.preventDefault(
),_.select(b))})}function x(){function a(){var a=$.getAttribs(_.getStart().cloneNode(!1));return function(){var b=_.getStart();b!==c.getBody()&&($.setAttrib(b,"style",null),X(a,function(a){b.setAttributeNode(a.cloneNode(!0))}))}}function b(){return!_.isCollapsed()&&$.getParent(_.getStart(),$.isBlock)!=$.getParent(_.getEnd(),$.isBlock)}c.on("keypress",function(d){var e;if(!n(d)&&(8==d.keyCode||46==d.keyCode)&&b())return e=a(),c.getDoc().execCommand("delete",!1,null),e(),d.preventDefault(),!1}),$.bind(c.getDoc(),"cut",function(d){var e;!n(d)&&b()&&(e=a(),i.setEditorTimeout(c,function(){e()}))})}function y(){document.body.setAttribute("role","application")}function z(){c.on("keydown",function(a){if(!n(a)&&a.keyCode===Y&&_.isCollapsed()&&0===_.getRng(!0).startOffset){var b=_.getNode().previousSibling;if(b&&b.nodeName&&"table&q
uot;===b.nodeName.toLowerCase())return a.preventDefault(),!1}})}function A(){m()>7||(d("RespectVisibilityInDesign",!0),c.contentStyles.push(".mceHideBrInPre pre br {display: none}"),$.addClass(c.getBody(),"mceHideBrInPre"),ba.addNodeFilter("pre",function(a){for(var b,c,d,f,g=a.length;g--;)for(b=a[g].getAll("br"),c=b.length;c--;)d=b[c],f=d.prev,f&&3===f.type&&"\n"!=f.value.charAt(f.value-1)?f.value+="\n":d.parent.insert(new e("#text",3),d,!0).value="\n"}),ca.addNodeFilter("pre",function(a){for(var b,c,d,e,f=a.length;f--;)for(b=a[f].getAll("br"),c=b.length;c--;)d=b[c],e=d.prev,e&&3==e.type&&(e.value=e.value.replace(/\r?\n$/,""))}))}function B(){$.bind(c.getBody(),"mouseup",function(){var a,b=_.getNode();"IMG"==b.nodeName&&((a=$.getStyle(b,"width"))&&($.setAttrib(b,"width",a.rep
lace(/[^0-9%]+/g,"")),$.setStyle(b,"width","")),(a=$.getStyle(b,"height"))&&($.setAttrib(b,"height",a.replace(/[^0-9%]+/g,"")),$.setStyle(b,"height","")))})}function C(){c.on("keydown",function(b){var d,e,f,g,h;if(!n(b)&&b.keyCode==a.BACKSPACE&&(d=_.getRng(),e=d.startContainer,f=d.startOffset,g=$.getRoot(),h=e,d.collapsed&&0===f)){for(;h&&h.parentNode&&h.parentNode.firstChild==h&&h.parentNode!=g;)h=h.parentNode;"BLOCKQUOTE"===h.tagName&&(c.formatter.toggle("blockquote",null,h),d=$.createRng(),d.setStart(e,0),d.setEnd(e,0),_.setRng(d))}})}function D(){function a(){U(),d("StyleWithCSS",!1),d("enableInlineTableEditing",!1),aa.object_resizing||d("enableObjectResizing",!1)}aa.readonly||c.on("BeforeExecCommand MouseDown",a)}function E(){function a(){X($.select("a"),fun
ction(a){var b=a.parentNode,c=$.getRoot();if(b.lastChild===a){for(;b&&!$.isBlock(b);){if(b.parentNode.lastChild!==b||b===c)return;b=b.parentNode}$.add(b,"br",{"data-mce-bogus":1})}})}c.on("SetContent ExecCommand",function(b){"setcontent"!=b.type&&"mceInsertLink"!==b.command||a()})}function F(){aa.forced_root_block&&c.on("init",function(){d("DefaultParagraphSeparator",aa.forced_root_block)})}function G(){c.on("keydown",function(a){var b;n(a)||a.keyCode!=Y||(b=c.getDoc().selection.createRange(),b&&b.item&&(a.preventDefault(),c.undoManager.beforeChange(),$.remove(b.item(0)),c.undoManager.add()))})}function H(){var a;m()>=10&&(a="",X("p div h1 h2 h3 h4 h5 h6".split(" "),function(b,c){a+=(c>0?",":"")+b+":empty"}),c.contentStyles.push(a+"{padding-right: 1px !important}"))}function I(){m()
<9&&(ba.addNodeFilter("noscript",function(a){for(var b,c,d=a.length;d--;)b=a[d],c=b.firstChild,c&&b.attr("data-mce-innertext",c.value)}),ca.addNodeFilter("noscript",function(a){for(var b,c,d,g=a.length;g--;)b=a[g],c=a[g].firstChild,c?c.value=f.decode(c.value):(d=b.attributes.map["data-mce-innertext"],d&&(b.attr("data-mce-innertext",null),c=new e("#text",3),c.value=d,c.raw=!0,b.append(c)))}))}function J(){function a(a,b){var c=h.createTextRange();try{c.moveToPoint(a,b)}catch(a){c=null}return c}function b(b){var d;b.button?(d=a(b.x,b.y),d&&(d.compareEndPoints("StartToStart",e)>0?d.setEndPoint("StartToStart",e):d.setEndPoint("EndToEnd",e),d.select())):c()}function c(){var a=g.selection.createRange();e&&!a.item&&0===a.compareEndPoints("StartToEnd",a)&&e.select(),$.unbind(g,"mouseup",c),$.unbind(g,"mousemove"
,b),e=d=0}var d,e,f,g=$.doc,h=g.body;g.documentElement.unselectable=!0,$.bind(g,"mousedown contextmenu",function(h){if("HTML"===h.target.nodeName){if(d&&c(),f=g.documentElement,f.scrollHeight>f.clientHeight)return;d=1,e=a(h.x,h.y),e&&($.bind(g,"mouseup",c),$.bind(g,"mousemove",b),$.getRoot().focus(),e.select())}})}function K(){c.on("keyup focusin mouseup",function(b){65==b.keyCode&&a.metaKeyPressed(b)||_.normalize()},!0)}function L(){c.contentStyles.push("img:-moz-broken {-moz-force-broken-image-icon:1;min-width:24px;min-height:24px}")}function M(){c.inline||c.on("keydown",function(){document.activeElement==document.body&&c.getWin().focus()})}function N(){c.inline||(c.contentStyles.push("body {min-height: 150px}"),c.on("click",function(a){var b;if("HTML"==a.target.nodeName){if(g.ie>11)return void c.getBody().focus();b=c.selection.getRng(),c.getBod
y().focus(),c.selection.setRng(b),c.selection.normalize(),c.nodeChanged()}}))}function O(){g.mac&&c.on("keydown",function(b){!a.metaKeyPressed(b)||b.shiftKey||37!=b.keyCode&&39!=b.keyCode||(b.preventDefault(),c.selection.getSel().modify("move",37==b.keyCode?"backward":"forward","lineboundary"))})}function P(){d("AutoUrlDetect",!1)}function Q(){c.on("click",function(a){var b=a.target;do if("A"===b.tagName)return void a.preventDefault();while(b=b.parentNode)}),c.contentStyles.push(".mce-content-body {-webkit-touch-callout: none}")}function R(){c.on("init",function(){c.dom.bind(c.getBody(),"submit",function(a){a.preventDefault()})})}function S(){ba.addNodeFilter("br",function(a){for(var b=a.length;b--;)"Apple-interchange-newline"==a[b].attr("class")&&a[b].remove()})}function T(){c.on("dragstart",function(a){o(a)}),
c.on("drop",function(a){if(!n(a)){var d=p(a);if(d&&d.id!=c.id){a.preventDefault();var e=b.getCaretRangeFromPoint(a.x,a.y,c.getDoc());_.setRng(e),q(d.html,!0)}}})}function U(){}function V(){var a;return da?(a=c.selection.getSel(),!a||!a.rangeCount||0===a.rangeCount):0}function W(){function b(a){var b=new l(a.getBody()),c=a.selection.getRng(),d=k.fromRangeStart(c),e=k.fromRangeEnd(c),f=b.prev(d),g=b.next(e);return!a.selection.isCollapsed()&&(!f||f.isAtStart()&&d.isEqual(f))&&(!g||g.isAtEnd()&&d.isEqual(g))}c.on("keypress",function(d){!n(d)&&!_.isCollapsed()&&d.charCode>31&&!a.metaKeyPressed(d)&&b(c)&&(d.preventDefault(),c.setContent(String.fromCharCode(d.charCode)),c.selection.select(c.getBody(),!0),c.selection.collapse(!1),c.nodeChanged())}),c.on("keydown",function(a){var d=a.keyCode;n(a)||d!=Z&&d!=Y||b(c)&&(a.preventDefault(),c.setContent(""),c.n
odeChanged())})}var X=h.each,Y=a.BACKSPACE,Z=a.DELETE,$=c.dom,_=c.selection,aa=c.settings,ba=c.parser,ca=c.serializer,da=g.gecko,ea=g.ie,fa=g.webkit,ga="data:text/mce-internal,",ha=ea?"Text":"URL";return C(),r(),g.windowsPhone||K(),fa&&(W(),t(),w(),F(),R(),z(),S(),g.iOS?(M(),N(),Q()):s()),ea&&g.ie<11&&(u(),y(),A(),B(),G(),H(),I(),J()),g.ie>=11&&(N(),z()),g.ie&&(s(),P(),T()),da&&(W(),u(),v(),x(),D(),E(),L(),O(),z()),{refreshContentEditable:U,isHidden:V}}}),g("54",["1x","4b","5o","e","s","o","5p","25","5q","t","l","i","j","5r","5s","5t","u","5","5u","9"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t){var u=d.DOM,v=function(a){var b=new k(a.settings,a.schema);return b.addAttributeFilter("s
rc,href,style,tabindex",function(b,c){for(var d,e,f,g=b.length,h=a.dom;g--;)if(d=b[g],e=d.attr(c),f="data-mce-"+c,!d.attributes.map[f]){if(0===e.indexOf("data:")||0===e.indexOf("blob:"))continue;"style"===c?(e=h.serializeStyle(h.parseStyle(e),d.name),e.length||(e=null),d.attr(f,e),d.attr(c,e)):"tabindex"===c?(d.attr(f,e),d.attr(c,null)):d.attr(f,a.convertURL(e,c,d.name))}}),b.addNodeFilter("script",function(a){for(var b,c,d=a.length;d--;)b=a[d],c=b.attr("type")||"no/type",0!==c.indexOf("mce-")&&b.attr("type","mce-"+c)}),b.addNodeFilter("#cdata",function(a){for(var b,c=a.length;c--;)b=a[c],b.type=8,b.name="#comment",b.value="[CDATA["+b.value+"]]"}),b.addNodeFilter("p,h1,h2,h3,h4,h5,h6,div",function(b){for(var c,d=b.length,e=a.schema.getNonEmptyElements();d--;)c=b[d],c.isEmpty(e)&&0===c.getAll("br"
;).length&&(c.append(new l("br",1)).shortEnded=!0)}),b},w=function(a){a.settings.auto_focus&&r.setEditorTimeout(a,function(){var b;b=a.settings.auto_focus===!0?a:a.editorManager.get(a.settings.auto_focus),b.destroyed||b.focus()},100)},x=function(a){a.bindPendingEventDelegates(),a.initialized=!0,a.fire("init"),a.focus(!0),a.nodeChanged({initial:!0}),a.execCallback("init_instance_callback",a),w(a)},y=function(k,l){var r,w,y=k.settings,z=k.getElement(),A=k.getDoc();y.inline||(k.getElement().style.visibility=k.orgVisibility),l||y.content_editable||(A.open(),A.write(k.iframeHTML),A.close()),y.content_editable&&(k.on("remove",function(){var a=this.getBody();u.removeClass(a,"mce-content-body"),u.removeClass(a,"mce-edit-focus"),u.setAttrib(a,"contentEditable",null)}),u.addClass(z,"mce-content-body"),k.contentDocument=A=y.content_document||a,k.contentWindow=y.content_window||b,k.bodyElemen
t=z,y.content_document=y.content_window=null,y.root_name=z.nodeName.toLowerCase()),r=k.getBody(),r.disabled=!0,k.readonly=y.readonly,k.readonly||(k.inline&&"static"===u.getStyle(r,"position",!0)&&(r.style.position="relative"),r.contentEditable=k.getParam("content_editable_state",!0)),r.disabled=!1,k.editorUpload=new g(k),k.schema=new m(y),k.dom=new d(A,{keep_values:!0,url_converter:k.convertURL,url_converter_scope:k,hex_colors:y.force_hex_style_colors,class_filter:y.class_filter,
+update_styles:!0,root_element:k.inline?k.getBody():null,collect:y.content_editable,schema:k.schema,onSetAttrib:function(a){k.fire("SetAttrib",a)}}),k.parser=v(k),k.serializer=new f(y,k),k.selection=new e(k.dom,k.getWin(),k.serializer,k),k.formatter=new j(k),k.undoManager=new q(k),k._nodeChangeDispatcher=new o(k),k._selectionOverrides=new p(k),c.setup(k),n.setup(k),i.setup(k),k.fire("PreInit"),y.browser_spellcheck||y.gecko_spellcheck||(A.body.spellcheck=!1,u.setAttrib(r,"spellcheck","false")),k.quirks=new s(k),k.fire("PostRender"),y.directionality&&(r.dir=y.directionality),y.nowrap&&(r.style.whiteSpace="nowrap"),y.protect&&k.on("BeforeSetContent",function(a){t.each(y.protect,function(b){a.content=a.content.replace(b,function(a){return"<!--mce:protected "+escape(a)+"-->"})})}),k.on("SetContent",function(){k.addVisual(k.getBody())}),y.padd_empty_editor&&
amp;k.on("PostProcess",function(a){a.content=a.content.replace(/^(<p[^>]*>( | |\s|\u00a0|<br \/>|)<\/p>[\r\n]*|<br \/>[\r\n]*)$/,"")}),k.load({initial:!0,format:"html"}),k.startContent=k.getContent({format:"raw"}),k.on("compositionstart compositionend",function(a){k.composing="compositionstart"===a.type}),k.contentStyles.length>0&&(w="",t.each(k.contentStyles,function(a){w+=a+"\r\n"}),k.dom.addStyle(w)),k.dom.styleSheetLoader.loadAll(k.contentCSS,function(a){x(k)},function(a){x(k),h.contentCssError(k,a)})};return{initContentBody:y}}),g("4d",["g"],function(a){return a.PluginManager}),g("4e",["g"],function(a){return a.ThemeManager}),g("4c",["1x","4b","e","6","54","4d","4e","9","24"],function(a,b,c,d,e,f,g,h,i){var
j=c.DOM,k=function(a,b,c){var d,e,g=f.get(c);if(d=f.urls[c]||a.documentBaseUrl.replace(/\/$/,""),c=h.trim(c),g&&h.inArray(b,c)===-1){if(h.each(f.dependencies(c),function(c){k(a,b,c)}),a.plugins[c])return;e=new g(a,d,a.$),a.plugins[c]=e,e.init&&(e.init(a,d),b.push(c))}},l=function(a){var b=[];h.each(a.settings.plugins.replace(/\-/g,"").split(/[ ,]/),function(c){k(a,b,c)})},m=function(a){var b,c=a.settings;c.theme&&("function"!=typeof c.theme?(c.theme=c.theme.replace(/-/,""),b=g.get(c.theme),a.theme=new b(a,g.urls[c.theme]),a.theme.init&&a.theme.init(a,g.urls[c.theme]||a.documentBaseUrl.replace(/\/$/,""),a.$)):a.theme=c.theme)},n=function(a){var b,c,d,e,f,g=a.settings,h=a.getElement();return g.render_ui&&a.theme&&(a.orgDisplay=h.style.display,"function"!=typeof g.theme?(b=g.width||j.getStyle(h,"width")||"100%",c=g.height||j.getStyle(h,"height")||h.
offsetHeight,d=g.min_height||100,e=/^[0-9\.]+(|px)$/i,e.test(""+b)&&(b=Math.max(parseInt(b,10),100)),e.test(""+c)&&(c=Math.max(parseInt(c,10),d)),f=a.theme.renderUI({targetNode:h,width:b,height:c,deltaWidth:g.delta_width,deltaHeight:g.delta_height}),g.content_editable||(c=(f.iframeHeight||c)+("number"==typeof c?f.deltaHeight||0:""),c<d&&(c=d))):(f=g.theme(a,h),f.editorContainer.nodeType&&(f.editorContainer.id=f.editorContainer.id||a.id+"_parent"),f.iframeContainer.nodeType&&(f.iframeContainer.id=f.iframeContainer.id||a.id+"_iframecontainer"),c=f.iframeHeight||h.offsetHeight),a.editorContainer=f.editorContainer,f.height=c),f},o=function(c,f){var g,h,k,l=c.settings;c.iframeHTML=l.doctype+"<html><head>",l.document_base_url!=c.documentBaseUrl&&(c.iframeHTML+='<base href="'+c.documentBaseURI.getURI()+'" />'),!d.caretAfter&&l.ie7_comp
at&&(c.iframeHTML+='<meta http-equiv="X-UA-Compatible" content="IE=7" />'),c.iframeHTML+='<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />',g=l.body_id||"tinymce",g.indexOf("=")!=-1&&(g=c.getParam("body_id","","hash"),g=g[c.id]||g),h=l.body_class||"",h.indexOf("=")!=-1&&(h=c.getParam("body_class","","hash"),h=h[c.id]||""),l.content_security_policy&&(c.iframeHTML+='<meta http-equiv="Content-Security-Policy" content="'+l.content_security_policy+'" />'),c.iframeHTML+='</head><body id="'+g+'" class="mce-content-body '+h+'" data-id="'+c.id+'"><br></body></html>';var m=i.uuid("mce");c[m]=function(){e.initContentBody(c)};var n='javascript:(function(){document.open();document.domain=&q
uot;'+a.domain+'";var ed = window.parent.tinymce.get("'+c.id+'");document.write(ed.iframeHTML);document.close();ed.'+m+"(true);})()";a.domain!=b.location.hostname&&d.ie&&d.ie<12&&(k=n);var o=j.create("iframe",{id:c.id+"_ifr",frameBorder:"0",allowTransparency:"true",title:c.editorManager.translate("Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help"),style:{width:"100%",height:f.height,display:"block"}});if(o.onload=function(){o.onload=null,c.fire("load")},j.setAttrib(o,"src",k||'javascript:""'),c.contentAreaContainer=f.iframeContainer,c.iframeElement=o,j.add(f.iframeContainer,o),d.ie)try{c.getDoc()}catch(a){o.src=k=n}return k},p=function(a){var b,c,d=a.settings,f=a.getElement();return a.rtl=d.rtl_ui||a.editorManager.i18n.rtl,a.editorManager.i18n.setCode(d.language),d.aria_label=d.aria_label||j.getA
ttrib(f,"aria-label",a.getLang("aria.rich_text_area")),a.fire("ScriptsLoaded"),m(a),l(a),b=n(a),d.content_css&&h.each(h.explode(d.content_css),function(b){a.contentCSS.push(a.documentBaseURI.toAbsolute(b))}),d.content_style&&a.contentStyles.push(d.content_style),d.content_editable?e.initContentBody(a):(c=o(a,b),b.editorContainer&&(j.get(b.editorContainer).style.display=a.orgDisplay,a.hidden=j.isHidden(b.editorContainer)),a.getElement().style.display="none",j.setAttrib(a.id,"aria-hidden",!0),void(c||e.initContentBody(a)))};return{init:p}}),g("21",["4b","e","7","f","6","25","4c","11","4d","4e","9","10"],function(a,b,c,d,e,f,g,h,i,j,k,l){var m=b.DOM,n=function(a,b){var c=a.settings,e=d.ScriptLoader;if(c.language&&"en"!=c.language&&!c.language_url&&(c.l
anguage_url=a.editorManager.baseURL+"/langs/"+c.language+".js"),c.language_url&&e.add(c.language_url),c.theme&&"function"!=typeof c.theme&&"-"!=c.theme.charAt(0)&&!j.urls[c.theme]){var h=c.theme_url;h=h?a.documentBaseURI.toAbsolute(h):"themes/"+c.theme+"/theme"+b+".js",j.load(c.theme,h)}k.isArray(c.plugins)&&(c.plugins=c.plugins.join(" ")),k.each(c.external_plugins,function(a,b){i.load(b,a),c.plugins+=" "+b}),k.each(c.plugins.split(/[ ,]/),function(a){if(a=k.trim(a),a&&!i.urls[a])if("-"===a.charAt(0)){a=a.substr(1,a.length);var c=i.dependencies(a);k.each(c,function(a){var c={prefix:"plugins/",resource:a,suffix:"/plugin"+b+".js"};a=i.createUrl(c,a),i.load(a.resource,a)})}else i.load(a,{prefix:"plugins/",resource:a,suffix:"/plugin"+b+".js"})}),e.loadQueue(function(){a.removed||g.i
nit(a)},a,function(b){f.pluginLoadError(a,b[0]),a.removed||g.init(a)})},o=function(b){function d(){m.unbind(a,"ready",d),b.render()}var f=b.settings,g=b.id;if(!c.Event.domLoaded)return void m.bind(a,"ready",d);if(b.getElement()&&e.contentEditable){f.inline?b.inline=!0:(b.orgVisibility=b.getElement().style.visibility,b.getElement().style.visibility="hidden");var i=b.getElement().form||m.getParent(g,"form");i&&(b.formElement=i,f.hidden_input&&!/TEXTAREA|INPUT/i.test(b.getElement().nodeName)&&(m.insertAfter(m.create("input",{type:"hidden",name:g}),g),b.hasHiddenInput=!0),b.formEventDelegate=function(a){b.fire(a.type,a)},m.bind(i,"submit reset",b.formEventDelegate),b.on("reset",function(){b.setContent(b.startContent,{format:"raw"})}),!f.submit_patch||i.submit.nodeType||i.submit.length||i._mceOldSubmit||(i._mceOldSubmit=i.submit,i.submit=function(){return b.editorMana
ger.triggerSave(),b.setDirty(!1),i._mceOldSubmit(i)})),b.windowManager=new l(b),b.notificationManager=new h(b),"xml"===f.encoding&&b.on("GetContent",function(a){a.save&&(a.content=m.encode(a.content))}),f.add_form_submit_trigger&&b.on("submit",function(){b.initialized&&b.save()}),f.add_unload_trigger&&(b._beforeUnload=function(){!b.initialized||b.destroyed||b.isHidden()||b.save({format:"raw",no_events:!0,set_dirty:!1})},b.editorManager.on("BeforeUnload",b._beforeUnload)),b.editorManager.add(b),n(b,b.suffix)}};return{render:o}}),g("22",[],function(){function a(a,b,c){try{a.getDoc().execCommand(b,!1,c)}catch(a){}}function b(a){var b,c;return b=a.getBody(),c=function(b){a.dom.getParents(b.target,"a").length>0&&b.preventDefault()},a.dom.bind(b,"click",c),{unbind:function(){a.dom.unbind(b,"click",c)}}}function c(c,d){c._clickBlocker&&(c._cli
ckBlocker.unbind(),c._clickBlocker=null),d?(c._clickBlocker=b(c),c.selection.controlSelection.hideResizeRect(),c.readonly=!0,c.getBody().contentEditable=!1):(c.readonly=!1,c.getBody().contentEditable=!0,a(c,"StyleWithCSS",!1),a(c,"enableInlineTableEditing",!1),a(c,"enableObjectResizing",!1),c.focus(),c.nodeChanged())}function d(a,b){var d=a.readonly?"readonly":"design";b!=d&&(a.initialized?c(a,"readonly"==b):a.on("init",function(){c(a,"readonly"==b)}),a.fire("SwitchMode",{mode:b}))}return{setMode:d}});g("23",[],function(){var a=function(a,b,c){var d=a.sidebars?a.sidebars:[];d.push({name:b,settings:c}),a.sidebars=d};return{add:a}});g("14",["g","a","e","v","12","6","n","21","22","13","23","9","w","24"],function(a,b,c,d,e,f,g,h,i,j,
k,l,m,n){function o(c,e,g){var h,i,k,l=this;h=l.documentBaseUrl=g.documentBaseURL,i=g.baseURI,k=g.defaultSettings,e=q({id:c,theme:"modern",delta_width:0,delta_height:0,popup_css:"",plugins:"",document_base_url:h,add_form_submit_trigger:!0,submit_patch:!0,add_unload_trigger:!0,convert_urls:!0,relative_urls:!0,remove_script_host:!0,object_resizing:!0,doctype:"<!DOCTYPE html>",visual:!0,font_size_style_values:"xx-small,x-small,small,medium,large,x-large,xx-large",font_size_legacy_values:"xx-small,small,medium,large,x-large,xx-large,300%",forced_root_block:"p",hidden_input:!0,padd_empty_editor:!0,render_ui:!0,indentation:"30px",inline_styles:!0,convert_fonts_to_spans:!0,indent:"simple",indent_before:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,figcaption,option,optgroup,datalist"
;,indent_after:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,figcaption,option,optgroup,datalist",validate:!0,entity_encoding:"named",url_converter:l.convertURL,url_converter_scope:l,ie7_compat:!0},k,e),k&&k.external_plugins&&e.external_plugins&&(e.external_plugins=q({},k.external_plugins,e.external_plugins)),l.settings=e,a.language=e.language||"en",a.languageLoad=e.language_load,a.baseURL=g.baseURL,l.id=e.id=c,l.setDirty(!1),l.plugins={},l.documentBaseURI=new m(e.document_base_url||h,{base_uri:i}),l.baseURI=i,l.contentCSS=[],l.contentStyles=[],l.shortcuts=new j(l),l.loadedCSS={},l.editorCommands=new d(l),l.suffix=g.suffix,l.editorManager=g,l.inline=e.inline,l.settings.content_editable=l.inline,e.cache_suffix&&(f.cacheSuffix=e.cache_suffix.replace(/^[\?\&]+/,"")),e.override_viewport===!1&&(f.overr
ideViewPort=!1),g.fire("SetupEditor",l),l.execCallback("setup",l),l.$=b.overrideDefaults(function(){return{context:l.inline?l.getBody():l.getDoc(),element:l.getBody()}})}var p=c.DOM,q=l.extend,r=l.each,s=l.trim,t=l.resolve,u=f.gecko,v=f.ie;return o.prototype={render:function(){h.render(this)},focus:function(a){function b(a){return g.dom.getParent(a,function(a){return"true"===g.dom.getContentEditable(a)})}var c,d,e,g=this,h=g.selection,i=g.settings.content_editable,j=g.getDoc(),k=g.getBody();if(!a){if(c=h.getRng(),c.item&&(d=c.item(0)),g.quirks.refreshContentEditable(),e=b(h.getNode()),g.$.contains(k,e))return e.focus(),h.normalize(),void g.editorManager.setActive(g);if(i||(f.opera||g.getBody().focus(),g.getWin().focus()),u||i){if(k.setActive)try{k.setActive()}catch(a){k.focus()}else k.focus();i&&h.normalize()}d&&d.ownerDocument==j&&(c=j.body.createControlRange(),c.addElement(d),c.select())}g.editorManager.setActive(g)},ex
ecCallback:function(a){var b,c=this,d=c.settings[a];if(d)return c.callbackLookup&&(b=c.callbackLookup[a])&&(d=b.func,b=b.scope),"string"==typeof d&&(b=d.replace(/\.\w+$/,""),b=b?t(b):0,d=t(d),c.callbackLookup=c.callbackLookup||{},c.callbackLookup[a]={func:d,scope:b}),d.apply(b||c,Array.prototype.slice.call(arguments,1))},translate:function(a){var b=this.settings.language||"en",c=this.editorManager.i18n;return a?(a=c.data[b+"."+a]||a.replace(/\{\#([^\}]+)\}/g,function(a,d){return c.data[b+"."+d]||"{#"+d+"}"}),this.editorManager.translate(a)):""},getLang:function(a,b){return this.editorManager.i18n.data[(this.settings.language||"en")+"."+a]||(void 0!==b?b:"{#"+a+"}")},getParam:function(a,b,c){var d,e=a in this.settings?this.settings[a]:b;return"hash"===c?(d={},"string"==typeof e?r(e.indexOf("=")>0?e.split(/[;,]
(?![^=;,]*(?:[;,]|$))/):e.split(","),function(a){a=a.split("="),a.length>1?d[s(a[0])]=s(a[1]):d[s(a[0])]=s(a)}):d=e,d):e},nodeChanged:function(a){this._nodeChangeDispatcher.nodeChanged(a)},addButton:function(a,b){var c=this;b.cmd&&(b.onclick=function(){c.execCommand(b.cmd)}),b.text||b.icon||(b.icon=a),c.buttons=c.buttons||{},b.tooltip=b.tooltip||b.title,c.buttons[a]=b},addSidebar:function(a,b){return k.add(this,a,b)},addMenuItem:function(a,b){var c=this;b.cmd&&(b.onclick=function(){c.execCommand(b.cmd)}),c.menuItems=c.menuItems||{},c.menuItems[a]=b},addContextToolbar:function(a,b){var c,d=this;d.contextToolbars=d.contextToolbars||[],"string"==typeof a&&(c=a,a=function(a){return d.dom.is(a,c)}),d.contextToolbars.push({id:n.uuid("mcet"),predicate:a,items:b})},addCommand:function(a,b,c){this.editorCommands.addCommand(a,b,c)},addQueryStateHandler:function(a,b,c){this.editorCommands.addQueryStateHandler(a,b,c)},addQueryVa
lueHandler:function(a,b,c){this.editorCommands.addQueryValueHandler(a,b,c)},addShortcut:function(a,b,c,d){this.shortcuts.add(a,b,c,d)},execCommand:function(a,b,c,d){return this.editorCommands.execCommand(a,b,c,d)},queryCommandState:function(a){return this.editorCommands.queryCommandState(a)},queryCommandValue:function(a){return this.editorCommands.queryCommandValue(a)},queryCommandSupported:function(a){return this.editorCommands.queryCommandSupported(a)},show:function(){var a=this;a.hidden&&(a.hidden=!1,a.inline?a.getBody().contentEditable=!0:(p.show(a.getContainer()),p.hide(a.id)),a.load(),a.fire("show"))},hide:function(){var a=this,b=a.getDoc();a.hidden||(v&&b&&!a.inline&&b.execCommand("SelectAll"),a.save(),a.inline?(a.getBody().contentEditable=!1,a==a.editorManager.focusedEditor&&(a.editorManager.focusedEditor=null)):(p.hide(a.getContainer()),p.setStyle(a.id,"display",a.orgDisplay)),a.hidden=!0,a.fire("hid
e"))},isHidden:function(){return!!this.hidden},setProgressState:function(a,b){this.fire("ProgressState",{state:a,time:b})},load:function(a){var b,c=this,d=c.getElement();if(d)return a=a||{},a.load=!0,b=c.setContent(void 0!==d.value?d.value:d.innerHTML,a),a.element=d,a.no_events||c.fire("LoadContent",a),a.element=d=null,b},save:function(a){var b,c,d=this,e=d.getElement();if(e&&d.initialized)return a=a||{},a.save=!0,a.element=e,b=a.content=d.getContent(a),a.no_events||d.fire("SaveContent",a),"raw"==a.format&&d.fire("RawSaveContent",a),b=a.content,/TEXTAREA|INPUT/i.test(e.nodeName)?e.value=b:(d.inline||(e.innerHTML=b),(c=p.getParent(d.id,"form"))&&r(c.elements,function(a){if(a.name==d.id)return a.value=b,!1})),a.element=e=null,a.set_dirty!==!1&&d.setDirty(!1),b},setContent:function(a,b){var c,d,e=this,f=e.getBody();return b=b||{},b.format=b.format||"html",b.set=!0,b.content=a,b.no
_events||e.fire("BeforeSetContent",b),a=b.content,0===a.length||/^\s+$/.test(a)?(d=v&&v<11?"":'<br data-mce-bogus="1">',"TABLE"==f.nodeName?a="<tr><td>"+d+"</td></tr>":/^(UL|OL)$/.test(f.nodeName)&&(a="<li>"+d+"</li>"),c=e.settings.forced_root_block,c&&e.schema.isValidChild(f.nodeName.toLowerCase(),c.toLowerCase())?(a=d,a=e.dom.createHTML(c,e.settings.forced_root_block_attrs,a)):v||a||(a='<br data-mce-bogus="1">'),e.dom.setHTML(f,a),e.fire("SetContent",b)):("raw"!==b.format&&(a=new g({validate:e.validate},e.schema).serialize(e.parser.parse(a,{isRootContent:!0}))),b.content=s(a),e.dom.setHTML(f,b.content),b.no_events||e.fire("SetContent",b)),b.content},getContent:function(a){var b,c=this,d=c.getBody();return a=a||{},a.format=a.format||"html",a.get=!0,a.getInner=!0,a.no_event
s||c.fire("BeforeGetContent",a),b="raw"==a.format?l.trim(c.serializer.getTrimmedContent()):"text"==a.format?d.innerText||d.textContent:c.serializer.serialize(d,a),"text"!=a.format?a.content=s(b):a.content=b,a.no_events||c.fire("GetContent",a),a.content},insertContent:function(a,b){b&&(a=q({content:a},b)),this.execCommand("mceInsertContent",!1,a)},isDirty:function(){return!this.isNotDirty},setDirty:function(a){var b=!this.isNotDirty;this.isNotDirty=!a,a&&a!=b&&this.fire("dirty")},setMode:function(a){i.setMode(this,a)},getContainer:function(){var a=this;return a.container||(a.container=p.get(a.editorContainer||a.id+"_parent")),a.container},getContentAreaContainer:function(){return this.contentAreaContainer},getElement:function(){return this.targetElm||(this.targetElm=p.get(this.id)),this.targetElm},getWin:function(){var a,b=this;return b.contentWindow||(a=b.iframeElement,a&&
(b.contentWindow=a.contentWindow)),b.contentWindow},getDoc:function(){var a,b=this;return b.contentDocument||(a=b.getWin(),a&&(b.contentDocument=a.document)),b.contentDocument},getBody:function(){var a=this.getDoc();return this.bodyElement||(a?a.body:null)},convertURL:function(a,b,c){var d=this,e=d.settings;return e.urlconverter_callback?d.execCallback("urlconverter_callback",a,c,!0,b):!e.convert_urls||c&&"LINK"==c.nodeName||0===a.indexOf("file:")||0===a.length?a:e.relative_urls?d.documentBaseURI.toRelative(a):a=d.documentBaseURI.toAbsolute(a,e.remove_script_host)},addVisual:function(a){var b,c=this,d=c.settings,e=c.dom;a=a||c.getBody(),void 0===c.hasVisual&&(c.hasVisual=d.visual),r(e.select("table,a",a),function(a){var f;switch(a.nodeName){case"TABLE":return b=d.visual_table_class||"mce-item-table",f=e.getAttrib(a,"border"),void(f&&"0"!=f||!c.hasVisual?e.removeClass(a,b):
e.addClass(a,b));case"A":return void(e.getAttrib(a,"href",!1)||(f=e.getAttrib(a,"name")||a.id,b=d.visual_anchor_class||"mce-item-anchor",f&&c.hasVisual?e.addClass(a,b):e.removeClass(a,b)))}}),c.fire("VisualAid",{element:a,hasVisual:c.hasVisual})},remove:function(){var a=this;a.removed||(a.save(),a.removed=1,a.unbindAllNativeEvents(),a.hasHiddenInput&&p.remove(a.getElement().nextSibling),a.inline||(v&&v<10&&a.getDoc().execCommand("SelectAll",!1,null),p.setStyle(a.id,"display",a.orgDisplay),a.getBody().onload=null),a.fire("remove"),a.editorManager.remove(a),p.remove(a.getContainer()),a._selectionOverrides.destroy(),a.editorUpload.destroy(),a.destroy())},destroy:function(a){var b,c=this;if(!c.destroyed){if(!a&&!c.removed)return void c.remove();a||(c.editorManager.off("beforeunload",c._beforeUnload),c.theme&&c.theme.destroy&&c.theme.destroy
(),c.selection.destroy(),c.dom.destroy()),b=c.formElement,b&&(b._mceOldSubmit&&(b.submit=b._mceOldSubmit,b._mceOldSubmit=null),p.unbind(b,"submit reset",c.formEventDelegate)),c.contentAreaContainer=c.formElement=c.container=c.editorContainer=null,c.bodyElement=c.contentDocument=c.contentWindow=null,c.iframeElement=c.targetElm=null,c.selection&&(c.selection=c.selection.win=c.selection.dom=c.selection.dom.doc=null),c.destroyed=1}},uploadImages:function(a){return this.editorUpload.uploadImages(a)},_scanForImages:function(){return this.editorUpload.scanForImages()}},q(o.prototype,e),o}),g("15",["9"],function(a){"use strict";var b={},c="en";return{setCode:function(a){a&&(c=a,this.rtl=!!this.data[a]&&"rtl"===this.data[a]._dir)},getCode:function(){return c},rtl:!1,add:function(a,c){var d=b[a];d||(b[a]=d={});for(var e in c)d[e]=c[e];this.setCode(a)},translate:function(d){function e(b){return
a.is(b,"function")?Object.prototype.toString.call(b):f(b)?"":""+b}function f(b){return""===b||null===b||a.is(b,"undefined")}function g(b){return b=e(b),a.hasOwn(h,b)?e(h[b]):b}var h=b[c]||{};if(f(d))return"";if(a.is(d,"object")&&a.hasOwn(d,"raw"))return e(d.raw);if(a.is(d,"array")){var i=d.slice(1);d=g(d[0]).replace(/\{([0-9]+)\}/g,function(b,c){return a.hasOwn(i,c)?e(i[c]):b})}return g(d).replace(/{context:\w+}$/,"")},data:b}}),g("16",["e","5","6"],function(a,b,c){function d(a){function d(){try{return document.activeElement}catch(a){return document.body}}function j(a,b){if(b&&b.startContainer){if(!a.isChildOf(b.startContainer,a.getRoot())||!a.isChildOf(b.endContainer,a.getRoot()))return;return{startContainer:b.startContainer,startOffset:b.startOffset,endContainer:b.endContainer,endOffset:b.endOffset}}return b}function l(a,b){var
c;return b.startContainer?(c=a.getDoc().createRange(),c.setStart(b.startContainer,b.startOffset),c.setEnd(b.endContainer,b.endOffset)):c=b,c}function m(m){var n=m.editor;n.on("init",function(){(n.inline||c.ie)&&("onbeforedeactivate"in document&&c.ie<9?n.dom.bind(n.getBody(),"beforedeactivate",function(a){if(a.target==n.getBody())try{n.lastRng=n.selection.getRng()}catch(a){}}):n.on("nodechange mouseup keyup",function(a){var b=d();"nodechange"==a.type&&a.selectionChange||(b&&b.id==n.id+"_ifr"&&(b=n.getBody()),n.dom.isChildOf(b,n.getBody())&&(n.lastRng=n.selection.getRng()))}),c.webkit&&!e&&(e=function(){var b=a.activeEditor;if(b&&b.selection){var c=b.selection.getRng();c&&!c.collapsed&&(n.lastRng=c)}},h.bind(document,"selectionchange",e)))}),n.on("setcontent",function(){n.lastRng=null}),n.on("mousedown",fu
nction(){n.selection.lastFocusBookmark=null}),n.on("focusin",function(){var b,c=a.focusedEditor;n.selection.lastFocusBookmark&&(b=l(n,n.selection.lastFocusBookmark),n.selection.lastFocusBookmark=null,n.selection.setRng(b)),c!=n&&(c&&c.fire("blur",{focusedEditor:n}),a.setActive(n),a.focusedEditor=n,n.fire("focus",{blurredEditor:c}),n.focus(!0)),n.lastRng=null}),n.on("focusout",function(){b.setEditorTimeout(n,function(){var b=a.focusedEditor;i(n,d())||b!=n||(n.fire("blur",{focusedEditor:null}),a.focusedEditor=null,n.selection&&(n.selection.lastFocusBookmark=null))})}),f||(f=function(b){var c,d=a.activeEditor;c=b.target,d&&c.ownerDocument===document&&(d.selection&&c!==d.getBody()&&k(n,c)&&(d.selection.lastFocusBookmark=j(d.dom,d.lastRng)),c===document.body||i(d,c)||a.focusedEditor!==d||(d.fire("blur",{focusedEditor:null}),a.focusedEditor=null))},h.bind(doc
ument,"focusin",f)),n.inline&&!g&&(g=function(b){var c=a.activeEditor,d=c.dom;if(c.inline&&d&&!d.isChildOf(b.target,c.getBody())){var e=c.selection.getRng();e.collapsed||(c.lastRng=e)}},h.bind(document,"mouseup",g))}function n(b){a.focusedEditor==b.editor&&(a.focusedEditor=null),a.activeEditor||(h.unbind(document,"selectionchange",e),h.unbind(document,"focusin",f),h.unbind(document,"mouseup",g),e=f=g=null)}a.on("AddEditor",m),a.on("RemoveEditor",n)}var e,f,g,h=a.DOM,i=function(a,b){var c=a?a.settings.custom_ui_selector:"",e=h.getParent(b,function(b){return d.isEditorUIElement(b)||!!c&&a.dom.is(b,c)});return null!==e},j=function(a){return a.inline===!0},k=function(a,b){return j(a)===!1||a.dom.isChildOf(b,a.getBody())===!1};return d.isEditorUIElement=function(a){return a.className.toString().indexOf("mce-")!==-1},d._isUIElement=i,d}),g("26"
;,["9"],function(a){var b=a.each,c=a.explode,d=function(a){a.on("AddEditor",function(a){var d=a.editor;d.on("preInit",function(){function a(a,c){b(c,function(b,c){b&&h.setStyle(a,c,b)}),h.rename(a,"span")}function e(a){h=d.dom,i.convert_fonts_to_spans&&b(h.select("font,u,strike",a.node),function(a){f[a.nodeName.toLowerCase()](h,a)})}var f,g,h,i=d.settings;i.inline_styles&&(g=c(i.font_size_legacy_values),f={font:function(b,c){a(c,{backgroundColor:c.style.backgroundColor,color:c.color,fontFamily:c.face,fontSize:g[parseInt(c.size,10)-1]})},u:function(b,c){"html4"===d.settings.schema&&a(c,{textDecoration:"underline"})},strike:function(b,c){a(c,{textDecoration:"line-through"})}},d.on("PreProcess SetContent",e))})})};return{register:d}}),g("17",["g","a","e","14","6","25","16","26"
,"15","z","4","9","w"],function(a,b,c,d,e,f,g,h,i,j,k,l,m){function n(a){v(s.editors,function(b){"scroll"===a.type?b.fire("ScrollWindow",a):b.fire("ResizeWindow",a)})}function o(a,c){c!==y&&(c?b(window).on("resize scroll",n):b(window).off("resize scroll",n),y=c)}function p(a){var b,c=s.editors;delete c[a.id];for(var d=0;d<c.length;d++)if(c[d]==a){c.splice(d,1),b=!0;break}return s.activeEditor==a&&(s.activeEditor=c[0]),s.focusedEditor==a&&(s.focusedEditor=null),b}function q(a){return a&&a.initialized&&!(a.getContainer()||a.getBody()).parentNode&&(p(a),a.unbindAllNativeEvents(),a.destroy(!0),a.removed=!0,a=null),a}var r,s,t=c.DOM,u=l.explode,v=l.each,w=l.extend,x=0,y=!1;return s={$:b,majorVersion:"4",minorVersion:"6.0",releaseDate:"2017-05-04",editors:[],i18n:i,activeEditor:null,setup:function(){var a,b,c,d
,e=this,f="";if(b=m.getDocumentBaseUrl(document.location),/^[^:]+:\/\/\/?[^\/]+\//.test(b)&&(b=b.replace(/[\?#].*$/,"").replace(/[\/\\][^\/]+$/,""),/[\/\\]$/.test(b)||(b+="/")),c=window.tinymce||window.tinyMCEPreInit)a=c.base||c.baseURL,f=c.suffix;else{for(var h=document.getElementsByTagName("script"),i=0;i<h.length;i++){d=h[i].src;var j=d.substring(d.lastIndexOf("/"));if(/tinymce(\.full|\.jquery|)(\.min|\.dev|)\.js/.test(d)){j.indexOf(".min")!=-1&&(f=".min"),a=d.substring(0,d.lastIndexOf("/"));break}}!a&&document.currentScript&&(d=document.currentScript.src,d.indexOf(".min")!=-1&&(f=".min"),a=d.substring(0,d.lastIndexOf("/")))}e.baseURL=new m(b).toAbsolute(a),e.documentBaseURL=b,e.baseURI=new m(e.baseURL),e.suffix=f,e.focusManager=new g(e)},overrideDefaults:function(b){var c,d;c=b.base_url,c&&(this.baseURL=new m(t
his.documentBaseURL).toAbsolute(c.replace(/\/+$/,"")),this.baseURI=new m(this.baseURL)),d=b.suffix,b.suffix&&(this.suffix=d),this.defaultSettings=b;var e=b.plugin_base_urls;for(var f in e)a.PluginManager.urls[f]=e[f]},init:function(a){function c(a,b){return a.inline&&b.tagName.toLowerCase()in o}function g(a){var b=a.id;return b||(b=a.name,b=b&&!t.get(b)?a.name:t.uniqueId(),a.setAttribute("id",b)),b}function h(b){var c=a[b];if(c)return c.apply(p,Array.prototype.slice.call(arguments,2))}function i(a,b){return b.constructor===RegExp?b.test(a.className):t.hasClass(a,b)}function j(a){var b,c=[];if(e.ie&&e.ie<11)return f.initError("TinyMCE does not support the browser you are using. For a list of supported browsers please see: https://www.tinymce.com/docs/get-started/system-requirements/"),[];if(a.types)return v(a.types,function(a){c=c.concat(t.select(a.selector))}),c;if(a.selector)return t.select(a.selector);if(a.target)ret
urn[a.target];switch(a.mode){case"exact":b=a.elements||"",b.length>0&&v(u(b),function(a){var b;(b=t.get(a))?c.push(b):v(document.forms,function(b){v(b.elements,function(b){b.name===a&&(a="mce_editor_"+x++,t.setAttrib(b,"id",a),c.push(b))})})});break;case"textareas":case"specific_textareas":v(t.select("textarea"),function(b){a.editor_deselector&&i(b,a.editor_deselector)||a.editor_selector&&!i(b,a.editor_selector)||c.push(b)})}return c}function m(){function e(a,b,c){var e=new d(a,b,p);n.push(e),e.on("init",function(){++k===i.length&&r(n)}),e.targetElm=e.targetElm||c,e.render()}var i,k=0,n=[];return t.unbind(window,"ready",m),h("onpageload"),i=b.unique(j(a)),a.types?void v(a.types,function(b){l.each(i,function(c){return!t.is(c,b.selector)||(e(g(c),w({},a,b),c),!1)})}):(l.each(i,function(a){q(p.get(a.id))}),i=l.grep(i,function(a){return!p.get(a.i
d)}),void(0===i.length?r([]):v(i,function(b){c(a,b)?f.initError("Could not initialize inline editor on invalid inline target element",b):e(g(b),a,b)})))}var n,o,p=this;o=l.makeMap("area base basefont br col frame hr img input isindex link meta param embed source wbr track colgroup option tbody tfoot thead tr script noscript style textarea video audio iframe object menu"," ");var r=function(a){n=a};return p.settings=a,t.bind(window,"ready",m),new k(function(a){n?a(n):r=function(b){a(b)}})},get:function(a){return arguments.length?a in this.editors?this.editors[a]:null:this.editors},add:function(a){var b=this,c=b.editors;return c[a.id]=a,c.push(a),o(c,!0),b.activeEditor=a,b.fire("AddEditor",{editor:a}),r||(r=function(){b.fire("BeforeUnload")},t.bind(window,"beforeunload",r)),a},createEditor:function(a,b){return this.add(new d(a,b,this))},remove:function(a){var b,c,d=this,e=d.editors;{if(a)return"string"==ty
peof a?(a=a.selector||a,void v(t.select(a),function(a){c=e[a.id],c&&d.remove(c)})):(c=a,e[c.id]?(p(c)&&d.fire("RemoveEditor",{editor:c}),e.length||t.unbind(window,"beforeunload",r),c.remove(),o(e,e.length>0),c):null);for(b=e.length-1;b>=0;b--)d.remove(e[b])}},execCommand:function(a,b,c){var e=this,f=e.get(c);switch(a){case"mceAddEditor":return e.get(c)||new d(c,e.settings,e).render(),!0;case"mceRemoveEditor":return f&&f.remove(),!0;case"mceToggleEditor":return f?(f.isHidden()?f.show():f.hide(),!0):(e.execCommand("mceAddEditor",0,c),!0)}return!!e.activeEditor&&e.activeEditor.execCommand(a,b,c)},triggerSave:function(){v(this.editors,function(a){a.save()})},addI18n:function(a,b){i.add(a,b)},translate:function(a){return i.translate(a)},setActive:function(a){var b=this.activeEditor;this.activeEditor!=a&&(b&&b.fire("deactivate",{relatedTarget:a}),a.fire("activat
e",{relatedTarget:b})),this.activeEditor=a}},w(s,j),s.setup(),h.register(s),s}),g("18",["z","9"],function(a,b){var c={send:function(a){function d(){!a.async||4==e.readyState||f++>1e4?(a.success&&f<1e4&&200==e.status?a.success.call(a.success_scope,""+e.responseText,e,a):a.error&&a.error.call(a.error_scope,f>1e4?"TIMED_OUT":"GENERAL",e,a),e=null):setTimeout(d,10)}var e,f=0;if(a.scope=a.scope||this,a.success_scope=a.success_scope||a.scope,a.error_scope=a.error_scope||a.scope,a.async=a.async!==!1,a.data=a.data||"",c.fire("beforeInitialize",{settings:a}),e=new XMLHttpRequest){if(e.overrideMimeType&&e.overrideMimeType(a.content_type),e.open(a.type||(a.data?"POST":"GET"),a.url,a.async),a.crossDomain&&(e.withCredentials=!0),a.content_type&&e.setRequestHeader("Content-Type",a.content_type),a.requestheaders&&b.each(
a.requestheaders,function(a){e.setRequestHeader(a.key,a.value)}),e.setRequestHeader("X-Requested-With","XMLHttpRequest"),e=c.fire("beforeSend",{xhr:e,settings:a}).xhr,e.send(a.data),!a.async)return d();setTimeout(d,10)}}};return b.extend(c,a),c}),g("19",[],function(){function a(b,c){var d,e,f,g;if(c=c||'"',null===b)return"null";if(f=typeof b,"string"==f)return e="\bb\tt\nn\ff\rr\"\"''\\\\",c+b.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g,function(a,b){return'"'===c&&"'"===a?a:(d=e.indexOf(b),d+1?"\\"+e.charAt(d+1):(a=b.charCodeAt().toString(16),"\\u"+"0000".substring(a.length)+a))})+c;if("object"==f){if(b.hasOwnProperty&&"[object Array]"===Object.prototype.toString.call(b)){for(d=0,e="[";d<b.length;d++)e+=(d>0?",":"")+a(b[d],c);return e+"]"}e="{";for(g in b)b.h
asOwnProperty(g)&&(e+="function"!=typeof b[g]?(e.length>1?","+c:c)+g+c+":"+a(b[g],c):"");return e+"}"}return""+b}return{serialize:a,parse:function(a){try{return window[String.fromCharCode(101)+"val"]("("+a+")")}catch(a){}}}}),g("1a",["19","18","9"],function(a,b,c){function d(a){this.settings=e({},a),this.count=0}var e=c.extend;return d.sendRPC=function(a){return(new d).send(a)},d.prototype={send:function(c){var d=c.error,f=c.success;c=e(this.settings,c),c.success=function(b,e){b=a.parse(b),"undefined"==typeof b&&(b={error:"JSON Parse error."}),b.error?d.call(c.error_scope||c.scope,b.error,e):f.call(c.success_scope||c.scope,b.result)},c.error=function(a,b){d&&d.call(c.error_scope||c.scope,a,b)},c.data=a.serialize({id:c.id||"c"+this.count++,method:c.method,params:c.params}),c.content_type="applic
ation/json",b.send(c)}},d}),g("1b",["e"],function(a){return{callbacks:{},count:0,send:function(b){var c=this,d=a.DOM,e=void 0!==b.count?b.count:c.count,f="tinymce_jsonp_"+e;c.callbacks[e]=function(a){d.remove(f),delete c.callbacks[e],b.callback(a)},d.add(d.doc.body,"script",{id:f,src:b.url,type:"text/javascript"}),c.count++}}}),g("1c",[],function(){function a(){g=[];for(var a in f)g.push(a);d.length=g.length}function b(){function b(a){var b,c;return c=void 0!==a?j+a:d.indexOf(",",j),c===-1||c>d.length?null:(b=d.substring(j,c),j=c+1,b)}var c,d,g,j=0;if(f={},i){e.load(h),d=e.getAttribute(h)||"";do{var k=b();if(null===k)break;if(c=b(parseInt(k,32)||0),null!==c){if(k=b(),null===k)break;g=b(parseInt(k,32)||0),c&&(f[c]=g)}}while(null!==c);a()}}function c(){
+var b,c="";if(i){for(var d in f)b=f[d],c+=(c?",":"")+d.length.toString(32)+","+d+","+b.length.toString(32)+","+b;e.setAttribute(h,c);try{e.save(h)}catch(a){}a()}}var d,e,f,g,h,i;try{if(window.localStorage)return localStorage}catch(a){}return h="tinymce",e=document.documentElement,i=!!e.addBehavior,i&&e.addBehavior("#default#userData"),d={key:function(a){return g[a]},getItem:function(a){return a in f?f[a]:null},setItem:function(a,b){f[a]=""+b,c()},removeItem:function(a){delete f[a],c()},clear:function(){f={},c()}},b(),d}),g("1d",["e","7","f","g","9","6"],function(a,b,c,d,e,f){var g=function(g){g.DOM=a.DOM,g.ScriptLoader=c.ScriptLoader,g.PluginManager=d.PluginManager,g.ThemeManager=d.ThemeManager,g.dom=g.dom||{},g.dom.Event=b.Event,e.each("trim isArray is toArray makeMap each map grep inArray extend create walk cre
ateNS resolve explode _addCacheSuffix".split(" "),function(a){g[a]=e[a]}),e.each("isOpera isWebKit isIE isGecko isMac".split(" "),function(a){g[a]=f[a.substr(2).toLowerCase()]})};return{register:g}}),g("1e",[],function(){function a(a){function e(a,e,f){var g,h,i,j,k,l;return g=0,h=0,i=0,a/=255,e/=255,f/=255,k=b(a,b(e,f)),l=c(a,c(e,f)),k==l?(i=k,{h:0,s:0,v:100*i}):(j=a==k?e-f:f==k?a-e:f-a,g=a==k?3:f==k?1:5,g=60*(g-j/(l-k)),h=(l-k)/l,i=l,{h:d(g),s:d(100*h),v:d(100*i)})}function f(a,e,f){var g,h,i,j;if(a=(parseInt(a,10)||0)%360,e=parseInt(e,10)/100,f=parseInt(f,10)/100,e=c(0,b(e,1)),f=c(0,b(f,1)),0===e)return void(l=m=n=d(255*f));switch(g=a/60,h=f*e,i=h*(1-Math.abs(g%2-1)),j=f-h,Math.floor(g)){case 0:l=h,m=i,n=0;break;case 1:l=i,m=h,n=0;break;case 2:l=0,m=h,n=i;break;case 3:l=0,m=i,n=h;break;case 4:l=i,m=0,n=h;break;case 5:l=h,m=0,n=i;break;default:l=m=n=0}l=d(255*(l+j)),m=d(255*(m+j)),n=d(255*(n+j))}function g(){function a(a){return a=parse
Int(a,10).toString(16),a.length>1?a:"0"+a}return"#"+a(l)+a(m)+a(n)}function h(){return{r:l,g:m,b:n}}function i(){return e(l,m,n)}function j(a){var b;return"object"==typeof a?"r"in a?(l=a.r,m=a.g,n=a.b):"v"in a&&f(a.h,a.s,a.v):(b=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)[^\)]*\)/gi.exec(a))?(l=parseInt(b[1],10),m=parseInt(b[2],10),n=parseInt(b[3],10)):(b=/#([0-F]{2})([0-F]{2})([0-F]{2})/gi.exec(a))?(l=parseInt(b[1],16),m=parseInt(b[2],16),n=parseInt(b[3],16)):(b=/#([0-F])([0-F])([0-F])/gi.exec(a))&&(l=parseInt(b[1]+b[1],16),m=parseInt(b[2]+b[2],16),n=parseInt(b[3]+b[3],16)),l=l<0?0:l>255?255:l,m=m<0?0:m>255?255:m,n=n<0?0:n>255?255:n,k}var k=this,l=0,m=0,n=0;a&&j(a),k.toRgb=h,k.toHsv=i,k.toHex=g,k.parse=j}var b=Math.min,c=Math.max,d=Math.round;return a}),g("2n",["x","9"],function(a,b){"use strict";return a.extend({Defaults:{firstControlClass:&
quot;first",lastControlClass:"last"},init:function(a){this.settings=b.extend({},this.Defaults,a)},preRender:function(a){a.bodyClasses.add(this.settings.containerClass)},applyClasses:function(a){var b,c,d,e,f=this,g=f.settings;b=g.firstControlClass,c=g.lastControlClass,a.each(function(a){a.classes.remove(b).remove(c).add(g.controlClass),a.visible()&&(d||(d=a),e=a)}),d&&d.classes.add(b),e&&e.classes.add(c)},renderHtml:function(a){var b=this,c="";return b.applyClasses(a.items()),a.items().each(function(a){c+=a.renderHtml()}),c},recalc:function(){},postRender:function(){},isNative:function(){return!1}})}),g("2o",["2n"],function(a){"use strict";return a.extend({Defaults:{containerClass:"abs-layout",controlClass:"abs-layout-item"},recalc:function(a){a.items().filter(":visible").each(function(a){var b=a.settings;a.layoutRect({x:b.x,y:b.y,w:b.w,h:b.h}),a.recalc&&a.recalc()})}
,renderHtml:function(a){return'<div id="'+a._id+'-absend" class="'+a.classPrefix+'abs-end"></div>'+this._super(a)}})}),g("2p",["2l"],function(a){"use strict";return a.extend({Defaults:{classes:"widget btn",role:"button"},init:function(a){var b,c=this;c._super(a),a=c.settings,b=c.settings.size,c.on("click mousedown",function(a){a.preventDefault()}),c.on("touchstart",function(a){c.fire("click",a),a.preventDefault()}),a.subtype&&c.classes.add(a.subtype),b&&c.classes.add("btn-"+b),a.icon&&c.icon(a.icon)},icon:function(a){return arguments.length?(this.state.set("icon",a),this):this.state.get("icon")},repaint:function(){var a,b=this.getEl().firstChild;b&&(a=b.style,a.width=a.height="100%"),this._super()},renderHtml:function(){var a,b=this,c=b._id,d=b.classPrefix,e=b.state.get("icon"),f=b.state.get(
"text"),g="";return a=b.settings.image,a?(e="none","string"!=typeof a&&(a=window.getSelection?a[0]:a[1]),a=" style=\"background-image: url('"+a+"')\""):a="",f&&(b.classes.add("btn-has-text"),g='<span class="'+d+'txt">'+b.encode(f)+"</span>"),e=e?d+"ico "+d+"i-"+e:"",'<div id="'+c+'" class="'+b.classes+'" tabindex="-1"><button role="presentation" type="button" tabindex="-1">'+(e?'<i class="'+e+'"'+a+"></i>":"")+g+"</button></div>"},bindStates:function(){function a(a){var e=c("span."+d,b.getEl());a?(e[0]||(c("button:first",b.getEl()).append('<span class="'+d+'"></span>'),e=c("span."+d,b.getEl())),e.html(b.encode(a))):e.remove(),b.class
es.toggle("btn-has-text",!!a)}var b=this,c=b.$,d=b.classPrefix+"txt";return b.state.on("change:text",function(b){a(b.value)}),b.state.on("change:icon",function(c){var d=c.value,e=b.classPrefix;b.settings.icon=d,d=d?e+"ico "+e+"i-"+b.settings.icon:"";var f=b.getEl().firstChild,g=f.getElementsByTagName("i")[0];d?(g&&g==f.firstChild||(g=document.createElement("i"),f.insertBefore(g,f.firstChild)),g.className=d):g&&f.removeChild(g),a(b.state.get("text"))}),b._super()}})}),g("2q",["2d"],function(a){"use strict";return a.extend({Defaults:{defaultType:"button",role:"group"},renderHtml:function(){var a=this,b=a._layout;return a.classes.add("btn-group"),a.preRender(),b.preRender(a),'<div id="'+a._id+'" class="'+a.classes+'"><div id="'+a._id+'-body">'+(a.settings.html||"&quo
t;)+b.renderHtml(a)+"</div></div>"}})}),g("2r",["2l"],function(a){"use strict";return a.extend({Defaults:{classes:"checkbox",role:"checkbox",checked:!1},init:function(a){var b=this;b._super(a),b.on("click mousedown",function(a){a.preventDefault()}),b.on("click",function(a){a.preventDefault(),b.disabled()||b.checked(!b.checked())}),b.checked(b.settings.checked)},checked:function(a){return arguments.length?(this.state.set("checked",a),this):this.state.get("checked")},value:function(a){return arguments.length?this.checked(a):this.checked()},renderHtml:function(){var a=this,b=a._id,c=a.classPrefix;return'<div id="'+b+'" class="'+a.classes+'" unselectable="on" aria-labelledby="'+b+'-al" tabindex="-1"><i class="'+c+"ico "+c+'i-checkbox"></i><span id="'+b+'-al" class="'+c+'la
bel">'+a.encode(a.state.get("text"))+"</span></div>"},bindStates:function(){function a(a){b.classes.toggle("checked",a),b.aria("checked",a)}var b=this;return b.state.on("change:text",function(a){b.getEl("al").firstChild.data=b.translate(a.value)}),b.state.on("change:checked change:value",function(c){b.fire("change"),a(c.value)}),b.state.on("change:icon",function(a){var c=a.value,d=b.classPrefix;if("undefined"==typeof c)return b.settings.icon;b.settings.icon=c,c=c?d+"ico "+d+"i-"+b.settings.icon:"";var e=b.getEl().firstChild,f=e.getElementsByTagName("i")[0];c?(f&&f==e.firstChild||(f=document.createElement("i"),e.insertBefore(f,e.firstChild)),f.className=c):f&&e.removeChild(f)}),b.state.get("checked")&&a(!0),b._super()}})}),g("2s",["2l","2b","48"
;,"a","p","9"],function(a,b,c,d,e,f){"use strict";return a.extend({init:function(a){var b=this;b._super(a),a=b.settings,b.classes.add("combobox"),b.subinput=!0,b.ariaTarget="inp",a.menu=a.menu||a.values,a.menu&&(a.icon="caret"),b.on("click",function(c){var e=c.target,f=b.getEl();if(d.contains(f,e)||e==f)for(;e&&e!=f;)e.id&&e.id.indexOf("-open")!=-1&&(b.fire("action"),a.menu&&(b.showMenu(),c.aria&&b.menu.items()[0].focus())),e=e.parentNode}),b.on("keydown",function(a){var c;13==a.keyCode&&"INPUT"===a.target.nodeName&&(a.preventDefault(),b.parents().reverse().each(function(a){if(a.toJSON)return c=a,!1}),b.fire("submit",{data:c.toJSON()}))}),b.on("keyup",function(a){if("INPUT"==a.target.nodeName){var c=b.state.get("value"),d=a.target.value;d!==c&&(b.state.se
t("value",d),b.fire("autocomplete",a))}}),b.on("mouseover",function(a){var c=b.tooltip().moveTo(-65535);if(b.statusLevel()&&a.target.className.indexOf(b.classPrefix+"status")!==-1){var d=b.statusMessage()||"Ok",e=c.text(d).show().testMoveRel(a.target,["bc-tc","bc-tl","bc-tr"]);c.classes.toggle("tooltip-n","bc-tc"==e),c.classes.toggle("tooltip-nw","bc-tl"==e),c.classes.toggle("tooltip-ne","bc-tr"==e),c.moveRel(a.target,e)}})},statusLevel:function(a){return arguments.length>0&&this.state.set("statusLevel",a),this.state.get("statusLevel")},statusMessage:function(a){return arguments.length>0&&this.state.set("statusMessage",a),this.state.get("statusMessage")},showMenu:function(){var a,c=this,d=c.settings;c.menu||(a=d.menu||[],a.length?a={type:"menu",items:a}:a.type=a.type
||"menu",c.menu=b.create(a).parent(c).renderTo(c.getContainerElm()),c.fire("createmenu"),c.menu.reflow(),c.menu.on("cancel",function(a){a.control===c.menu&&c.focus()}),c.menu.on("show hide",function(a){a.control.items().each(function(a){a.active(a.value()==c.value())})}).fire("show"),c.menu.on("select",function(a){c.value(a.control.value())}),c.on("focusin",function(a){"INPUT"==a.target.tagName.toUpperCase()&&c.menu.hide()}),c.aria("expanded",!0)),c.menu.show(),c.menu.layoutRect({w:c.layoutRect().w}),c.menu.moveRel(c.getEl(),c.isRtl()?["br-tr","tr-br"]:["bl-tl","tl-bl"])},focus:function(){this.getEl("inp").focus()},repaint:function(){var a,b,e=this,f=e.getEl(),g=e.getEl("open"),h=e.layoutRect(),i=0,j=f.firstChild;e.statusLevel()&&"none"!==e.statusLevel()&&(i=parseInt(c.getRuntimeStyle(j,"p
adding-right"),10)-parseInt(c.getRuntimeStyle(j,"padding-left"),10)),a=g?h.w-c.getSize(g).width-10:h.w-10;var k=document;return k.all&&(!k.documentMode||k.documentMode<=8)&&(b=e.layoutRect().h-2+"px"),d(j).css({width:a-i,lineHeight:b}),e._super(),e},postRender:function(){var a=this;return d(this.getEl("inp")).on("change",function(b){a.state.set("value",b.target.value),a.fire("change",b)}),a._super()},renderHtml:function(){var a,b,c=this,d=c._id,e=c.settings,f=c.classPrefix,g=c.state.get("value")||"",h="",i="",j="";return"spellcheck"in e&&(i+=' spellcheck="'+e.spellcheck+'"'),e.maxLength&&(i+=' maxlength="'+e.maxLength+'"'),e.size&&(i+=' size="'+e.size+'"'),e.subtype&&(i+=' type="'+e.subtype+'"'),j='<i id="'+d+'-status" class="mce-status mce-ico" st
yle="display: none"></i>',c.disabled()&&(i+=' disabled="disabled"'),a=e.icon,a&&"caret"!=a&&(a=f+"ico "+f+"i-"+e.icon),b=c.state.get("text"),(a||b)&&(h='<div id="'+d+'-open" class="'+f+"btn "+f+'open" tabIndex="-1" role="button"><button id="'+d+'-action" type="button" hidefocus="1" tabindex="-1">'+("caret"!=a?'<i class="'+a+'"></i>':'<i class="'+f+'caret"></i>')+(b?(a?" ":"")+b:"")+"</button></div>",c.classes.add("has-open")),'<div id="'+d+'" class="'+c.classes+'"><input id="'+d+'-inp" class="'+f+'textbox" value="'+c.encode(g,!1)+'" hidefocus="1"'+i+' placeholder="'+c.encode(e.placeholder)+'"
/>'+j+h+"</div>"},value:function(a){return arguments.length?(this.state.set("value",a),this):(this.state.get("rendered")&&this.state.set("value",this.getEl("inp").value),this.state.get("value"))},showAutoComplete:function(a,c){var d=this;if(0===a.length)return void d.hideMenu();var e=function(a,b){return function(){d.fire("selectitem",{title:b,value:a})}};d.menu?d.menu.items().remove():d.menu=b.create({type:"menu",classes:"combobox-menu",layout:"flow"}).parent(d).renderTo(),f.each(a,function(a){d.menu.add({text:a.title,url:a.previewUrl,match:c,classes:"menu-item-ellipsis",onclick:e(a.value,a.title)})}),d.menu.renderNew(),d.hideMenu(),d.menu.on("cancel",function(a){a.control.parent()===d.menu&&(a.stopPropagation(),d.focus(),d.hideMenu())}),d.menu.on("select",function(){d.focus()});var g=d.layoutRect().w;d.menu.layoutRect({w:g,minW
:0,maxW:g}),d.menu.reflow(),d.menu.show(),d.menu.moveRel(d.getEl(),d.isRtl()?["br-tr","tr-br"]:["bl-tl","tl-bl"])},hideMenu:function(){this.menu&&this.menu.hide()},bindStates:function(){var a=this;a.state.on("change:value",function(b){a.getEl("inp").value!=b.value&&(a.getEl("inp").value=b.value)}),a.state.on("change:disabled",function(b){a.getEl("inp").disabled=b.value}),a.state.on("change:statusLevel",function(b){var d=a.getEl("status"),e=a.classPrefix,f=b.value;c.css(d,"display","none"===f?"none":""),c.toggleClass(d,e+"i-checkmark","ok"===f),c.toggleClass(d,e+"i-warning","warn"===f),c.toggleClass(d,e+"i-error","error"===f),a.classes.toggle("has-status","none"!==f),a.repaint()}),c.on(a.getEl("status"),"mouseleave",functi
on(){a.tooltip().hide()}),a.on("cancel",function(b){a.menu&&a.menu.visible()&&(b.stopPropagation(),a.hideMenu())});var b=function(a,b){b&&b.items().length>0&&b.items().eq(a)[0].focus()};return a.on("keydown",function(c){var d=c.keyCode;"INPUT"===c.target.nodeName&&(d===e.DOWN?(c.preventDefault(),a.fire("autocomplete"),b(0,a.menu)):d===e.UP&&(c.preventDefault(),b(-1,a.menu)))}),a._super()},remove:function(){d(this.getEl("inp")).off(),this.menu&&this.menu.remove(),this._super()}})}),g("2t",["2s"],function(a){"use strict";return a.extend({init:function(a){var b=this;a.spellcheck=!1,a.onaction&&(a.icon="none"),b._super(a),b.classes.add("colorbox"),b.on("change keyup postrender",function(){b.repaintColor(b.value())})},repaintColor:function(a){var b=this.getEl("open"),c=b?b.getElementsByTagName("i&qu
ot;)[0]:null;if(c)try{c.style.background=a}catch(a){}},bindStates:function(){var a=this;return a.state.on("change:value",function(b){a.state.get("rendered")&&a.repaintColor(b.value)}),a._super()}})}),g("2u",["2p","2j"],function(a,b){"use strict";return a.extend({showPanel:function(){var a=this,c=a.settings;if(a.active(!0),a.panel)a.panel.show();else{var d=c.panel;d.type&&(d={layout:"grid",items:d}),d.role=d.role||"dialog",d.popover=!0,d.autohide=!0,d.ariaRoot=!0,a.panel=new b(d).on("hide",function(){a.active(!1)}).on("cancel",function(b){b.stopPropagation(),a.focus(),a.hidePanel()}).parent(a).renderTo(a.getContainerElm()),a.panel.fire("show"),a.panel.reflow()}a.panel.moveRel(a.getEl(),c.popoverAlign||(a.isRtl()?["bc-tr","bc-tc"]:["bc-tl","bc-tc"]))},hidePanel:function(){var a=this;a.panel&&a.panel.hide()},postRe
nder:function(){var a=this;return a.aria("haspopup",!0),a.on("click",function(b){b.control===a&&(a.panel&&a.panel.visible()?a.hidePanel():(a.showPanel(),a.panel.focus(!!b.aria)))}),a._super()},remove:function(){return this.panel&&(this.panel.remove(),this.panel=null),this._super()}})}),g("2v",["2u","e"],function(a,b){"use strict";var c=b.DOM;return a.extend({init:function(a){this._super(a),this.classes.add("colorbutton")},color:function(a){return a?(this._color=a,this.getEl("preview").style.backgroundColor=a,this):this._color},resetColor:function(){return this._color=null,this.getEl("preview").style.backgroundColor=null,this},renderHtml:function(){var a=this,b=a._id,c=a.classPrefix,d=a.state.get("text"),e=a.settings.icon?c+"ico "+c+"i-"+a.settings.icon:"",f=a.settings.image?" style=\"background-image: url('"+a.settin
gs.image+"')\"":"",g="";return d&&(a.classes.add("btn-has-text"),g='<span class="'+c+'txt">'+a.encode(d)+"</span>"),'<div id="'+b+'" class="'+a.classes+'" role="button" tabindex="-1" aria-haspopup="true"><button role="presentation" hidefocus="1" type="button" tabindex="-1">'+(e?'<i class="'+e+'"'+f+"></i>":"")+'<span id="'+b+'-preview" class="'+c+'preview"></span>'+g+'</button><button type="button" class="'+c+'open" hidefocus="1" tabindex="-1"> <i class="'+c+'caret"></i></button></div>'},postRender:function(){var a=this,b=a.settings.onclick;return a.on("click",function(d){d.aria&&"down"==d.aria.key||d.control!=a||c
.getParent(d.target,"."+a.classPrefix+"open")||(d.stopImmediatePropagation(),b.call(a,d))}),delete a.settings.onclick,a._super()}})}),g("2w",["2l","2e","48","1e"],function(a,b,c,d){"use strict";return a.extend({Defaults:{classes:"widget colorpicker"},init:function(a){this._super(a)},postRender:function(){function a(a,b){var d,e,f=c.getPos(a);return d=b.pageX-f.x,e=b.pageY-f.y,d=Math.max(0,Math.min(d/a.clientWidth,1)),e=Math.max(0,Math.min(e/a.clientHeight,1)),{x:d,y:e}}function e(a,b){var e=(360-a.h)/360;c.css(j,{top:100*e+"%"}),b||c.css(l,{left:a.s+"%",top:100-a.v+"%"}),k.style.background=new d({s:100,v:100,h:a.h}).toHex(),m.color().parse({s:a.s,v:a.v,h:a.h})}function f(b){var c;c=a(k,b),h.s=100*c.x,h.v=100*(1-c.y),e(h),m.fire("change")}function g(b){var c;c=a(i,b),h=n.toHsv(),h.h=360*(1-c.y),e(h,!0),m.fire("change")}var h,i,j,k,l,m=this,n=m.co
lor();i=m.getEl("h"),j=m.getEl("hp"),k=m.getEl("sv"),l=m.getEl("svp"),m._repaint=function(){h=n.toHsv(),e(h)},m._super(),m._svdraghelper=new b(m._id+"-sv",{start:f,drag:f}),m._hdraghelper=new b(m._id+"-h",{start:g,drag:g}),m._repaint()},rgb:function(){return this.color().toRgb()},value:function(a){var b=this;return arguments.length?(b.color().parse(a),void(b._rendered&&b._repaint())):b.color().toHex()},color:function(){return this._color||(this._color=new d),this._color},renderHtml:function(){function a(){var a,b,c,d,g="";for(c="filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr=",d=f.split(","),a=0,b=d.length-1;a<b;a++)g+='<div class="'+e+'colorpicker-h-chunk" style="height:'+100/b+"%;"+c+d[a]+",endColorstr="+d[a+1]+");-ms-"+c+d[a]+",endColorstr="+d[a+1]+')"></div>';return g}var b,c=t
his,d=c._id,e=c.classPrefix,f="#ff0000,#ff0080,#ff00ff,#8000ff,#0000ff,#0080ff,#00ffff,#00ff80,#00ff00,#80ff00,#ffff00,#ff8000,#ff0000",g="background: -ms-linear-gradient(top,"+f+");background: linear-gradient(to bottom,"+f+");";return b='<div id="'+d+'-h" class="'+e+'colorpicker-h" style="'+g+'">'+a()+'<div id="'+d+'-hp" class="'+e+'colorpicker-h-marker"></div></div>','<div id="'+d+'" class="'+c.classes+'"><div id="'+d+'-sv" class="'+e+'colorpicker-sv"><div class="'+e+'colorpicker-overlay1"><div class="'+e+'colorpicker-overlay2"><div id="'+d+'-svp" class="'+e+'colorpicker-selector1"><div class="'+e+'colorpicker-selector2"></div></div></div></div></div>'+b+"</div>"}})}),g("2x",["2l"
],function(a){"use strict";return a.extend({init:function(a){var b=this;a.delimiter||(a.delimiter="\xbb"),b._super(a),b.classes.add("path"),b.canFocus=!0,b.on("click",function(a){var c,d=a.target;(c=d.getAttribute("data-index"))&&b.fire("select",{value:b.row()[c],index:c})}),b.row(b.settings.row)},focus:function(){var a=this;return a.getEl().firstChild.focus(),a},row:function(a){return arguments.length?(this.state.set("row",a),this):this.state.get("row")},renderHtml:function(){var a=this;return'<div id="'+a._id+'" class="'+a.classes+'">'+a._getDataPathHtml(a.state.get("row"))+"</div>"},bindStates:function(){var a=this;return a.state.on("change:row",function(b){a.innerHtml(a._getDataPathHtml(b.value))}),a._super()},_getDataPathHtml:function(a){var b,c,d=this,e=a||[],f="",g=d.classPrefix;for(b=0,c=e.length;b<c;b++)f+=(b>0
?'<div class="'+g+'divider" aria-hidden="true"> '+d.settings.delimiter+" </div>":"")+'<div role="button" class="'+g+"path-item"+(b==c-1?" "+g+"last":"")+'" data-index="'+b+'" tabindex="-1" id="'+d._id+"-"+b+'" aria-level="'+(b+1)+'">'+e[b].name+"</div>";return f||(f='<div class="'+g+'path-item">\xa0</div>'),f}})}),g("2y",["2x"],function(a){return a.extend({postRender:function(){function a(a){if(1===a.nodeType){if("BR"==a.nodeName||a.getAttribute("data-mce-bogus"))return!0;if("bookmark"===a.getAttribute("data-mce-type"))return!0}return!1}var b=this,c=b.settings.editor;return c.settings.elementpath!==!1&&(b.on("select",function(a){c.focus(),c.selection.select(this.row()[a.index].element),c.nodeChanged()}),
c.on("nodeChange",function(d){for(var e=[],f=d.parents,g=f.length;g--;)if(1==f[g].nodeType&&!a(f[g])){var h=c.fire("ResolveName",{name:f[g].nodeName.toLowerCase(),target:f[g]});if(h.isDefaultPrevented()||e.push({name:h.name,element:f[g]}),h.isPropagationStopped())break}b.row(e)})),b._super()}})}),g("2z",["2d"],function(a){"use strict";return a.extend({Defaults:{layout:"flex",align:"center",defaults:{flex:1}},renderHtml:function(){var a=this,b=a._layout,c=a.classPrefix;return a.classes.add("formitem"),b.preRender(a),'<div id="'+a._id+'" class="'+a.classes+'" hidefocus="1" tabindex="-1">'+(a.settings.title?'<div id="'+a._id+'-title" class="'+c+'title">'+a.settings.title+"</div>":"")+'<div id="'+a._id+'-body" class="'+a.bodyClasses+'">'+(a.settings.html||"")+b.renderH
tml(a)+"</div></div>"}})}),g("30",["2d","2z","9"],function(a,b,c){"use strict";return a.extend({Defaults:{containerCls:"form",layout:"flex",direction:"column",align:"stretch",flex:1,padding:20,labelGap:30,spacing:10,callbacks:{submit:function(){this.submit()}}},preRender:function(){var a=this,d=a.items();a.settings.formItemDefaults||(a.settings.formItemDefaults={layout:"flex",autoResize:"overflow",defaults:{flex:1}}),d.each(function(d){var e,f=d.settings.label;f&&(e=new b(c.extend({items:{type:"label",id:d._id+"-l",text:f,flex:0,forId:d._id,disabled:d.disabled()}},a.settings.formItemDefaults)),e.type="formitem",d.aria("labelledby",d._id+"-l"),"undefined"==typeof d.settings.flex&&(d.settings.flex=1),a.replace(d,e),e.add(d))})},submit:function(){return this.fire("submit"
,{data:this.toJSON()})},postRender:function(){var a=this;a._super(),a.fromJSON(a.settings.data)},bindStates:function(){function a(){var a,c,d,e=0,f=[];if(b.settings.labelGapCalc!==!1)for(d="children"==b.settings.labelGapCalc?b.find("formitem"):b.items(),d.filter("formitem").each(function(a){var b=a.items()[0],c=b.getEl().clientWidth;e=c>e?c:e,f.push(b)}),c=b.settings.labelGap||0,a=f.length;a--;)f[a].settings.minWidth=e+c}var b=this;b._super(),b.on("show",a),a()}})}),g("31",["30"],function(a){"use strict";return a.extend({Defaults:{containerCls:"fieldset",layout:"flex",direction:"column",align:"stretch",flex:1,padding:"25 15 5 15",labelGap:30,spacing:10,border:1},renderHtml:function(){var a=this,b=a._layout,c=a.classPrefix;return a.preRender(),b.preRender(a),'<fieldset id="'+a._id+'" class="'+a.classes+'" hidefocus="1" tabindex=&q
uot;-1">'+(a.settings.title?'<legend id="'+a._id+'-title" class="'+c+'fieldset-title">'+a.settings.title+"</legend>":"")+'<div id="'+a._id+'-body" class="'+a.bodyClasses+'">'+(a.settings.html||"")+b.renderHtml(a)+"</div></fieldset>"}})}),g("4f",["e","1j","1g","1r","9","24"],function(a,b,c,d,e,f){var g=e.trim,h=function(a,b,c,d,e){return{type:a,title:b,url:c,level:d,attach:e}},i=function(a){for(;a=a.parentNode;){var c=a.contentEditable;if(c&&"inherit"!==c)return b.isContentEditableTrue(a)}return!1},j=function(b,c){return a.DOM.select(b,c)},k=function(a){return a.innerText||a.textContent},l=function(a){return a.id?a.id:f.uuid("h")},m=function(a){return a&&"A"===a.nodeName&&(a.id||a.name)},n=function(a){return m(a)&&p(a)},o=function(a){retu
rn a&&/^(H[1-6])$/.test(a.nodeName)},p=function(a){return i(a)&&!b.isContentEditableFalse(a)},q=function(a){return o(a)&&p(a)},r=function(a){return o(a)?parseInt(a.nodeName.substr(1),10):0},s=function(a){var b=l(a),c=function(){a.id=b};return h("header",k(a),"#"+b,r(a),c)},t=function(a){var b=a.id||a.name,c=k(a);return h("anchor",c?c:"#"+b,"#"+b,0,d.noop)},u=function(a){return c.map(c.filter(a,q),s)},v=function(a){return c.map(c.filter(a,n),t)},w=function(a){var b=j("h1,h2,h3,h4,h5,h6,a:not([href])",a);return b},x=function(a){return g(a.title).length>0},y=function(a){var b=w(a);return c.filter(u(b).concat(v(b)),x)};return{find:y}}),g("32",["4b","4f","17","2s","1g","1r","9"],function(a,b,c,d,e,f,g){"use strict";var h=function(){return a.tinymce?a.tinymce.activeEditor:c.activeEditor},i={},j=5,k=function(a){retu
rn{title:a.title,value:{title:{raw:a.title},url:a.url,attach:a.attach}}},l=function(a){return g.map(a,k)},m=function(a,b){return{title:a,value:{title:a,url:b,attach:f.noop}}},n=function(a,b){var c=e.find(b,function(b){return b.url===a});return!c},o=function(a,b,c){var d=b in a?a[b]:c;return d===!1?null:d},p=function(a,b,c,d){var h={title:"-"},j=function(a){var d=e.filter(a[c],function(a){return n(a,b)});return g.map(d,function(a){return{title:a,value:{title:a,url:a,attach:f.noop}}})},k=function(a){var c=e.filter(b,function(b){return b.type==a});return l(c)},p=function(){var a=k("anchor"),b=o(d,"anchor_top","#top"),c=o(d,"anchor_bottom","#bottom");return null!==b&&a.unshift(m("<top>",b)),null!==c&&a.push(m("<bottom>",c)),a},q=function(a){return e.reduce(a,function(a,b){var c=0===a.length||0===b.length;return c?a.concat(b):a.concat(h,b)},[])};return d.typeahead_urls===!1?[]:&quo
t;file"===c?q([r(a,j(i)),r(a,k("header")),r(a,p())]):r(a,j(i))},q=function(a,b){var c=i[b];/^https?/.test(a)&&(c?e.indexOf(c,a)===-1&&(i[b]=c.slice(0,j).concat(a)):i[b]=[a])},r=function(a,b){var c=a.toLowerCase(),d=g.grep(b,function(a){return a.title.toLowerCase().indexOf(c)!==-1});return 1===d.length&&d[0].title===a?[]:d},s=function(a){var b=a.title;return b.raw?b.raw:b},t=function(a,c,d,e){var f=function(f){var g=b.find(d),h=p(f,g,e,c);a.showAutoComplete(h,f)};a.on("autocomplete",function(){f(a.value())}),a.on("selectitem",function(b){var c=b.value;a.value(c.url);var d=s(c);"image"===e?a.fire("change",{meta:{alt:d,attach:c.attach}}):a.fire("change",{meta:{text:d,attach:c.attach}}),a.focus()}),a.on("click",function(b){0===a.value().length&&"INPUT"===b.target.nodeName&&f("")}),a.on("PostRender",function(){a.getRoot().on("submit",f
unction(b){b.isDefaultPrevented()||q(a.value(),e)})})},u=function(a){var b=a.status,c=a.message;return"valid"===b?{status:"ok",message:c}:"unknown"===b?{status:"warn",message:c}:"invalid"===b?{status:"warn",message:c}:{status:"none",message:""}},v=function(a,b,c){var d=b.filepicker_validator_handler;if(d){var e=function(b){return 0===b.length?void a.statusLevel("none"):void d({url:b,type:c},function(b){var c=u(b);a.statusMessage(c.message),a.statusLevel(c.status)})};a.state.on("change:value",function(a){e(a.value)})}};return d.extend({init:function(b){var c,d,e,f=this,i=h(),j=i.settings,k=b.filetype;b.spellcheck=!1,e=j.file_picker_types||j.file_browser_callback_types,e&&(e=g.makeMap(e,/[, ]/)),e&&!e[k]||(d=j.file_picker_callback,!d||e&&!e[k]?(d=j.file_browser_callback,!d||e&&!e[k]||(c=function(){d(f.getEl("inp").id,f.value(),k,a)})):c=function
(){var a=f.fire("beforecall").meta;a=g.extend({filetype:k},a),d.call(i,function(a,b){f.value(a).fire("change",{meta:b})},f.value(),a)}),c&&(b.icon="browse",b.onaction=c),f._super(b),t(f,j,i.getBody(),k),v(f,j,k)}})}),g("33",["2o"],function(a){"use strict";return a.extend({recalc:function(a){var b=a.layoutRect(),c=a.paddingBox;a.items().filter(":visible").each(function(a){a.layoutRect({x:c.left,y:c.top,w:b.innerW-c.right-c.left,h:b.innerH-c.top-c.bottom}),a.recalc&&a.recalc()})}})}),g("34",["2o"],function(a){"use strict";return a.extend({recalc:function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N=[],O=Math.max,P=Math.min;for(d=a.items().filter(":visible"),e=a.layoutRect(),f=a.paddingBox,g=a.settings,m=a.isRtl()?g.direction||"row-reversed":g.direction,h=g.align,i=a.isRtl()?g.pack||"end":g.pack,j=g.spa
cing||0,"row-reversed"!=m&&"column-reverse"!=m||(d=d.set(d.toArray().reverse()),m=m.split("-")[0]),"column"==m?(z="y",x="h",y="minH",A="maxH",C="innerH",B="top",D="deltaH",E="contentH",J="left",H="w",F="x",G="innerW",I="minW",K="right",L="deltaW",M="contentW"):(z="x",x="w",y="minW",A="maxW",C="innerW",B="left",D="deltaW",E="contentW",J="top",H="h",F="y",G="innerH",I="minH",K="bottom",L="deltaH",M="contentH"),l=e[C]-f[B]-f[B],w=k=0,b=0,c=d.length;b<c;b++)n=d[b],o=n.layoutRect(),p=n.settings,q=p.flex,l-=b<c-1?j:0,q>0&&(k+=q,o[A]&&N.push(n),o.flex=q),l-=o[y],r=f[J]+o[I]+f[K],r>w&&(w=r);if(
u={},l<0?u[y]=e[y]-l+e[D]:u[y]=e[C]-l+e[D],u[I]=w+e[L],u[E]=e[C]-l,u[M]=w,u.minW=P(u.minW,e.maxW),u.minH=P(u.minH,e.maxH),u.minW=O(u.minW,e.startMinWidth),u.minH=O(u.minH,e.startMinHeight),!e.autoResize||u.minW==e.minW&&u.minH==e.minH){for(t=l/k,b=0,c=N.length;b<c;b++)n=N[b],o=n.layoutRect(),s=o[A],r=o[y]+o.flex*t,r>s?(l-=o[A]-o[y],k-=o.flex,o.flex=0,o.maxFlexSize=s):o.maxFlexSize=0;for(t=l/k,v=f[B],u={},0===k&&("end"==i?v=l+f[B]:"center"==i?(v=Math.round(e[C]/2-(e[C]-l)/2)+f[B],v<0&&(v=f[B])):"justify"==i&&(v=f[B],j=Math.floor(l/(d.length-1)))),u[F]=f[J],b=0,c=d.length;b<c;b++)n=d[b],o=n.layoutRect(),r=o.maxFlexSize||o[y],"center"===h?u[F]=Math.round(e[G]/2-o[H]/2):"stretch"===h?(u[H]=O(o[I]||0,e[G]-f[J]-f[K]),u[F]=f[J]):"end"===h&&(u[F]=e[G]-o[H]-f.top),o.flex>0&&(r+=o.flex*t),u[x]=r,u[z]=v,n.layoutRect(u),n.recalc&&n.recalc(),v+=r+j}else if(u.w=u.m
inW,u.h=u.minH,a.layoutRect(u),this.recalc(a),null===a._lastRect){var Q=a.parent();Q&&(Q._lastRect=null,Q.recalc())}}})}),g("35",["2n"],function(a){return a.extend({Defaults:{containerClass:"flow-layout",controlClass:"flow-layout-item",endClass:"break"},recalc:function(a){a.items().filter(":visible").each(function(a){a.recalc&&a.recalc()})},isNative:function(){return!0}})}),g("4g",["e"],function(a){var b=function(a,b,c){for(;c!==b;){if(c.style[a])return c.style[a];c=c.parentNode}return""},c=function(a){return/[0-9.]+px$/.test(a)?Math.round(72*parseInt(a,10)/96)+"pt":a},d=function(a){return a.replace(/[\'\"]/g,"").replace(/,\s+/g,",")},e=function(b,c){return a.DOM.getStyle(c,b,!0)},f=function(a,c){var d=b("fontSize",a,c);return""!==d?d:e("fontSize",c)},g=function(a,c){var f=b("fontFamily",a,c),g="&quo
t;!==f?f:e("fontFamily",c);return void 0!==g?d(g):""};return{getFontSize:f,getFontFamily:g,toPt:c}}),g("36",["2a","2l","2j","9","1g","e","17","6","4g"],function(a,b,c,d,e,f,g,h,i){function j(a){a.settings.ui_container&&(h.container=f.DOM.select(a.settings.ui_container)[0])}function k(b){b.on("ScriptsLoaded",function(){b.rtl&&(a.rtl=!0)})}function l(a){function b(b,c){return function(){var d=this;a.on("nodeChange",function(e){var f=a.formatter,g=null;m(e.parents,function(a){if(m(b,function(b){if(c?f.matchNode(a,c,{value:b.value})&&(g=b.value):f.matchNode(a,b.value)&&(g=b.value),g)return!1}),g)return!1}),d.value(g)})}}function e(b){return function(){var c=this,d=function(a){return a?a.split(",")[0]:""};a.on("nodeChange",function(e){var f,g=null;f=i.getFontFamily(a.getBody(),e.element),m
(b,function(a){a.value.toLowerCase()===f.toLowerCase()&&(g=a.value)}),m(b,function(a){g||d(a.value).toLowerCase()!==d(f).toLowerCase()||(g=a.value)}),c.value(g),!g&&f&&c.text(d(f))})}}function f(b){return function(){var c=this;a.on("nodeChange",function(d){var e,f,g=null;e=i.getFontSize(a.getBody(),d.element),f=i.toPt(e),m(b,function(a){a.value===e?g=e:a.value===f&&(g=f)}),c.value(g),g||c.text(f)})}}function g(a){a=a.replace(/;$/,"").split(";");for(var b=a.length;b--;)a[b]=a[b].split("=");return a}function h(){function b(a){var c=[];if(a)return m(a,function(a){var f={text:a.title,icon:a.icon};if(a.items)f.menu=b(a.items);else{var g=a.format||"custom"+d++;a.format||(a.name=g,e.push(a)),f.format=g,f.cmd=a.cmd}c.push(f)}),c}function c(){var c;return c=b(a.settings.style_formats_merge?a.settings.style_formats?f.concat(a.settings.style_formats):f:a.settings.style_formats||f)}var d=0,e=[],f=[{title:"Hea
dings",items:[{title:"Heading 1",format:"h1"},{title:"Heading 2",format:"h2"},{title:"Heading 3",format:"h3"},{title:"Heading 4",format:"h4"},{title:"Heading 5",format:"h5"},{title:"Heading 6",format:"h6"}]},{title:"Inline",items:[{title:"Bold",icon:"bold",format:"bold"},{title:"Italic",icon:"italic",format:"italic"},{title:"Underline",icon:"underline",format:"underline"},{title:"Strikethrough",icon:"strikethrough",format:"strikethrough"},{title:"Superscript",icon:"superscript",format:"superscript"},{title:"Subscript",icon:"subscript",format:"subscript"},{title:"Code",icon:"code",format:"code"}]},{title:"Blocks",items:[{title:"Pa
ragraph",format:"p"},{title:"Blockquote",format:"blockquote"},{title:"Div",format:"div"},{title:"Pre",format:"pre"}]},{title:"Alignment",items:[{title:"Left",icon:"alignleft",format:"alignleft"},{title:"Center",icon:"aligncenter",format:"aligncenter"},{title:"Right",icon:"alignright",format:"alignright"},{title:"Justify",icon:"alignjustify",format:"alignjustify"}]}];return a.on("init",function(){m(e,function(b){a.formatter.register(b.name,b)})}),{type:"menu",items:c(),onPostRender:function(b){
+a.fire("renderFormatsMenu",{control:b.control})},itemDefaults:{preview:!0,textStyle:function(){if(this.settings.format)return a.formatter.getCssText(this.settings.format)},onPostRender:function(){var b=this;b.parent().on("show",function(){var c,d;c=b.settings.format,c&&(b.disabled(!a.formatter.canApply(c)),b.active(a.formatter.match(c))),d=b.settings.cmd,d&&b.active(a.queryCommandState(d))})},onclick:function(){this.settings.format&&o(this.settings.format),this.settings.cmd&&a.execCommand(this.settings.cmd)}}}}function j(b){return function(){var c=this;a.formatter?a.formatter.formatChanged(b,function(a){c.active(a)}):a.on("init",function(){a.formatter.formatChanged(b,function(a){c.active(a)})})}}function k(b){return function(){function c(){var c="redo"==b?"hasRedo":"hasUndo";return!!a.undoManager&&a.undoManager[c]()}var d=this;d.disabled(!c()),a.on("Undo Redo AddUndo TypingUndo C
learUndos SwitchMode",function(){d.disabled(a.readonly||!c())})}}function l(){var b=this;a.on("VisualAid",function(a){b.active(a.hasVisual)}),b.active(a.hasVisual)}function o(b){b.control&&(b=b.control.value()),b&&a.execCommand("mceToggleFormat",!1,b)}function p(b){var c=b.length;return d.each(b,function(b){b.menu&&(b.hidden=0===p(b.menu));var d=b.format;d&&(b.hidden=!a.formatter.canApply(d)),b.hidden&&c--}),c}function q(b){var c=b.items().length;return b.items().each(function(b){b.menu&&b.visible(q(b.menu)>0),!b.menu&&b.settings.menu&&b.visible(p(b.settings.menu)>0);var d=b.settings.format;d&&b.visible(a.formatter.canApply(d)),b.visible()||c--}),c}var r;r=h(),m({bold:"Bold",italic:"Italic",underline:"Underline",strikethrough:"Strikethrough",subscript:"Subscript",superscript:"Superscript"},function(b,c){a.addButton(c,{tool
tip:b,onPostRender:j(c),onclick:function(){o(c)}})}),m({outdent:["Decrease indent","Outdent"],indent:["Increase indent","Indent"],cut:["Cut","Cut"],copy:["Copy","Copy"],paste:["Paste","Paste"],help:["Help","mceHelp"],selectall:["Select all","SelectAll"],removeformat:["Clear formatting","RemoveFormat"],visualaid:["Visual aids","mceToggleVisualAid"],newdocument:["New document","mceNewDocument"]},function(b,c){a.addButton(c,{tooltip:b[0],cmd:b[1]})}),m({blockquote:["Blockquote","mceBlockQuote"],subscript:["Subscript","Subscript"],superscript:["Superscript","Superscript"],alignleft:["Align left","JustifyLeft"],aligncenter:["Align center","JustifyCenter"],alignright:["Align right",&q
uot;JustifyRight"],alignjustify:["Justify","JustifyFull"],alignnone:["No alignment","JustifyNone"]},function(b,c){a.addButton(c,{tooltip:b[0],cmd:b[1],onPostRender:j(c)})});var s=function(a){var b=a;return b.length>0&&"-"===b[0].text&&(b=b.slice(1)),b.length>0&&"-"===b[b.length-1].text&&(b=b.slice(0,b.length-1)),b},t=function(b){var c,e;if("string"==typeof b)e=b.split(" ");else if(d.isArray(b))return n(d.map(b,t));return c=d.grep(e,function(b){return"|"===b||b in a.menuItems}),d.map(c,function(b){return"|"===b?{text:"-"}:a.menuItems[b]})},u=function(b){var c=[{text:"-"}],e=d.grep(a.menuItems,function(a){return a.context===b});return d.each(e,function(a){"before"==a.separator&&c.push({text:"|"}),a.prependToContext?c.unshift(a):c.push(a),"after"==a.separator&&c.push({text:"|
"})}),c},v=function(a){return s(a.insert_button_items?t(a.insert_button_items):u("insert"))};a.addButton("undo",{tooltip:"Undo",onPostRender:k("undo"),cmd:"undo"}),a.addButton("redo",{tooltip:"Redo",onPostRender:k("redo"),cmd:"redo"}),a.addMenuItem("newdocument",{text:"New document",icon:"newdocument",cmd:"mceNewDocument"}),a.addMenuItem("undo",{text:"Undo",icon:"undo",shortcut:"Meta+Z",onPostRender:k("undo"),cmd:"undo"}),a.addMenuItem("redo",{text:"Redo",icon:"redo",shortcut:"Meta+Y",onPostRender:k("redo"),cmd:"redo"}),a.addMenuItem("visualaid",{text:"Visual aids",selectable:!0,onPostRender:l,cmd:"mceToggleVisualAid"}),a.addButton("remove",{tooltip:"Remove",icon:"remove",c
md:"Delete"}),a.addButton("insert",{type:"menubutton",icon:"insert",menu:[],oncreatemenu:function(){this.menu.add(v(a.settings)),this.menu.renderNew()}}),m({cut:["Cut","Cut","Meta+X"],copy:["Copy","Copy","Meta+C"],paste:["Paste","Paste","Meta+V"],selectall:["Select all","SelectAll","Meta+A"],bold:["Bold","Bold","Meta+B"],italic:["Italic","Italic","Meta+I"],underline:["Underline","Underline","Meta+U"],strikethrough:["Strikethrough","Strikethrough"],subscript:["Subscript","Subscript"],superscript:["Superscript","Superscript"],removeformat:["Clear formatting","RemoveFormat"]},function(b,c){a.addMenuItem(c,{text:b[0],icon:c,shortcut:b[2],cmd:b[1]})}),a.on("m
ousedown",function(){c.hideAll()}),a.addButton("styleselect",{type:"menubutton",text:"Formats",menu:r,onShowMenu:function(){a.settings.style_formats_autohide&&q(this.menu)}}),a.addButton("formatselect",function(){var c=[],d=g(a.settings.block_formats||"Paragraph=p;Heading 1=h1;Heading 2=h2;Heading 3=h3;Heading 4=h4;Heading 5=h5;Heading 6=h6;Preformatted=pre");return m(d,function(b){c.push({text:b[0],value:b[1],textStyle:function(){return a.formatter.getCssText(b[1])}})}),{type:"listbox",text:d[0][0],values:c,fixedWidth:!0,onselect:o,onPostRender:b(c)}}),a.addButton("fontselect",function(){var b="Andale Mono=andale mono,monospace;Arial=arial,helvetica,sans-serif;Arial Black=arial black,sans-serif;Book Antiqua=book antiqua,palatino,serif;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier,monospace;Georgia=georgia,palatino,serif;Helvetica=helvetica,arial,sans-serif;Impact=impact,
sans-serif;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco,monospace;Times New Roman=times new roman,times,serif;Trebuchet MS=trebuchet ms,geneva,sans-serif;Verdana=verdana,geneva,sans-serif;Webdings=webdings;Wingdings=wingdings,zapf dingbats",c=[],d=g(a.settings.font_formats||b);return m(d,function(a){c.push({text:{raw:a[0]},value:a[1],textStyle:a[1].indexOf("dings")==-1?"font-family:"+a[1]:""})}),{type:"listbox",text:"Font Family",tooltip:"Font Family",values:c,fixedWidth:!0,onPostRender:e(c),onselect:function(b){b.control.settings.value&&a.execCommand("FontName",!1,b.control.settings.value)}}}),a.addButton("fontsizeselect",function(){var b=[],c="8pt 10pt 12pt 14pt 18pt 24pt 36pt",d=a.settings.fontsizeFormats||c;return m(d.split(" "),function(a){var c=a,d=a,e=a.split("=");e.length>1&&(c=e[0],d=e[1]),b.push({text:c,val
ue:d})}),{type:"listbox",text:"Font Sizes",tooltip:"Font Sizes",values:b,fixedWidth:!0,onPostRender:f(b),onclick:function(b){b.control.settings.value&&a.execCommand("FontSize",!1,b.control.settings.value)}}}),a.addMenuItem("formats",{text:"Formats",menu:r})}var m=d.each,n=function(a){return e.reduce(a,function(a,b){return a.concat(b)},[])};return g.on("AddEditor",function(a){var b=a.editor;k(b),l(b),j(b)}),a.translate=function(a){return g.translate(a)},b.tooltips=!h.iOS,{}}),g("37",["2o"],function(a){"use strict";return a.extend({recalc:function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E=[],F=[];b=a.settings,e=a.items().filter(":visible"),f=a.layoutRect(),d=b.columns||Math.ceil(Math.sqrt(e.length)),c=Math.ceil(e.length/d),s=b.spacingH||b.spacing||0,t=b.spacingV||b.spacing||0,u=b.alignH||b.align,v=b.alignV||b.align,q=a.paddingBox,C="revers
eRows"in b?b.reverseRows:a.isRtl(),u&&"string"==typeof u&&(u=[u]),v&&"string"==typeof v&&(v=[v]);for(l=0;l<d;l++)E.push(0);for(m=0;m<c;m++)F.push(0);for(m=0;m<c;m++)for(l=0;l<d&&(k=e[m*d+l],k);l++)j=k.layoutRect(),y=j.minW,z=j.minH,E[l]=y>E[l]?y:E[l],F[m]=z>F[m]?z:F[m];for(A=f.innerW-q.left-q.right,w=0,l=0;l<d;l++)w+=E[l]+(l>0?s:0),A-=(l>0?s:0)+E[l];for(B=f.innerH-q.top-q.bottom,x=0,m=0;m<c;m++)x+=F[m]+(m>0?t:0),B-=(m>0?t:0)+F[m];if(w+=q.left+q.right,x+=q.top+q.bottom,i={},i.minW=w+(f.w-f.innerW),i.minH=x+(f.h-f.innerH),i.contentW=i.minW-f.deltaW,i.contentH=i.minH-f.deltaH,i.minW=Math.min(i.minW,f.maxW),i.minH=Math.min(i.minH,f.maxH),i.minW=Math.max(i.minW,f.startMinWidth),i.minH=Math.max(i.minH,f.startMinHeight),!f.autoResize||i.minW==f.minW&&i.minH==f.minH){f.autoResize&&(i=a.layoutRect(i),i.contentW=i.minW-f.deltaW,i.contentH=i.minH-f.deltaH);var G;G="start&qu
ot;==b.packV?0:B>0?Math.floor(B/c):0;var H=0,I=b.flexWidths;if(I)for(l=0;l<I.length;l++)H+=I[l];else H=d;var J=A/H;for(l=0;l<d;l++)E[l]+=I?I[l]*J:J;for(o=q.top,m=0;m<c;m++){for(n=q.left,h=F[m]+G,l=0;l<d&&(D=C?m*d+d-1-l:m*d+l,k=e[D],k);l++)p=k.settings,j=k.layoutRect(),g=Math.max(E[l],j.startMinWidth),j.x=n,j.y=o,r=p.alignH||(u?u[l]||u[0]:null),"center"==r?j.x=n+g/2-j.w/2:"right"==r?j.x=n+g-j.w:"stretch"==r&&(j.w=g),r=p.alignV||(v?v[l]||v[0]:null),"center"==r?j.y=o+h/2-j.h/2:"bottom"==r?j.y=o+h-j.h:"stretch"==r&&(j.h=h),k.layoutRect(j),n+=g+s,k.recalc&&k.recalc();o+=h+t}}else if(i.w=i.minW,i.h=i.minH,a.layoutRect(i),this.recalc(a),null===a._lastRect){var K=a.parent();K&&(K._lastRect=null,K.recalc())}}})}),g("38",["2l","5"],function(a,b){"use strict";return a.extend({renderHtml:function(){var a=this;return a.classes.add("iframe
"),a.canFocus=!1,'<iframe id="'+a._id+'" class="'+a.classes+'" tabindex="-1" src="'+(a.settings.url||"javascript:''")+'" frameborder="0"></iframe>'},src:function(a){this.getEl().src=a},html:function(a,c){var d=this,e=this.getEl().contentWindow.document.body;return e?(e.innerHTML=a,c&&c()):b.setTimeout(function(){d.html(a)}),this}})}),g("39",["2l"],function(a){"use strict";return a.extend({init:function(a){var b=this;b._super(a),b.classes.add("widget").add("infobox"),b.canFocus=!1},severity:function(a){this.classes.remove("error"),this.classes.remove("warning"),this.classes.remove("success"),this.classes.add(a)},help:function(a){this.state.set("help",a)},renderHtml:function(){var a=this,b=a.classPrefix;return'<div id="'+a._id+'" class="'+a.classes+'"><div id="'+a._id+'-body"
;>'+a.encode(a.state.get("text"))+'<button role="button" tabindex="-1"><i class="'+b+"ico "+b+'i-help"></i></button></div></div>'},bindStates:function(){var a=this;return a.state.on("change:text",function(b){a.getEl("body").firstChild.data=a.encode(b.value),a.state.get("rendered")&&a.updateLayoutRect()}),a.state.on("change:help",function(b){a.classes.toggle("has-help",b.value),a.state.get("rendered")&&a.updateLayoutRect()}),a._super()}})}),g("3a",["2l","48"],function(a,b){"use strict";return a.extend({init:function(a){var b=this;b._super(a),b.classes.add("widget").add("label"),b.canFocus=!1,a.multiline&&b.classes.add("autoscroll"),a.strong&&b.classes.add("strong")},initLayoutRect:function(){var a=this,c=a._super();if(a.setting
s.multiline){var d=b.getSize(a.getEl());d.width>c.maxW&&(c.minW=c.maxW,a.classes.add("multiline")),a.getEl().style.width=c.minW+"px",c.startMinH=c.h=c.minH=Math.min(c.maxH,b.getSize(a.getEl()).height)}return c},repaint:function(){var a=this;return a.settings.multiline||(a.getEl().style.lineHeight=a.layoutRect().h+"px"),a._super()},severity:function(a){this.classes.remove("error"),this.classes.remove("warning"),this.classes.remove("success"),this.classes.add(a)},renderHtml:function(){var a,b,c=this,d=c.settings.forId,e=c.settings.html?c.settings.html:c.encode(c.state.get("text"));return!d&&(b=c.settings.forName)&&(a=c.getRoot().find("#"+b)[0],a&&(d=a._id)),d?'<label id="'+c._id+'" class="'+c.classes+'"'+(d?' for="'+d+'"':"")+">"+e+"</label>":'<span id="'+c._id+'" class="'+c.classes+
'">'+e+"</span>"},bindStates:function(){var a=this;return a.state.on("change:text",function(b){a.innerHtml(a.encode(b.value)),a.state.get("rendered")&&a.updateLayoutRect()}),a._super()}})}),g("3b",["2d"],function(a){"use strict";return a.extend({Defaults:{role:"toolbar",layout:"flow"},init:function(a){var b=this;b._super(a),b.classes.add("toolbar")},postRender:function(){var a=this;return a.items().each(function(a){a.classes.add("toolbar-item")}),a._super()}})}),g("3c",["3b"],function(a){"use strict";return a.extend({Defaults:{role:"menubar",containerCls:"menubar",ariaRoot:!0,defaults:{type:"menubutton"}}})}),g("3d",["2p","2b","3c"],function(a,b,c){"use strict";function d(a,b){for(;a;){if(b===a)return!0;a=a.parentNode}return!1}var e=a.extend({init:functio
n(a){var b=this;b._renderOpen=!0,b._super(a),a=b.settings,b.classes.add("menubtn"),a.fixedWidth&&b.classes.add("fixed-width"),b.aria("haspopup",!0),b.state.set("menu",a.menu||b.render())},showMenu:function(a){var c,d=this;return d.menu&&d.menu.visible()&&a!==!1?d.hideMenu():(d.menu||(c=d.state.get("menu")||[],c.length?c={type:"menu",items:c}:c.type=c.type||"menu",c.renderTo?d.menu=c.parent(d).show().renderTo():d.menu=b.create(c).parent(d).renderTo(),d.fire("createmenu"),d.menu.reflow(),d.menu.on("cancel",function(a){a.control.parent()===d.menu&&(a.stopPropagation(),d.focus(),d.hideMenu())}),d.menu.on("select",function(){d.focus()}),d.menu.on("show hide",function(a){a.control==d.menu&&d.activeMenu("show"==a.type),d.aria("expanded","show"==a.type)}).fire("show")),d.menu.show(),d.menu.layoutRect({w:
d.layoutRect().w}),d.menu.moveRel(d.getEl(),d.isRtl()?["br-tr","tr-br"]:["bl-tl","tl-bl"]),void d.fire("showmenu"))},hideMenu:function(){var a=this;a.menu&&(a.menu.items().each(function(a){a.hideMenu&&a.hideMenu()}),a.menu.hide())},activeMenu:function(a){this.classes.toggle("active",a)},renderHtml:function(){var a,b=this,d=b._id,e=b.classPrefix,f=b.settings.icon,g=b.state.get("text"),h="";return a=b.settings.image,a?(f="none","string"!=typeof a&&(a=window.getSelection?a[0]:a[1]),a=" style=\"background-image: url('"+a+"')\""):a="",g&&(b.classes.add("btn-has-text"),h='<span class="'+e+'txt">'+b.encode(g)+"</span>"),f=b.settings.icon?e+"ico "+e+"i-"+f:"",b.aria("role",b.parent()instanceof c?"menuitem":"button"),'<
div id="'+d+'" class="'+b.classes+'" tabindex="-1" aria-labelledby="'+d+'"><button id="'+d+'-open" role="presentation" type="button" tabindex="-1">'+(f?'<i class="'+f+'"'+a+"></i>":"")+h+' <i class="'+e+'caret"></i></button></div>'},postRender:function(){var a=this;return a.on("click",function(b){b.control===a&&d(b.target,a.getEl())&&(a.focus(),a.showMenu(!b.aria),b.aria&&a.menu.items().filter(":visible")[0].focus())}),a.on("mouseenter",function(b){var c,d=b.control,f=a.parent();d&&f&&d instanceof e&&d.parent()==f&&(f.items().filter("MenuButton").each(function(a){a.hideMenu&&a!=d&&(a.menu&&a.menu.visible()&&(c=!0),a.hideMenu())}),c&&(d.focus(),d.showMenu()))}),a._super()},bindStates:func
tion(){var a=this;return a.state.on("change:menu",function(){a.menu&&a.menu.remove(),a.menu=null}),a._super()},remove:function(){this._super(),this.menu&&this.menu.remove()}});return e}),g("3e",["2l","2b","6","5"],function(a,b,c,d){"use strict";return a.extend({Defaults:{border:0,role:"menuitem"},init:function(a){var b,c=this;c._super(a),a=c.settings,c.classes.add("menu-item"),a.menu&&c.classes.add("menu-item-expand"),a.preview&&c.classes.add("menu-item-preview"),b=c.state.get("text"),"-"!==b&&"|"!==b||(c.classes.add("menu-item-sep"),c.aria("role","separator"),c.state.set("text","-")),a.selectable&&(c.aria("role","menuitemcheckbox"),c.classes.add("menu-item-checkbox"),a.icon="selected"),a.preview||a.selectable
||c.classes.add("menu-item-normal"),c.on("mousedown",function(a){a.preventDefault()}),a.menu&&!a.ariaHideMenu&&c.aria("haspopup",!0)},hasMenus:function(){return!!this.settings.menu},showMenu:function(){var a,c=this,d=c.settings,e=c.parent();if(e.items().each(function(a){a!==c&&a.hideMenu()}),d.menu){a=c.menu,a?a.show():(a=d.menu,a.length?a={type:"menu",items:a}:a.type=a.type||"menu",e.settings.itemDefaults&&(a.itemDefaults=e.settings.itemDefaults),a=c.menu=b.create(a).parent(c).renderTo(),a.reflow(),a.on("cancel",function(b){b.stopPropagation(),c.focus(),a.hide()}),a.on("show hide",function(a){a.control.items&&a.control.items().each(function(a){a.active(a.settings.selected)})}).fire("show"),a.on("hide",function(b){b.control===a&&c.classes.remove("selected")}),a.submenu=!0),a._parentMenu=e,a.classes.add("menu-sub");var f=a.testM
oveRel(c.getEl(),c.isRtl()?["tl-tr","bl-br","tr-tl","br-bl"]:["tr-tl","br-bl","tl-tr","bl-br"]);a.moveRel(c.getEl(),f),a.rel=f,f="menu-sub-"+f,a.classes.remove(a._lastRel).add(f),a._lastRel=f,c.classes.add("selected"),c.aria("expanded",!0)}},hideMenu:function(){var a=this;return a.menu&&(a.menu.items().each(function(a){a.hideMenu&&a.hideMenu()}),a.menu.hide(),a.aria("expanded",!1)),a},renderHtml:function(){function a(a){var b,d,e={};for(e=c.mac?{alt:"⌥",ctrl:"⌘",shift:"⇧",meta:"⌘"}:{meta:"Ctrl"},a=a.split("+"),b=0;b<a.length;b++)d=e[a[b].toLowerCase()],d&&(a[b]=d);return a.join("+")}function b(a){return a.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function d(a){var c=h.match||"";return c?a.replace(new RegExp
(b(c),"gi"),function(a){return"!mce~match["+a+"]mce~match!"}):a}function e(a){return a.replace(new RegExp(b("!mce~match["),"g"),"<b>").replace(new RegExp(b("]mce~match!"),"g"),"</b>")}var f=this,g=f._id,h=f.settings,i=f.classPrefix,j=f.state.get("text"),k=f.settings.icon,l="",m=h.shortcut,n=f.encode(h.url),o="";return k&&f.parent().classes.add("menu-has-icons"),h.image&&(l=" style=\"background-image: url('"+h.image+"')\""),m&&(m=a(m)),k=i+"ico "+i+"i-"+(f.settings.icon||"none"),o="-"!==j?'<i class="'+k+'"'+l+"></i>\xa0":"",j=e(f.encode(d(j))),n=e(f.encode(d(n))),'<div id="'+g+'" class="'+f.classes+'" tabindex="-1">'+o+("-"!==j?'<span id="'+g+'-text" cl
ass="'+i+'text">'+j+"</span>":"")+(m?'<div id="'+g+'-shortcut" class="'+i+'menu-shortcut">'+m+"</div>":"")+(h.menu?'<div class="'+i+'caret"></div>':"")+(n?'<div class="'+i+'menu-item-link">'+n+"</div>":"")+"</div>"},postRender:function(){var a=this,b=a.settings,c=b.textStyle;if("function"==typeof c&&(c=c.call(this)),c){var e=a.getEl("text");e&&e.setAttribute("style",c)}return a.on("mouseenter click",function(c){c.control===a&&(b.menu||"click"!==c.type?(a.showMenu(),c.aria&&a.menu.focus(!0)):(a.fire("select"),d.requestAnimationFrame(function(){a.parent().hideAll()})))}),a._super(),a},hover:function(){var a=this;return a.parent().items().each(function(a){a.classes.remove("selected")}),a.classes.toggle("
;selected",!0),a},active:function(a){return"undefined"!=typeof a&&this.aria("checked",a),this._super(a)},remove:function(){this._super(),this.menu&&this.menu.remove()}})}),g("3f",["a","2a","5"],function(a,b,c){"use strict";return function(d,e){var f,g,h=this,i=b.classPrefix;h.show=function(b,j){function k(){f&&(a(d).append('<div class="'+i+"throbber"+(e?" "+i+"throbber-inline":"")+'"></div>'),j&&j())}return h.hide(),f=!0,b?g=c.setTimeout(k,b):k(),h},h.hide=function(){var a=d.lastChild;return c.clearTimeout(g),a&&a.className.indexOf("throbber")!=-1&&a.parentNode.removeChild(a),f=!1,h}}}),g("3g",["2j","3e","3f","9"],function(a,b,c,d){"use strict";return a.extend({Defaults:{defaultType:"menuitem",border:1,layout:"stack&q
uot;,role:"application",bodyRole:"menu",ariaRoot:!0},init:function(a){var b=this;if(a.autohide=!0,a.constrainToViewport=!0,"function"==typeof a.items&&(a.itemsFactory=a.items,a.items=[]),a.itemDefaults)for(var c=a.items,e=c.length;e--;)c[e]=d.extend({},a.itemDefaults,c[e]);b._super(a),b.classes.add("menu")},repaint:function(){return this.classes.toggle("menu-align",!0),this._super(),this.getEl().style.height="",this.getEl("body").style.height="",this},cancel:function(){var a=this;a.hideAll(),a.fire("select")},load:function(){function a(){e.throbber&&(e.throbber.hide(),e.throbber=null)}var b,d,e=this;d=e.settings.itemsFactory,d&&(e.throbber||(e.throbber=new c(e.getEl("body"),!0),0===e.items().length?(e.throbber.show(),e.fire("loading")):e.throbber.show(100,function(){e.items().remove(),e.fire("loading")}),e.on("hide close",a)),e.req
uestTime=b=(new Date).getTime(),e.settings.itemsFactory(function(c){return 0===c.length?void e.hide():void(e.requestTime===b&&(e.getEl().style.width="",e.getEl("body").style.width="",a(),e.items().remove(),e.getEl("body").innerHTML="",e.add(c),e.renderNew(),e.fire("loaded")))}))},hideAll:function(){var a=this;return this.find("menuitem").exec("hideMenu"),a._super()},preRender:function(){var a=this;return a.items().each(function(b){var c=b.settings;if(c.icon||c.image||c.selectable)return a._hasIcons=!0,!1}),a.settings.itemsFactory&&a.on("postrender",function(){a.settings.itemsFactory&&a.load()}),a._super()}})}),g("3h",["3d","3g"],function(a,b){"use strict";return a.extend({init:function(a){function b(c){for(var f=0;f<c.length;f++){if(d=c[f].selected||a.value===c[f].value)return e=e||c[f].text,g.state.set("value",c[f].va
lue),!0;if(c[f].menu&&b(c[f].menu))return!0}}var c,d,e,f,g=this;g._super(a),a=g.settings,g._values=c=a.values,c&&("undefined"!=typeof a.value&&b(c),!d&&c.length>0&&(e=c[0].text,g.state.set("value",c[0].value)),g.state.set("menu",c)),g.state.set("text",a.text||e),g.classes.add("listbox"),g.on("select",function(b){var c=b.control;f&&(b.lastControl=f),a.multiple?c.active(!c.active()):g.value(b.control.value()),f=c})},bindStates:function(){function a(a,c){a instanceof b&&a.items().each(function(a){a.hasMenus()||a.active(a.value()===c)})}function c(a,b){var d;if(a)for(var e=0;e<a.length;e++){if(a[e].value===b)return a[e];if(a[e].menu&&(d=c(a[e].menu,b)))return d}}var d=this;return d.on("show",function(b){a(b.control,d.value())}),d.state.on("change:value",function(a){var b=c(d.state.get("menu"),a.value);b?d.text(b.text):d.text(d.se
ttings.text)}),d._super()}})}),g("3i",["2r"],function(a){"use strict";return a.extend({Defaults:{classes:"radio",role:"radio"}})}),g("3j",["2l","2e"],function(a,b){"use strict";return a.extend({renderHtml:function(){var a=this,b=a.classPrefix;return a.classes.add("resizehandle"),"both"==a.settings.direction&&a.classes.add("resizehandle-both"),a.canFocus=!1,'<div id="'+a._id+'" class="'+a.classes+'"><i class="'+b+"ico "+b+'i-resize"></i></div>'},postRender:function(){var a=this;a._super(),a.resizeDragHelper=new b(this._id,{start:function(){a.fire("ResizeStart")},drag:function(b){"both"!=a.settings.direction&&(b.deltaX=0),a.fire("Resize",b)},stop:function(){a.fire("ResizeEnd")}})},remove:function(){return this.resizeDragHelper&&this.resizeDr
agHelper.destroy(),this._super()}})}),g("3k",["2l"],function(a){"use strict";function b(a){var b="";if(a)for(var c=0;c<a.length;c++)b+='<option value="'+a[c]+'">'+a[c]+"</option>";return b}return a.extend({Defaults:{classes:"selectbox",role:"selectbox",options:[]},init:function(a){var b=this;b._super(a),b.settings.size&&(b.size=b.settings.size),b.settings.options&&(b._options=b.settings.options),b.on("keydown",function(a){var c;13==a.keyCode&&(a.preventDefault(),b.parents().reverse().each(function(a){if(a.toJSON)return c=a,!1}),b.fire("submit",{data:c.toJSON()}))})},options:function(a){return arguments.length?(this.state.set("options",a),this):this.state.get("options")},renderHtml:function(){var a,c=this,d="";return a=b(c._options),c.size&&(d=' size = "'+c.size+'"'),'<select id="'+c._id+'&qu
ot; class="'+c.classes+'"'+d+">"+a+"</select>"},bindStates:function(){var a=this;return a.state.on("change:options",function(c){a.getEl().innerHTML=b(c.value)}),a._super()}})}),g("3l",["2l","2e","48"],function(a,b,c){"use strict";function d(a,b,c){return a<b&&(a=b),a>c&&(a=c),a}function e(a,b,c){a.setAttribute("aria-"+b,c)}function f(a,b){var d,f,g,h,i,j;"v"==a.settings.orientation?(h="top",g="height",f="h"):(h="left",g="width",f="w"),j=a.getEl("handle"),d=(a.layoutRect()[f]||100)-c.getSize(j)[g],i=d*((b-a._minValue)/(a._maxValue-a._minValue))+"px",j.style[h]=i,j.style.height=a.layoutRect().h+"px",e(j,"valuenow",b),e(j,"valuetext",""+a.settings.previewFilter(b)),e(j,"valuemin",a._minValue),e(j,"valuemax",a.
_maxValue)}return a.extend({init:function(a){var b=this;a.previewFilter||(a.previewFilter=function(a){return Math.round(100*a)/100}),b._super(a),b.classes.add("slider"),"v"==a.orientation&&b.classes.add("vertical"),b._minValue=a.minValue||0,b._maxValue=a.maxValue||100,b._initValue=b.state.get("value")},renderHtml:function(){var a=this,b=a._id,c=a.classPrefix;return'<div id="'+b+'" class="'+a.classes+'"><div id="'+b+'-handle" class="'+c+'slider-handle" role="slider" tabindex="-1"></div></div>'},reset:function(){this.value(this._initValue).repaint()},postRender:function(){function a(a,b,c){return(c+a)/(b-a)}function e(a,b,c){return c*(b-a)-a}function f(b,c){function f(f){var g;g=n.value(),g=e(b,c,a(b,c,g)+.05*f),g=d(g,b,c),n.value(g),n.fire("dragstart",{value:g}),n.fire("drag",{value:g}),n.fire("dragend",{value:g})}n.on("
;keydown",function(a){switch(a.keyCode){case 37:case 38:f(-1);break;case 39:case 40:f(1)}})}function g(a,e,f){var g,h,i,o,p;n._dragHelper=new b(n._id,{handle:n._id+"-handle",start:function(a){g=a[j],h=parseInt(n.getEl("handle").style[k],10),i=(n.layoutRect()[m]||100)-c.getSize(f)[l],n.fire("dragstart",{value:p})},drag:function(b){var c=b[j]-g;o=d(h+c,0,i),f.style[k]=o+"px",p=a+o/i*(e-a),n.value(p),n.tooltip().text(""+n.settings.previewFilter(p)).show().moveRel(f,"bc tc"),n.fire("drag",{value:p})},stop:function(){n.tooltip().hide(),n.fire("dragend",{value:p})}})}var h,i,j,k,l,m,n=this;h=n._minValue,i=n._maxValue,"v"==n.settings.orientation?(j="screenY",k="top",l="height",m="h"):(j="screenX",k="left",l="width",m="w"),n._super(),f(h,i,n.getEl("handle")),g(h,i,n.getEl("handle"))},repaint:functio
n(){this._super(),f(this,this.value())},bindStates:function(){var a=this;return a.state.on("change:value",function(b){f(a,b.value)}),a._super()}})}),g("3m",["2l"],function(a){"use strict";return a.extend({renderHtml:function(){var a=this;return a.classes.add("spacer"),a.canFocus=!1,'<div id="'+a._id+'" class="'+a.classes+'"></div>'}})}),g("3n",["3d","48","a"],function(a,b,c){return a.extend({Defaults:{classes:"widget btn splitbtn",role:"button"},repaint:function(){var a,d,e=this,f=e.getEl(),g=e.layoutRect();return e._super(),a=f.firstChild,d=f.lastChild,c(a).css({width:g.w-b.getSize(d).width,height:g.h-2}),c(d).css({height:g.h-2}),e},activeMenu:function(a){var b=this;c(b.getEl().lastChild).toggleClass(b.classPrefix+"active",a)},renderHtml:function(){var a,b=this,c=b._id,d=b.classPrefix,e=b.state.get("icon"),f=b.state.get(&q
uot;text"),g="";return a=b.settings.image,a?(e="none","string"!=typeof a&&(a=window.getSelection?a[0]:a[1]),a=" style=\"background-image: url('"+a+"')\""):a="",e=b.settings.icon?d+"ico "+d+"i-"+e:"",f&&(b.classes.add("btn-has-text"),g='<span class="'+d+'txt">'+b.encode(f)+"</span>"),'<div id="'+c+'" class="'+b.classes+'" role="button" tabindex="-1"><button type="button" hidefocus="1" tabindex="-1">'+(e?'<i class="'+e+'"'+a+"></i>":"")+g+'</button><button type="button" class="'+d+'open" hidefocus="1" tabindex="-1">'+(b._menuBtnText?(e?"\xa0":"")+b._menuBtnText:"")+' <i class="'+d+'caret"></i></but
ton></div>'},postRender:function(){var a=this,b=a.settings.onclick;return a.on("click",function(a){var c=a.target;if(a.control==this)for(;c;){if(a.aria&&"down"!=a.aria.key||"BUTTON"==c.nodeName&&c.className.indexOf("open")==-1)return a.stopImmediatePropagation(),void(b&&b.call(this,a));c=c.parentNode}}),delete a.settings.onclick,a._super()}})}),g("3o",["35"],function(a){"use strict";return a.extend({Defaults:{containerClass:"stack-layout",controlClass:"stack-layout-item",endClass:"break"},isNative:function(){return!0}})}),g("3p",["2g","a","48"],function(a,b,c){"use strict";return a.extend({Defaults:{layout:"absolute",defaults:{type:"panel"}},activateTab:function(a){var c;this.activeTabId&&(c=this.getEl(this.activeTabId),b(c).removeClass(this.classPrefix+"active"),c.
setAttribute("aria-selected","false")),this.activeTabId="t"+a,c=this.getEl("t"+a),c.setAttribute("aria-selected","true"),b(c).addClass(this.classPrefix+"active"),this.items()[a].show().fire("showtab"),this.reflow(),this.items().each(function(b,c){a!=c&&b.hide()})},renderHtml:function(){var a=this,b=a._layout,c="",d=a.classPrefix;return a.preRender(),b.preRender(a),a.items().each(function(b,e){var f=a._id+"-t"+e;b.aria("role","tabpanel"),b.aria("labelledby",f),c+='<div id="'+f+'" class="'+d+'tab" unselectable="on" role="tab" aria-controls="'+b._id+'" aria-selected="false" tabIndex="-1">'+a.encode(b.settings.title)+"</div>"}),'<div id="'+a._id+'" class="'+a.classes+'" hidefocus="1" tabindex="-1"><div id="'
+a._id+'-head" class="'+d+'tabs" role="tablist">'+c+'</div><div id="'+a._id+'-body" class="'+a.bodyClasses+'">'+b.renderHtml(a)+"</div></div>"},postRender:function(){var a=this;a._super(),a.settings.activeTab=a.settings.activeTab||0,a.activateTab(a.settings.activeTab),this.on("click",function(b){var c=b.target.parentNode;if(c&&c.id==a._id+"-head")for(var d=c.childNodes.length;d--;)c.childNodes[d]==b.target&&a.activateTab(d)})},initLayoutRect:function(){var a,b,d,e=this;b=c.getSize(e.getEl("head")).width,b=b<0?0:b,d=0,e.items().each(function(a){b=Math.max(b,a.layoutRect().minW),d=Math.max(d,a.layoutRect().minH)}),e.items().each(function(a){a.settings.x=0,a.settings.y=0,a.settings.w=b,a.settings.h=d,a.layoutRect({x:0,y:0,w:b,h:d})});var f=c.getSize(e.getEl("head")).height;return e.settings.minWidth=b,e.settings.minHeight=d+f,a=e._super(),a.deltaH
+=f,a.innerH=a.h-a.deltaH,a}})}),g("3q",["2l","9","48"],function(a,b,c){return a.extend({init:function(a){var b=this;b._super(a),b.classes.add("textbox"),a.multiline?b.classes.add("multiline"):(b.on("keydown",function(a){var c;13==a.keyCode&&(a.preventDefault(),b.parents().reverse().each(function(a){if(a.toJSON)return c=a,!1}),b.fire("submit",{data:c.toJSON()}))}),b.on("keyup",function(a){b.state.set("value",a.target.value)}))},repaint:function(){var a,b,c,d,e,f=this,g=0;a=f.getEl().style,b=f._layoutRect,e=f._lastRepaintRect||{};var h=document;return!f.settings.multiline&&h.all&&(!h.documentMode||h.documentMode<=8)&&(a.lineHeight=b.h-g+"px"),c=f.borderBox,d=c.left+c.right+8,g=c.top+c.bottom+(f.settings.multiline?8:0),b.x!==e.x&&(a.left=b.x+"px",e.x=b.x),b.y!==e.y&&(a.top=b.y+"px",e.y=b.y),b.w!==e.w&&a
mp;(a.width=b.w-d+"px",e.w=b.w),b.h!==e.h&&(a.height=b.h-g+"px",e.h=b.h),f._lastRepaintRect=e,f.fire("repaint",{},!1),f},renderHtml:function(){var a,d,e=this,f=e.settings;return a={id:e._id,hidefocus:"1"},b.each(["rows","spellcheck","maxLength","size","readonly","min","max","step","list","pattern","placeholder","required","multiple"],function(b){a[b]=f[b]}),e.disabled()&&(a.disabled="disabled"),f.subtype&&(a.type=f.subtype),d=c.create(f.multiline?"textarea":"input",a),d.value=e.state.get("value"),d.className=e.classes,d.outerHTML},value:function(a){return arguments.length?(this.state.set("value",a),this):(this.state.get("rendered")&&this.state.set("value",this.getEl().value),this.state.get("value"))},postR
ender:function(){var a=this;a.getEl().value=a.state.get("value"),a._super(),a.$el.on("change",function(b){a.state.set("value",b.target.value),a.fire("change",b)})},bindStates:function(){var a=this;return a.state.on("change:value",function(b){a.getEl().value!=b.value&&(a.getEl().value=b.value)}),a.state.on("change:disabled",function(b){a.getEl().disabled=b.value}),a._super()},remove:function(){this.$el.off(),this._super()}})}),g("1f",["27","28","29","2a","2b","2c","2d","2e","2f","2g","2h","2i","2j","1y","1z","2k","2l","2m","20","2n","2o","2p","2q","2r","2s","2t","2u","2v","2w","2x","2y","2z",&
quot;30","31","32","33","34","35","36","37","38","39","3a","3b","3c","3d","3e","3f","3g","3h","3i","3j","3k","3l","3m","3n","3o","3p","3q"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,$,_,aa,ba,ca,da,ea){"use strict";var fa=function(a,b){e.add(a.split(".").pop(),b)},ga=function(a,b,c){var d,e;for(e=b.split(/[.\/]/),d=0;d<e.length-1;++d)void 0===a[e[d]]&&(a[e[d]]={}),a=a[e[d]];a[e[e.length-1]]=c,fa(b,c)},ha=function(fa){ga(fa,"ui.Selector",a),ga(fa,"ui.Collection",b),ga(fa,"ui.ReflowQueue",c),ga(fa,"ui.Control",d),ga(fa,"ui.Factory",e),ga(fa,"ui.KeyboardNavigation",f
),ga(fa,"ui.Container",g),ga(fa,"ui.DragHelper",h),ga(fa,"ui.Scrollable",i),ga(fa,"ui.Panel",j),ga(fa,"ui.Movable",k),ga(fa,"ui.Resizable",l),ga(fa,"ui.FloatPanel",m),ga(fa,"ui.Window",n),ga(fa,"ui.MessageBox",o),ga(fa,"ui.Tooltip",p),ga(fa,"ui.Widget",q),ga(fa,"ui.Progress",r),ga(fa,"ui.Notification",s),ga(fa,"ui.Layout",t),ga(fa,"ui.AbsoluteLayout",u),ga(fa,"ui.Button",v),ga(fa,"ui.ButtonGroup",w),ga(fa,"ui.Checkbox",x),ga(fa,"ui.ComboBox",y),ga(fa,"ui.ColorBox",z),ga(fa,"ui.PanelButton",A),
+ga(fa,"ui.ColorButton",B),ga(fa,"ui.ColorPicker",C),ga(fa,"ui.Path",D),ga(fa,"ui.ElementPath",E),ga(fa,"ui.FormItem",F),ga(fa,"ui.Form",G),ga(fa,"ui.FieldSet",H),ga(fa,"ui.FilePicker",I),ga(fa,"ui.FitLayout",J),ga(fa,"ui.FlexLayout",K),ga(fa,"ui.FlowLayout",L),ga(fa,"ui.FormatControls",M),ga(fa,"ui.GridLayout",N),ga(fa,"ui.Iframe",O),ga(fa,"ui.InfoBox",P),ga(fa,"ui.Label",Q),ga(fa,"ui.Toolbar",R),ga(fa,"ui.MenuBar",S),ga(fa,"ui.MenuButton",T),ga(fa,"ui.MenuItem",U),ga(fa,"ui.Throbber",V),ga(fa,"ui.Menu",W),ga(fa,"ui.ListBox",X),ga(fa,"ui.Radio",Y),ga(fa,"ui.ResizeHandle",Z),ga(fa,"ui.SelectBox",$),ga(fa,"ui.Slider",_),ga(fa,"ui.Spacer",aa),ga(fa,"ui.SplitButton",ba),ga(fa,"ui.StackLayout"
,ca),ga(fa,"ui.TabPanel",da),ga(fa,"ui.TextBox",ea),ga(fa,"ui.Api",ia)},ia={appendTo:ha};return ia}),g("1",["3","4","5","6","7","8","9","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W){var X=O,Y=function(a,b,c){var d,e;for(
e=b.split(/[.\/]/),d=0;d<e.length-1;++d)void 0===a[e[d]]&&(a[e[d]]={}),a=a[e[d]];a[e[e.length-1]]=c};return Y(X,"geom.Rect",a),Y(X,"util.Promise",b),Y(X,"util.Delay",c),Y(X,"Env",d),Y(X,"dom.EventUtils",e),Y(X,"dom.Sizzle",f),Y(X,"util.Tools",g),Y(X,"dom.DomQuery",h),Y(X,"html.Styles",i),Y(X,"dom.TreeWalker",j),Y(X,"html.Entities",k),Y(X,"dom.DOMUtils",l),Y(X,"dom.ScriptLoader",m),Y(X,"AddOnManager",n),Y(X,"dom.RangeUtils",o),Y(X,"html.Node",p),Y(X,"html.Schema",q),Y(X,"html.SaxParser",r),Y(X,"html.DomParser",s),Y(X,"html.Writer",t),Y(X,"html.Serializer",u),Y(X,"dom.Serializer",v),Y(X,"util.VK",w),Y(X,"dom.ControlSelection",x),Y(X,"dom.BookmarkManager",y),Y(X,"dom.Selection",z),Y(X,"Formatter",A),Y(X,"
UndoManager",B),Y(X,"EditorCommands",C),Y(X,"util.URI",D),Y(X,"util.Class",E),Y(X,"util.EventDispatcher",F),Y(X,"util.Observable",G),Y(X,"WindowManager",H),Y(X,"NotificationManager",I),Y(X,"EditorObservable",J),Y(X,"Shortcuts",K),Y(X,"Editor",L),Y(X,"util.I18n",M),Y(X,"FocusManager",N),Y(X,"EditorManager",O),Y(X,"util.XHR",P),Y(X,"util.JSON",Q),Y(X,"util.JSONRequest",R),Y(X,"util.JSONP",S),Y(X,"util.LocalStorage",T),Y(X,"Compat",U),Y(X,"util.Color",V),W.appendTo(X),U.register(X),X}),g("2",[],function(){var a=this||window,b=function(b){"function"==typeof a.define&&(a.define.amd||(a.define("ephox/tinymce",[],function(){return b}),a.define("17",[],function(){return b}))),"object"==typeof module&&(module.exports=b)};retu
rn{exposeToModuleLoaders:b}}),g("0",["1","2"],function(a,b){return function(){return window.tinymce=a,window.tinyMCE=a,b.exposeToModuleLoaders(a),a}}),d("0")()}();
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymceutilseditable_selectsjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/utils/editable_selects.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/utils/editable_selects.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/utils/editable_selects.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2,69 +2,71 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * editable_selects.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> var TinyMCE_EditableSelects = {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- editSelectElm : null,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ editSelectElm : null,
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- init : function() {
- var nl = document.getElementsByTagName("select"), i, d = document, o;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ init : function () {
+ var nl = document.getElementsByTagName("select"), i, d = document, o;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i=0; i<nl.length; i++) {
- if (nl[i].className.indexOf('mceEditableSelect') != -1) {
- o = new Option(tinyMCEPopup.editor.translate('value'), '__mce_add_custom__');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0; i < nl.length; i++) {
+ if (nl[i].className.indexOf('mceEditableSelect') != -1) {
+ o = new Option(tinyMCEPopup.editor.translate('value'), '__mce_add_custom__');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- o.className = 'mceAddSelectValue';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ o.className = 'mceAddSelectValue';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- nl[i].options[nl[i].options.length] = o;
- nl[i].onchange = TinyMCE_EditableSelects.onChangeEditableSelect;
- }
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ nl[i].options[nl[i].options.length] = o;
+ nl[i].onchange = TinyMCE_EditableSelects.onChangeEditableSelect;
+ }
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- onChangeEditableSelect : function(e) {
- var d = document, ne, se = window.event ? window.event.srcElement : e.target;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ onChangeEditableSelect : function (e) {
+ var d = document, ne, se = window.event ? window.event.srcElement : e.target;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (se.options[se.selectedIndex].value == '__mce_add_custom__') {
- ne = d.createElement("input");
- ne.id = se.id + "_custom";
- ne.name = se.name + "_custom";
- ne.type = "text";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (se.options[se.selectedIndex].value == '__mce_add_custom__') {
+ ne = d.createElement("input");
+ ne.id = se.id + "_custom";
+ ne.name = se.name + "_custom";
+ ne.type = "text";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- ne.style.width = se.offsetWidth + 'px';
- se.parentNode.insertBefore(ne, se);
- se.style.display = 'none';
- ne.focus();
- ne.onblur = TinyMCE_EditableSelects.onBlurEditableSelectInput;
- ne.onkeydown = TinyMCE_EditableSelects.onKeyDown;
- TinyMCE_EditableSelects.editSelectElm = se;
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ne.style.width = se.offsetWidth + 'px';
+ se.parentNode.insertBefore(ne, se);
+ se.style.display = 'none';
+ ne.focus();
+ ne.onblur = TinyMCE_EditableSelects.onBlurEditableSelectInput;
+ ne.onkeydown = TinyMCE_EditableSelects.onKeyDown;
+ TinyMCE_EditableSelects.editSelectElm = se;
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- onBlurEditableSelectInput : function() {
- var se = TinyMCE_EditableSelects.editSelectElm;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ onBlurEditableSelectInput : function () {
+ var se = TinyMCE_EditableSelects.editSelectElm;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (se) {
- if (se.previousSibling.value != '') {
- addSelectValue(document.forms[0], se.id, se.previousSibling.value, se.previousSibling.value);
- selectByValue(document.forms[0], se.id, se.previousSibling.value);
- } else
- selectByValue(document.forms[0], se.id, '');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (se) {
+ if (se.previousSibling.value != '') {
+ addSelectValue(document.forms[0], se.id, se.previousSibling.value, se.previousSibling.value);
+ selectByValue(document.forms[0], se.id, se.previousSibling.value);
+ } else {
+ selectByValue(document.forms[0], se.id, '');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- se.style.display = 'inline';
- se.parentNode.removeChild(se.previousSibling);
- TinyMCE_EditableSelects.editSelectElm = null;
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ se.style.display = 'inline';
+ se.parentNode.removeChild(se.previousSibling);
+ TinyMCE_EditableSelects.editSelectElm = null;
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- onKeyDown : function(e) {
- e = e || window.event;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ onKeyDown : function (e) {
+ e = e || window.event;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e.keyCode == 13)
- TinyMCE_EditableSelects.onBlurEditableSelectInput();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e.keyCode == 13) {
+ TinyMCE_EditableSelects.onBlurEditableSelectInput();
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> };
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymceutilsform_utilsjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/utils/form_utils.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/utils/form_utils.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/utils/form_utils.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2,7 +2,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * form_utils.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -11,200 +11,212 @@
</span><span class="cx" style="display: block; padding: 0 10px"> var themeBaseURL = tinyMCEPopup.editor.baseURI.toAbsolute('themes/' + tinyMCEPopup.getParam("theme"));
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> function getColorPickerHTML(id, target_form_element) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var h = "", dom = tinyMCEPopup.dom;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var h = "", dom = tinyMCEPopup.dom;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (label = dom.select('label[for=' + target_form_element + ']')[0]) {
- label.id = label.id || dom.uniqueId();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (label = dom.select('label[for=' + target_form_element + ']')[0]) {
+ label.id = label.id || dom.uniqueId();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- h += '<a role="button" aria-labelledby="' + id + '_label" id="' + id + '_link" href="javascript:;" onclick="tinyMCEPopup.pickColor(event,\'' + target_form_element +'\');" onmousedown="return false;" class="pickcolor">';
- h += '<span id="' + id + '" title="' + tinyMCEPopup.getLang('browse') + '"> <span id="' + id + '_label" class="mceVoiceLabel mceIconOnly" style="display:none;">' + tinyMCEPopup.getLang('browse') + '</span></span></a>';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ h += '<a role="button" aria-labelledby="' + id + '_label" id="' + id + '_link" href="javascript:;" onclick="tinyMCEPopup.pickColor(event,\'' + target_form_element + '\');" onmousedown="return false;" class="pickcolor">';
+ h += '<span id="' + id + '" title="' + tinyMCEPopup.getLang('browse') + '"> <span id="' + id + '_label" class="mceVoiceLabel mceIconOnly" style="display:none;">' + tinyMCEPopup.getLang('browse') + '</span></span></a>';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return h;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return h;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> function updateColor(img_id, form_element_id) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- document.getElementById(img_id).style.backgroundColor = document.forms[0].elements[form_element_id].value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ document.getElementById(img_id).style.backgroundColor = document.forms[0].elements[form_element_id].value;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> function setBrowserDisabled(id, state) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var img = document.getElementById(id);
- var lnk = document.getElementById(id + "_link");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var img = document.getElementById(id);
+ var lnk = document.getElementById(id + "_link");
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (lnk) {
- if (state) {
- lnk.setAttribute("realhref", lnk.getAttribute("href"));
- lnk.removeAttribute("href");
- tinyMCEPopup.dom.addClass(img, 'disabled');
- } else {
- if (lnk.getAttribute("realhref"))
- lnk.setAttribute("href", lnk.getAttribute("realhref"));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (lnk) {
+ if (state) {
+ lnk.setAttribute("realhref", lnk.getAttribute("href"));
+ lnk.removeAttribute("href");
+ tinyMCEPopup.dom.addClass(img, 'disabled');
+ } else {
+ if (lnk.getAttribute("realhref")) {
+ lnk.setAttribute("href", lnk.getAttribute("realhref"));
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tinyMCEPopup.dom.removeClass(img, 'disabled');
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ tinyMCEPopup.dom.removeClass(img, 'disabled');
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> function getBrowserHTML(id, target_form_element, type, prefix) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var option = prefix + "_" + type + "_browser_callback", cb, html;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var option = prefix + "_" + type + "_browser_callback", cb, html;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- cb = tinyMCEPopup.getParam(option, tinyMCEPopup.getParam("file_browser_callback"));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ cb = tinyMCEPopup.getParam(option, tinyMCEPopup.getParam("file_browser_callback"));
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!cb)
- return "";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!cb) {
+ return "";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- html = "";
- html += '<a id="' + id + '_link" href="javascript:openBrowser(\'' + id + '\',\'' + target_form_element + '\', \'' + type + '\',\'' + option + '\');" onmousedown="return false;" class="browse">';
- html += '<span id="' + id + '" title="' + tinyMCEPopup.getLang('browse') + '"> </span></a>';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ html = "";
+ html += '<a id="' + id + '_link" href="javascript:openBrowser(\'' + id + '\',\'' + target_form_element + '\', \'' + type + '\',\'' + option + '\');" onmousedown="return false;" class="browse">';
+ html += '<span id="' + id + '" title="' + tinyMCEPopup.getLang('browse') + '"> </span></a>';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return html;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return html;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> function openBrowser(img_id, target_form_element, type, option) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var img = document.getElementById(img_id);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var img = document.getElementById(img_id);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (img.className != "mceButtonDisabled")
- tinyMCEPopup.openBrowser(target_form_element, type, option);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (img.className != "mceButtonDisabled") {
+ tinyMCEPopup.openBrowser(target_form_element, type, option);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> function selectByValue(form_obj, field_name, value, add_custom, ignore_case) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!form_obj || !form_obj.elements[field_name])
- return;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!form_obj || !form_obj.elements[field_name]) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!value)
- value = "";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!value) {
+ value = "";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var sel = form_obj.elements[field_name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var sel = form_obj.elements[field_name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var found = false;
- for (var i=0; i<sel.options.length; i++) {
- var option = sel.options[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var found = false;
+ for (var i = 0; i < sel.options.length; i++) {
+ var option = sel.options[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (option.value == value || (ignore_case && option.value.toLowerCase() == value.toLowerCase())) {
- option.selected = true;
- found = true;
- } else
- option.selected = false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (option.value == value || (ignore_case && option.value.toLowerCase() == value.toLowerCase())) {
+ option.selected = true;
+ found = true;
+ } else {
+ option.selected = false;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!found && add_custom && value != '') {
- var option = new Option(value, value);
- option.selected = true;
- sel.options[sel.options.length] = option;
- sel.selectedIndex = sel.options.length - 1;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!found && add_custom && value != '') {
+ var option = new Option(value, value);
+ option.selected = true;
+ sel.options[sel.options.length] = option;
+ sel.selectedIndex = sel.options.length - 1;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return found;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return found;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> function getSelectValue(form_obj, field_name) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var elm = form_obj.elements[field_name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var elm = form_obj.elements[field_name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (elm == null || elm.options == null || elm.selectedIndex === -1)
- return "";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (elm == null || elm.options == null || elm.selectedIndex === -1) {
+ return "";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return elm.options[elm.selectedIndex].value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return elm.options[elm.selectedIndex].value;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> function addSelectValue(form_obj, field_name, name, value) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var s = form_obj.elements[field_name];
- var o = new Option(name, value);
- s.options[s.options.length] = o;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var s = form_obj.elements[field_name];
+ var o = new Option(name, value);
+ s.options[s.options.length] = o;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> function addClassesToList(list_id, specific_option) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Setup class droplist
- var styleSelectElm = document.getElementById(list_id);
- var styles = tinyMCEPopup.getParam('theme_advanced_styles', false);
- styles = tinyMCEPopup.getParam(specific_option, styles);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setup class droplist
+ var styleSelectElm = document.getElementById(list_id);
+ var styles = tinyMCEPopup.getParam('theme_advanced_styles', false);
+ styles = tinyMCEPopup.getParam(specific_option, styles);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (styles) {
- var stylesAr = styles.split(';');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (styles) {
+ var stylesAr = styles.split(';');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (var i=0; i<stylesAr.length; i++) {
- if (stylesAr != "") {
- var key, value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (var i = 0; i < stylesAr.length; i++) {
+ if (stylesAr != "") {
+ var key, value;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- key = stylesAr[i].split('=')[0];
- value = stylesAr[i].split('=')[1];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ key = stylesAr[i].split('=')[0];
+ value = stylesAr[i].split('=')[1];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- styleSelectElm.options[styleSelectElm.length] = new Option(key, value);
- }
- }
- } else {
- /*tinymce.each(tinyMCEPopup.editor.dom.getClasses(), function(o) {
- styleSelectElm.options[styleSelectElm.length] = new Option(o.title || o['class'], o['class']);
- });*/
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ styleSelectElm.options[styleSelectElm.length] = new Option(key, value);
+ }
+ }
+ } else {
+ /*tinymce.each(tinyMCEPopup.editor.dom.getClasses(), function(o) {
+ styleSelectElm.options[styleSelectElm.length] = new Option(o.title || o['class'], o['class']);
+ });*/
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> function isVisible(element_id) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var elm = document.getElementById(element_id);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var elm = document.getElementById(element_id);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return elm && elm.style.display != "none";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return elm && elm.style.display != "none";
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> function convertRGBToHex(col) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var re = new RegExp("rgb\\s*\\(\\s*([0-9]+).*,\\s*([0-9]+).*,\\s*([0-9]+).*\\)", "gi");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var re = new RegExp("rgb\\s*\\(\\s*([0-9]+).*,\\s*([0-9]+).*,\\s*([0-9]+).*\\)", "gi");
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var rgb = col.replace(re, "$1,$2,$3").split(',');
- if (rgb.length == 3) {
- r = parseInt(rgb[0]).toString(16);
- g = parseInt(rgb[1]).toString(16);
- b = parseInt(rgb[2]).toString(16);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var rgb = col.replace(re, "$1,$2,$3").split(',');
+ if (rgb.length == 3) {
+ r = parseInt(rgb[0]).toString(16);
+ g = parseInt(rgb[1]).toString(16);
+ b = parseInt(rgb[2]).toString(16);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- r = r.length == 1 ? '0' + r : r;
- g = g.length == 1 ? '0' + g : g;
- b = b.length == 1 ? '0' + b : b;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ r = r.length == 1 ? '0' + r : r;
+ g = g.length == 1 ? '0' + g : g;
+ b = b.length == 1 ? '0' + b : b;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return "#" + r + g + b;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return "#" + r + g + b;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return col;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return col;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> function convertHexToRGB(col) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (col.indexOf('#') != -1) {
- col = col.replace(new RegExp('[^0-9A-F]', 'gi'), '');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (col.indexOf('#') != -1) {
+ col = col.replace(new RegExp('[^0-9A-F]', 'gi'), '');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- r = parseInt(col.substring(0, 2), 16);
- g = parseInt(col.substring(2, 4), 16);
- b = parseInt(col.substring(4, 6), 16);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ r = parseInt(col.substring(0, 2), 16);
+ g = parseInt(col.substring(2, 4), 16);
+ b = parseInt(col.substring(4, 6), 16);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return "rgb(" + r + "," + g + "," + b + ")";
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return "rgb(" + r + "," + g + "," + b + ")";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return col;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return col;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> function trimSize(size) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return size.replace(/([0-9\.]+)(px|%|in|cm|mm|em|ex|pt|pc)/i, '$1$2');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return size.replace(/([0-9\.]+)(px|%|in|cm|mm|em|ex|pt|pc)/i, '$1$2');
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> function getCSSSize(size) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- size = trimSize(size);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ size = trimSize(size);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (size == "")
- return "";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (size == "") {
+ return "";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Add px
- if (/^[0-9]+$/.test(size))
- size += 'px';
- // Sanity check, IE doesn't like broken values
- else if (!(/^[0-9\.]+(px|%|in|cm|mm|em|ex|pt|pc)$/i.test(size)))
- return "";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Add px
+ if (/^[0-9]+$/.test(size)) {
+ size += 'px';
+ }
+ // Sanity check, IE doesn't like broken values
+ else if (!(/^[0-9\.]+(px|%|in|cm|mm|em|ex|pt|pc)$/i.test(size))) {
+ return "";
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return size;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return size;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> function getStyle(elm, attrib, style) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var val = tinyMCEPopup.dom.getAttrib(elm, attrib);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var val = tinyMCEPopup.dom.getAttrib(elm, attrib);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (val != '')
- return '' + val;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (val != '') {
+ return '' + val;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (typeof(style) == 'undefined')
- style = attrib;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (typeof (style) == 'undefined') {
+ style = attrib;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return tinyMCEPopup.dom.getStyle(elm, style);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return tinyMCEPopup.dom.getStyle(elm, style);
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymceutilsmctabsjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/utils/mctabs.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/utils/mctabs.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/utils/mctabs.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2,7 +2,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * mctabs.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -11,154 +11,158 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /*jshint globals: tinyMCEPopup */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> function MCTabs() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.settings = [];
- this.onChange = tinyMCEPopup.editor.windowManager.createInstance('tinymce.util.Dispatcher');
-};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.settings = [];
+ this.onChange = tinyMCEPopup.editor.windowManager.createInstance('tinymce.plugins.util.Dispatcher');
+}
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-MCTabs.prototype.init = function(settings) {
- this.settings = settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+MCTabs.prototype.init = function (settings) {
+ this.settings = settings;
</ins><span class="cx" style="display: block; padding: 0 10px"> };
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-MCTabs.prototype.getParam = function(name, default_value) {
- var value = null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+MCTabs.prototype.getParam = function (name, default_value) {
+ var value = null;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- value = (typeof(this.settings[name]) == "undefined") ? default_value : this.settings[name];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ value = (typeof (this.settings[name]) == "undefined") ? default_value : this.settings[name];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Fix bool values
- if (value == "true" || value == "false")
- return (value == "true");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Fix bool values
+ if (value == "true" || value == "false") {
+ return (value == "true");
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return value;
</ins><span class="cx" style="display: block; padding: 0 10px"> };
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-MCTabs.prototype.showTab =function(tab){
- tab.className = 'current';
- tab.setAttribute("aria-selected", true);
- tab.setAttribute("aria-expanded", true);
- tab.tabIndex = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+MCTabs.prototype.showTab = function (tab) {
+ tab.className = 'current';
+ tab.setAttribute("aria-selected", true);
+ tab.setAttribute("aria-expanded", true);
+ tab.tabIndex = 0;
</ins><span class="cx" style="display: block; padding: 0 10px"> };
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-MCTabs.prototype.hideTab =function(tab){
- var t=this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+MCTabs.prototype.hideTab = function (tab) {
+ var t = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tab.className = '';
- tab.setAttribute("aria-selected", false);
- tab.setAttribute("aria-expanded", false);
- tab.tabIndex = -1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ tab.className = '';
+ tab.setAttribute("aria-selected", false);
+ tab.setAttribute("aria-expanded", false);
+ tab.tabIndex = -1;
</ins><span class="cx" style="display: block; padding: 0 10px"> };
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-MCTabs.prototype.showPanel = function(panel) {
- panel.className = 'current';
- panel.setAttribute("aria-hidden", false);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+MCTabs.prototype.showPanel = function (panel) {
+ panel.className = 'current';
+ panel.setAttribute("aria-hidden", false);
</ins><span class="cx" style="display: block; padding: 0 10px"> };
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-MCTabs.prototype.hidePanel = function(panel) {
- panel.className = 'panel';
- panel.setAttribute("aria-hidden", true);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+MCTabs.prototype.hidePanel = function (panel) {
+ panel.className = 'panel';
+ panel.setAttribute("aria-hidden", true);
</ins><span class="cx" style="display: block; padding: 0 10px"> };
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-MCTabs.prototype.getPanelForTab = function(tabElm) {
- return tinyMCEPopup.dom.getAttrib(tabElm, "aria-controls");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+MCTabs.prototype.getPanelForTab = function (tabElm) {
+ return tinyMCEPopup.dom.getAttrib(tabElm, "aria-controls");
</ins><span class="cx" style="display: block; padding: 0 10px"> };
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-MCTabs.prototype.displayTab = function(tab_id, panel_id, avoid_focus) {
- var panelElm, panelContainerElm, tabElm, tabContainerElm, selectionClass, nodes, i, t = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+MCTabs.prototype.displayTab = function (tab_id, panel_id, avoid_focus) {
+ var panelElm, panelContainerElm, tabElm, tabContainerElm, selectionClass, nodes, i, t = this;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tabElm = document.getElementById(tab_id);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ tabElm = document.getElementById(tab_id);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (panel_id === undefined) {
- panel_id = t.getPanelForTab(tabElm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (panel_id === undefined) {
+ panel_id = t.getPanelForTab(tabElm);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- panelElm= document.getElementById(panel_id);
- panelContainerElm = panelElm ? panelElm.parentNode : null;
- tabContainerElm = tabElm ? tabElm.parentNode : null;
- selectionClass = t.getParam('selection_class', 'current');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ panelElm = document.getElementById(panel_id);
+ panelContainerElm = panelElm ? panelElm.parentNode : null;
+ tabContainerElm = tabElm ? tabElm.parentNode : null;
+ selectionClass = t.getParam('selection_class', 'current');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (tabElm && tabContainerElm) {
- nodes = tabContainerElm.childNodes;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (tabElm && tabContainerElm) {
+ nodes = tabContainerElm.childNodes;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Hide all other tabs
- for (i = 0; i < nodes.length; i++) {
- if (nodes[i].nodeName == "LI") {
- t.hideTab(nodes[i]);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Hide all other tabs
+ for (i = 0; i < nodes.length; i++) {
+ if (nodes[i].nodeName == "LI") {
+ t.hideTab(nodes[i]);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Show selected tab
- t.showTab(tabElm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Show selected tab
+ t.showTab(tabElm);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (panelElm && panelContainerElm) {
- nodes = panelContainerElm.childNodes;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (panelElm && panelContainerElm) {
+ nodes = panelContainerElm.childNodes;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Hide all other panels
- for (i = 0; i < nodes.length; i++) {
- if (nodes[i].nodeName == "DIV")
- t.hidePanel(nodes[i]);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Hide all other panels
+ for (i = 0; i < nodes.length; i++) {
+ if (nodes[i].nodeName == "DIV") {
+ t.hidePanel(nodes[i]);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!avoid_focus) {
- tabElm.focus();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!avoid_focus) {
+ tabElm.focus();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Show selected panel
- t.showPanel(panelElm);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Show selected panel
+ t.showPanel(panelElm);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> };
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-MCTabs.prototype.getAnchor = function() {
- var pos, url = document.location.href;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+MCTabs.prototype.getAnchor = function () {
+ var pos, url = document.location.href;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ((pos = url.lastIndexOf('#')) != -1)
- return url.substring(pos + 1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ((pos = url.lastIndexOf('#')) != -1) {
+ return url.substring(pos + 1);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return "";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return "";
</ins><span class="cx" style="display: block; padding: 0 10px"> };
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> //Global instance
</span><span class="cx" style="display: block; padding: 0 10px"> var mcTabs = new MCTabs();
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-tinyMCEPopup.onInit.add(function() {
- var tinymce = tinyMCEPopup.getWin().tinymce, dom = tinyMCEPopup.dom, each = tinymce.each;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+tinyMCEPopup.onInit.add(function () {
+ var tinymce = tinyMCEPopup.getWin().tinymce, dom = tinyMCEPopup.dom, each = tinymce.each;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(dom.select('div.tabs'), function(tabContainerElm) {
- //var keyNav;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(dom.select('div.tabs'), function (tabContainerElm) {
+ //var keyNav;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.setAttrib(tabContainerElm, "role", "tablist");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.setAttrib(tabContainerElm, "role", "tablist");
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var items = tinyMCEPopup.dom.select('li', tabContainerElm);
- var action = function(id) {
- mcTabs.displayTab(id, mcTabs.getPanelForTab(id));
- mcTabs.onChange.dispatch(id);
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var items = tinyMCEPopup.dom.select('li', tabContainerElm);
+ var action = function (id) {
+ mcTabs.displayTab(id, mcTabs.getPanelForTab(id));
+ mcTabs.onChange.dispatch(id);
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(items, function(item) {
- dom.setAttrib(item, 'role', 'tab');
- dom.bind(item, 'click', function(evt) {
- action(item.id);
- });
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(items, function (item) {
+ dom.setAttrib(item, 'role', 'tab');
+ dom.bind(item, 'click', function (evt) {
+ action(item.id);
+ });
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- dom.bind(dom.getRoot(), 'keydown', function(evt) {
- if (evt.keyCode === 9 && evt.ctrlKey && !evt.altKey) { // Tab
- //keyNav.moveFocus(evt.shiftKey ? -1 : 1);
- tinymce.dom.Event.cancel(evt);
- }
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ dom.bind(dom.getRoot(), 'keydown', function (evt) {
+ if (evt.keyCode === 9 && evt.ctrlKey && !evt.altKey) { // Tab
+ //keyNav.moveFocus(evt.shiftKey ? -1 : 1);
+ tinymce.dom.Event.cancel(evt);
+ }
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- each(dom.select('a', tabContainerElm), function(a) {
- dom.setAttrib(a, 'tabindex', '-1');
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ each(dom.select('a', tabContainerElm), function (a) {
+ dom.setAttrib(a, 'tabindex', '-1');
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /*keyNav = tinyMCEPopup.editor.windowManager.createInstance('tinymce.ui.KeyboardNavigation', {
- root: tabContainerElm,
- items: items,
- onAction: action,
- actOnFocus: true,
- enableLeftRight: true,
- enableUpDown: true
- }, tinyMCEPopup.dom);*/
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /*keyNav = tinyMCEPopup.editor.windowManager.createInstance('tinymce.plugins.ui.KeyboardNavigation', {
+ root: tabContainerElm,
+ items: items,
+ onAction: action,
+ actOnFocus: true,
+ enableLeftRight: true,
+ enableUpDown: true
+ }, tinyMCEPopup.dom);*/
+ }
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> });
</span><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjstinymceutilsvalidatejs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/tinymce/utils/validate.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/tinymce/utils/validate.js 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/js/tinymce/utils/validate.js 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2,251 +2,266 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * validate.js
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Released under LGPL License.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * License: http://www.tinymce.com/license
</span><span class="cx" style="display: block; padding: 0 10px"> * Contributing: http://www.tinymce.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // String validation:
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // String validation:
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!Validator.isEmail('myemail'))
- alert('Invalid email.');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!Validator.isEmail('myemail'))
+ alert('Invalid email.');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Form validation:
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Form validation:
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- var f = document.forms['myform'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var f = document.forms['myform'];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!Validator.isEmail(f.myemail))
- alert('Invalid email.');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!Validator.isEmail(f.myemail))
+ alert('Invalid email.');
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> var Validator = {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- isEmail : function(s) {
- return this.test(s, '^[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+@[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ isEmail : function (s) {
+ return this.test(s, '^[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+@[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- isAbsUrl : function(s) {
- return this.test(s, '^(news|telnet|nttp|file|http|ftp|https)://[-A-Za-z0-9\\.]+\\/?.*$');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ isAbsUrl : function (s) {
+ return this.test(s, '^(news|telnet|nttp|file|http|ftp|https)://[-A-Za-z0-9\\.]+\\/?.*$');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- isSize : function(s) {
- return this.test(s, '^[0-9.]+(%|in|cm|mm|em|ex|pt|pc|px)?$');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ isSize : function (s) {
+ return this.test(s, '^[0-9.]+(%|in|cm|mm|em|ex|pt|pc|px)?$');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- isId : function(s) {
- return this.test(s, '^[A-Za-z_]([A-Za-z0-9_])*$');
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ isId : function (s) {
+ return this.test(s, '^[A-Za-z_]([A-Za-z0-9_])*$');
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- isEmpty : function(s) {
- var nl, i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ isEmpty : function (s) {
+ var nl, i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (s.nodeName == 'SELECT' && s.selectedIndex < 1)
- return true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (s.nodeName == 'SELECT' && s.selectedIndex < 1) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (s.type == 'checkbox' && !s.checked)
- return true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (s.type == 'checkbox' && !s.checked) {
+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (s.type == 'radio') {
- for (i=0, nl = s.form.elements; i<nl.length; i++) {
- if (nl[i].type == "radio" && nl[i].name == s.name && nl[i].checked)
- return false;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (s.type == 'radio') {
+ for (i = 0, nl = s.form.elements; i < nl.length; i++) {
+ if (nl[i].type == "radio" && nl[i].name == s.name && nl[i].checked) {
+ return false;
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return true;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return true;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return new RegExp('^\\s*$').test(s.nodeType == 1 ? s.value : s);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return new RegExp('^\\s*$').test(s.nodeType == 1 ? s.value : s);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- isNumber : function(s, d) {
- return !isNaN(s.nodeType == 1 ? s.value : s) && (!d || !this.test(s, '^-?[0-9]*\\.[0-9]*$'));
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ isNumber : function (s, d) {
+ return !isNaN(s.nodeType == 1 ? s.value : s) && (!d || !this.test(s, '^-?[0-9]*\\.[0-9]*$'));
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- test : function(s, p) {
- s = s.nodeType == 1 ? s.value : s;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test : function (s, p) {
+ s = s.nodeType == 1 ? s.value : s;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return s == '' || new RegExp(p).test(s);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return s == '' || new RegExp(p).test(s);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> };
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> var AutoValidator = {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- settings : {
- id_cls : 'id',
- int_cls : 'int',
- url_cls : 'url',
- number_cls : 'number',
- email_cls : 'email',
- size_cls : 'size',
- required_cls : 'required',
- invalid_cls : 'invalid',
- min_cls : 'min',
- max_cls : 'max'
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ settings : {
+ id_cls : 'id',
+ int_cls : 'int',
+ url_cls : 'url',
+ number_cls : 'number',
+ email_cls : 'email',
+ size_cls : 'size',
+ required_cls : 'required',
+ invalid_cls : 'invalid',
+ min_cls : 'min',
+ max_cls : 'max'
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- init : function(s) {
- var n;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ init : function (s) {
+ var n;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (n in s)
- this.settings[n] = s[n];
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (n in s) {
+ this.settings[n] = s[n];
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- validate : function(f) {
- var i, nl, s = this.settings, c = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ validate : function (f) {
+ var i, nl, s = this.settings, c = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- nl = this.tags(f, 'label');
- for (i=0; i<nl.length; i++) {
- this.removeClass(nl[i], s.invalid_cls);
- nl[i].setAttribute('aria-invalid', false);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ nl = this.tags(f, 'label');
+ for (i = 0; i < nl.length; i++) {
+ this.removeClass(nl[i], s.invalid_cls);
+ nl[i].setAttribute('aria-invalid', false);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- c += this.validateElms(f, 'input');
- c += this.validateElms(f, 'select');
- c += this.validateElms(f, 'textarea');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ c += this.validateElms(f, 'input');
+ c += this.validateElms(f, 'select');
+ c += this.validateElms(f, 'textarea');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return c == 3;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return c == 3;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- invalidate : function(n) {
- this.mark(n.form, n);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ invalidate : function (n) {
+ this.mark(n.form, n);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- getErrorMessages : function(f) {
- var nl, i, s = this.settings, field, msg, values, messages = [], ed = tinyMCEPopup.editor;
- nl = this.tags(f, "label");
- for (i=0; i<nl.length; i++) {
- if (this.hasClass(nl[i], s.invalid_cls)) {
- field = document.getElementById(nl[i].getAttribute("for"));
- values = { field: nl[i].textContent };
- if (this.hasClass(field, s.min_cls, true)) {
- message = ed.getLang('invalid_data_min');
- values.min = this.getNum(field, s.min_cls);
- } else if (this.hasClass(field, s.number_cls)) {
- message = ed.getLang('invalid_data_number');
- } else if (this.hasClass(field, s.size_cls)) {
- message = ed.getLang('invalid_data_size');
- } else {
- message = ed.getLang('invalid_data');
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ getErrorMessages : function (f) {
+ var nl, i, s = this.settings, field, msg, values, messages = [], ed = tinyMCEPopup.editor;
+ nl = this.tags(f, "label");
+ for (i = 0; i < nl.length; i++) {
+ if (this.hasClass(nl[i], s.invalid_cls)) {
+ field = document.getElementById(nl[i].getAttribute("for"));
+ values = { field: nl[i].textContent };
+ if (this.hasClass(field, s.min_cls, true)) {
+ message = ed.getLang('invalid_data_min');
+ values.min = this.getNum(field, s.min_cls);
+ } else if (this.hasClass(field, s.number_cls)) {
+ message = ed.getLang('invalid_data_number');
+ } else if (this.hasClass(field, s.size_cls)) {
+ message = ed.getLang('invalid_data_size');
+ } else {
+ message = ed.getLang('invalid_data');
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- message = message.replace(/{\#([^}]+)\}/g, function(a, b) {
- return values[b] || '{#' + b + '}';
- });
- messages.push(message);
- }
- }
- return messages;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ message = message.replace(/{\#([^}]+)\}/g, function (a, b) {
+ return values[b] || '{#' + b + '}';
+ });
+ messages.push(message);
+ }
+ }
+ return messages;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- reset : function(e) {
- var t = ['label', 'input', 'select', 'textarea'];
- var i, j, nl, s = this.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ reset : function (e) {
+ var t = ['label', 'input', 'select', 'textarea'];
+ var i, j, nl, s = this.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (e == null)
- return;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (e == null) {
+ return;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- for (i=0; i<t.length; i++) {
- nl = this.tags(e.form ? e.form : e, t[i]);
- for (j=0; j<nl.length; j++) {
- this.removeClass(nl[j], s.invalid_cls);
- nl[j].setAttribute('aria-invalid', false);
- }
- }
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (i = 0; i < t.length; i++) {
+ nl = this.tags(e.form ? e.form : e, t[i]);
+ for (j = 0; j < nl.length; j++) {
+ this.removeClass(nl[j], s.invalid_cls);
+ nl[j].setAttribute('aria-invalid', false);
+ }
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- validateElms : function(f, e) {
- var nl, i, n, s = this.settings, st = true, va = Validator, v;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ validateElms : function (f, e) {
+ var nl, i, n, s = this.settings, st = true, va = Validator, v;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- nl = this.tags(f, e);
- for (i=0; i<nl.length; i++) {
- n = nl[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ nl = this.tags(f, e);
+ for (i = 0; i < nl.length; i++) {
+ n = nl[i];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.removeClass(n, s.invalid_cls);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.removeClass(n, s.invalid_cls);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.hasClass(n, s.required_cls) && va.isEmpty(n))
- st = this.mark(f, n);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.hasClass(n, s.required_cls) && va.isEmpty(n)) {
+ st = this.mark(f, n);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.hasClass(n, s.number_cls) && !va.isNumber(n))
- st = this.mark(f, n);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.hasClass(n, s.number_cls) && !va.isNumber(n)) {
+ st = this.mark(f, n);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.hasClass(n, s.int_cls) && !va.isNumber(n, true))
- st = this.mark(f, n);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.hasClass(n, s.int_cls) && !va.isNumber(n, true)) {
+ st = this.mark(f, n);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.hasClass(n, s.url_cls) && !va.isAbsUrl(n))
- st = this.mark(f, n);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.hasClass(n, s.url_cls) && !va.isAbsUrl(n)) {
+ st = this.mark(f, n);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.hasClass(n, s.email_cls) && !va.isEmail(n))
- st = this.mark(f, n);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.hasClass(n, s.email_cls) && !va.isEmail(n)) {
+ st = this.mark(f, n);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.hasClass(n, s.size_cls) && !va.isSize(n))
- st = this.mark(f, n);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.hasClass(n, s.size_cls) && !va.isSize(n)) {
+ st = this.mark(f, n);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.hasClass(n, s.id_cls) && !va.isId(n))
- st = this.mark(f, n);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.hasClass(n, s.id_cls) && !va.isId(n)) {
+ st = this.mark(f, n);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.hasClass(n, s.min_cls, true)) {
- v = this.getNum(n, s.min_cls);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.hasClass(n, s.min_cls, true)) {
+ v = this.getNum(n, s.min_cls);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isNaN(v) || parseInt(n.value) < parseInt(v))
- st = this.mark(f, n);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isNaN(v) || parseInt(n.value) < parseInt(v)) {
+ st = this.mark(f, n);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (this.hasClass(n, s.max_cls, true)) {
- v = this.getNum(n, s.max_cls);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (this.hasClass(n, s.max_cls, true)) {
+ v = this.getNum(n, s.max_cls);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (isNaN(v) || parseInt(n.value) > parseInt(v))
- st = this.mark(f, n);
- }
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (isNaN(v) || parseInt(n.value) > parseInt(v)) {
+ st = this.mark(f, n);
+ }
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return st;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return st;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- hasClass : function(n, c, d) {
- return new RegExp('\\b' + c + (d ? '[0-9]+' : '') + '\\b', 'g').test(n.className);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ hasClass : function (n, c, d) {
+ return new RegExp('\\b' + c + (d ? '[0-9]+' : '') + '\\b', 'g').test(n.className);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- getNum : function(n, c) {
- c = n.className.match(new RegExp('\\b' + c + '([0-9]+)\\b', 'g'))[0];
- c = c.replace(/[^0-9]/g, '');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ getNum : function (n, c) {
+ c = n.className.match(new RegExp('\\b' + c + '([0-9]+)\\b', 'g'))[0];
+ c = c.replace(/[^0-9]/g, '');
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return c;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return c;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- addClass : function(n, c, b) {
- var o = this.removeClass(n, c);
- n.className = b ? c + (o != '' ? (' ' + o) : '') : (o != '' ? (o + ' ') : '') + c;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ addClass : function (n, c, b) {
+ var o = this.removeClass(n, c);
+ n.className = b ? c + (o != '' ? (' ' + o) : '') : (o != '' ? (o + ' ') : '') + c;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- removeClass : function(n, c) {
- c = n.className.replace(new RegExp("(^|\\s+)" + c + "(\\s+|$)"), ' ');
- return n.className = c != ' ' ? c : '';
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ removeClass : function (n, c) {
+ c = n.className.replace(new RegExp("(^|\\s+)" + c + "(\\s+|$)"), ' ');
+ return n.className = c != ' ' ? c : '';
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- tags : function(f, s) {
- return f.getElementsByTagName(s);
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ tags : function (f, s) {
+ return f.getElementsByTagName(s);
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- mark : function(f, n) {
- var s = this.settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ mark : function (f, n) {
+ var s = this.settings;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- this.addClass(n, s.invalid_cls);
- n.setAttribute('aria-invalid', 'true');
- this.markLabels(f, n, s.invalid_cls);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ this.addClass(n, s.invalid_cls);
+ n.setAttribute('aria-invalid', 'true');
+ this.markLabels(f, n, s.invalid_cls);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return false;
- },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
+ },
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- markLabels : function(f, n, ic) {
- var nl, i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ markLabels : function (f, n, ic) {
+ var nl, i;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- nl = this.tags(f, "label");
- for (i=0; i<nl.length; i++) {
- if (nl[i].getAttribute("for") == n.id || nl[i].htmlFor == n.id)
- this.addClass(nl[i], ic);
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ nl = this.tags(f, "label");
+ for (i = 0; i < nl.length; i++) {
+ if (nl[i].getAttribute("for") == n.id || nl[i].htmlFor == n.id) {
+ this.addClass(nl[i], ic);
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return null;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> };
</span></span></pre></div>
<a id="trunksrcwpincludesversionphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/version.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/version.php 2017-05-08 05:00:29 UTC (rev 40582)
+++ trunk/src/wp-includes/version.php 2017-05-08 05:31:08 UTC (rev 40583)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -18,7 +18,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @global string $tinymce_version
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-$tinymce_version = '4506-20170408';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+$tinymce_version = '4600-20170506';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Holds the required PHP version
</span></span></pre>
</div>
</div>
</body>
</html>